{"id":3517,"date":"2012-11-01T09:03:19","date_gmt":"2012-11-01T07:03:19","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=3517"},"modified":"2019-03-15T17:10:14","modified_gmt":"2019-03-15T15:10:14","slug":"verp-variable-envelope-return-path-net","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/verp-variable-envelope-return-path-net","title":{"rendered":"VERP (Variable Envelope Return Path) in .NET"},"content":{"rendered":"<p>Variable Envelope Return Path (VERP) is a technique used to enable <strong>automatic detection and removal of undeliverable e-mail addresses<\/strong>. It works by using a different return path (also called &#8220;envelope sender&#8221; or MAIL FROM) for each recipient of a message.<\/p>\n<h2>Bounce message processing problem<\/h2>\n<p>In general the hard part of bounce handling is<strong> matching up a bounce message with the undeliverable address<\/strong> that caused the bounce. <\/p>\n<p>Mail.dll <a href=\"\/mail\">email library<\/a> includes <em>Bounce <\/em>class that <a href=\"\/blog\/bounce-handling\">analyses bounced emails<\/a> and extracts undeliverable Recipient address. The problem is that some bounced messages don&#8217;t contain this information or use invalid or unrecognizable format.<\/p>\n<p>If the mailing software could see that a bounce resulted from an attempt to send a message to <code>bob@example.org<\/code>, then it doesn&#8217;t need to understand the rest of the information in the bounce. It can simply count how many messages were recently sent to this email address, and how many bounces resulted, and if the proportion of bounced messages is too high, the address is removed from the list.<\/p>\n<h2>There&#8217;s no need to process bounces with VERP<\/h2>\n<p>VERP solves bounce analyzing problem, by using a <strong>different return path for each email<\/strong>. <\/p>\n<p>Consider an email send from <code>wikipedians@wiki.net<\/code> to bob@example.org. <\/p>\n<p>VERP changes the sender address to<br \/>\n<code>wikipedians+bob=example.org@wiki.net<\/code> &#8211; it is still a valid email address, but it also contains information about the original recipient of the email. <\/p>\n<p>If the email is bounced, bounce message comes to a unique email address (<code>wikipedians+bob=example.org@wiki.net<\/code>) that also <strong>contains information about the undeliverable recipient address<\/strong> (<code>bob@example.org<\/code>).<\/p>\n<p>This way by creating catch all mailbox you can easily filter bounced email addresses.<\/p>\n<h2>Return-path email header<\/h2>\n<p>Return-path email header contains email address that delivery failures (bounces) should go to. <\/p>\n<p>Return-path is added at the receiving end, from the SMTP&#8217;s &#8220;MAIL FROM&#8221; command. That&#8217;s why it is not the correct place for the VERP address, as in most cases it will be ignored and\/or overridden by real SMTP envelope sender (&#8220;MAIL FROM&#8221;). <\/p>\n<h2>Proper VERP message<\/h2>\n<p>So how should the proper VERP message look like? Here are some points:<\/p>\n<ul>\n<li>It has From email header set to <strong>original sender<\/strong>:<br \/>\n<code>wikipedians@wiki.net<\/code>.<\/li>\n<li>It has To email header set to <strong>original recipient<\/strong>:<br \/>\n<code>bob@example.org<\/code>.<\/li>\n<li>It uses special, <strong>unique MAIL FROM address<\/strong> during SMTP conversation:<br \/>\n<code>wikipedians+bob=example.org@wiki.net<\/code>.<\/li>\n<li>It has Return-path email header set to this unique address (<code>wikipedians+bob=example.org@wiki.net<\/code>), usually as a result of setting this header with MAIL FROM value.<\/li>\n<\/ul>\n<h2>System.Net.Mail does not work<\/h2>\n<p>As Return-path header is usually replaced by &#8220;MAIL FROM&#8221; command .NET <em> System.Net.Mail.SmtpClient<\/em> class <strong>can not be used to create proper VERP messages<\/strong>. You can only set the from address, which <em>System.Net.Mail<\/em> will also use as the &#8220;MAIL FROM&#8221; during SMTP conversation.<\/p>\n<p>Setting different Return-path does not help, as it is overridden.<\/p>\n<h2>Sending VERP messages in .NET<\/h2>\n<p>Sending VERP email messages with Mail.dll is extremely easy. You just need to use <em>SmtpMail.CreateUsingVERP<\/em> method to create <em>SmtpMail<\/em> object that can be sent using <em>Smtp <\/em>client. Simple as that:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/ C#\r\n\r\nMailBuilder builder = new MailBuilder();\r\nbuilder.Subject = @&quot;Subject&quot;;\r\nbuilder.Html = @&quot;Body&quot;;\r\nbuilder.From.Add(new MailBox(&quot;wikipedians@wiki.net&quot;));\r\nbuilder.To.Add(new MailBox(&quot;bob@example.org&quot;));\r\nIMail email = builder.Create();\r\n\r\nSmtpMail smtpMail = SmtpMail.CreateUsingVERP(email);\r\n\r\nusing (Smtp smtp = new Smtp())\r\n{\r\n    smtp.Connect(&quot;smtp.wiki.net&quot;);\r\n    smtp.UseBestLogin(&quot;user&quot;, &quot;password&quot;);\r\n    smtp.SendMessage(smtpMail);\r\n    smtp.Close();\r\n}\r\n<\/pre>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' VB.NET\r\n\r\nDim builder As MailBuilder = New MailBuilder()\r\nbuilder.Subject = &quot;Subject&quot;\r\nbuilder.Html = &quot;Body&quot;\r\nbuilder.From.Add(New MailBox(&quot;wikipedians@wiki.net&quot;))\r\nbuilder.&#x5B;To].Add(New MailBox(&quot;bob@example.org&quot;))\r\nDim email As IMail = builder.Create()\r\n\r\nDim smtpMail As SmtpMail = SmtpMail.CreateUsingVERP(email)\r\n\r\nUsing smtp As New Smtp()\r\n\tsmtp.Connect(&quot;smtp.wiki.net&quot;)\r\n\tsmtp.UseBestLogin(&quot;user&quot;, &quot;password&quot;)\r\n\tsmtp.SendMessage(smtpMail)\r\n\tsmtp.Close()\r\nEnd Using\r\n<\/pre>\n<h2>Processing bounced messages<\/h2>\n<p>Mail.dll <a href=\"\/mail\">email library<\/a> also contains a useful tool for processing VERP addresses:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/ C#\r\n\r\nVERPAddress verp = VERPAddress.Parse(\r\n    &quot;wikipedians+bob=example.org@wiki.net&quot;);\r\n\r\nConsole.WriteLine(verp.ToAddress);    \/\/ &quot;bob@example.org&quot;\r\nConsole.WriteLine(verp.FromAddress);  \/\/ &quot;wikipedians@wiki.net&quot;\r\n<\/pre>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' VB.NET\r\n\r\nDim verp As VERPAddress = VERPAddress.Parse( _\r\n    &quot;wikipedians+bob=example.org@wiki.net&quot;)\r\n\r\nConsole.WriteLine(verp.ToAddress)    ' &quot;bob@example.org&quot;\r\nConsole.WriteLine(verp.FromAddress)  ' &quot;wikipedians@wiki.net&quot;\r\n<\/pre>\n<p>You need to use IMAP or POP3 component to receive bounced messages. <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/ C#\r\n\r\n\r\nusing(Imap imap = new Imap())\r\n{\r\n    imap.Connect(&quot;imap.example.com&quot;);   \/\/ or ConnectSSL for SSL\r\n    imap.Login(&quot;wikipedians@wiki.net&quot;, &quot;password&quot;);\r\n\r\n    imap.SelectInbox();\r\n\r\n    foreach (long uid in imap.Search(Flag.Unseen))\r\n    {\r\n        var eml = imap.GetMessageByUID(uid);\r\n        IMail email = new MailBuilder().CreateFromEml(eml);\r\n\r\n        \/\/ wikipedians+bob=example.org@wiki.net\r\n        VERPAddress verp = VERPAddress.Parse(email.To&#x5B;0]); \r\n\r\n        Console.WriteLine(verp.ToAddress); \/\/ &quot;bob@example.org&quot;\r\n    }\r\n    imap.Close();\r\n}\r\n<\/pre>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' VB.NET\r\n\r\nUsing imap As New Imap()\r\n    imap.Connect(&quot;imap.example.com&quot;)\t' or ConnectSSL for SSL\r\n    imap.Login(&quot;wikipedians@wiki.net&quot;, &quot;password&quot;)\r\n\r\n    imap.SelectInbox()\r\n\r\n    For Each uid As Long In imap.Search(Flag.Unseen)\r\n        Dim eml = imap.GetMessageByUID(uid)\r\n\tDim email As IMail = New MailBuilder().CreateFromEml(eml)\r\n\r\n\t' wikipedians+bob=example.org@wiki.net\r\n\tDim verp As VERPAddress = VERPAddress.Parse(email.&#x5B;To](0))\r\n\r\n\tConsole.WriteLine(verp.ToAddress)\t' &quot;bob@example.org&quot;\r\n    Next\r\n    imap.Close()\r\nEnd Using\r\n<\/pre>\n<h2>VERP drawbacks<\/h2>\n<p>The only drawback of this methods is, that email messages <strong>must be sent one by one<\/strong>. Even if the actual message is the same, &#8220;undisclosed recipients and many BCC addresses&#8221; technique can not be used. <\/p>\n<p>This is because of a limitation of SMTP, which allows multiple recipient addresses to be specified in a single transaction, but only one sender address. And each VERP message must have its own unique MAIL FROM address specified during SMTP conversation.<\/p>\n<p>In most cases this is <strong>not a serious problem<\/strong> as most newsletters are <strong>personalized <\/strong>this days, at least with the simplest &#8220;Hi [FirstName] [LastName]&#8221; <a href=\"\/blog\/email-template-engine\">email template<\/a>.<\/p>\n<h2>Specify &#8216;MAIL FROM&#8217; address manually<\/h2>\n<p>Mail.dll email component is very flexible and you can always specify &#8216;MAIL FROM&#8217; address directly:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/ C#\r\n\r\nIMail email = ...\r\n\r\nSmtpMail smtpMail = CreateFrom(email);\r\nsmtpMail.From = &quot;wikipedians+bob=example.org@wiki.net&quot;;\r\n\r\nusing (Smtp smtp = new Smtp())\r\n{\r\n    smtp.Connect(&quot;smtp.wiki.net&quot;);\r\n    smtp.UseBestLogin(&quot;user&quot;, &quot;password&quot;);\r\n    smtp.SendMessage(smtpMail);\r\n    smtp.Close();\r\n}\r\n<\/pre>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' VB.NET\r\n\r\nDim email As IMail = ...\r\n\r\nDim smtpMail As SmtpMail = CreateFrom(email)\r\nsmtpMail.From = &quot;wikipedians+bob=example.org@wiki.net&quot;\r\n\r\nUsing smtp As New Smtp()\r\n\tsmtp.Connect(&quot;smtp.wiki.net&quot;)\r\n\tsmtp.UseBestLogin(&quot;user&quot;, &quot;password&quot;)\r\n\tsmtp.SendMessage(smtpMail)\r\n\tsmtp.Close()\r\nEnd Using\r\n<\/pre>\n<p>This might be useful, if you want to add additional information, besides the original recipient email address, such as mailing id.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Variable Envelope Return Path (VERP) is a technique used to enable automatic detection and removal of undeliverable e-mail addresses. It works by using a different return path (also called &#8220;envelope sender&#8221; or MAIL FROM) for each recipient of a message. Bounce message processing problem In general the hard part of bounce handling is matching up [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[87,15,50,57,88],"class_list":["post-3517","post","type-post","status-publish","format-standard","hentry","category-mail-dll","tag-bounce","tag-c","tag-smtp","tag-vb-net","tag-verp"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/3517"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=3517"}],"version-history":[{"count":45,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/3517\/revisions"}],"predecessor-version":[{"id":5487,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/3517\/revisions\/5487"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=3517"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=3517"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=3517"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}