VERP (Variable Envelope Return Path) in .NET
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 “envelope sender” or MAIL FROM) for each recipient of a message.
Bounce message processing problem
In general the hard part of bounce handling is matching up a bounce message with the undeliverable address that caused the bounce.
Mail.dll email library includes Bounce class that analyses bounced emails and extracts undeliverable Recipient address. The problem is that some bounced messages don’t contain this information or use invalid or unrecognizable format.
If the mailing software could see that a bounce resulted from an attempt to send a message to bob@example.org
, then it doesn’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.
There’s no need to process bounces with VERP
VERP solves bounce analyzing problem, by using a different return path for each email.
Consider an email send from wikipedians@wiki.net
to bob@example.org.
VERP changes the sender address to
wikipedians+bob=example.org@wiki.net
– it is still a valid email address, but it also contains information about the original recipient of the email.
If the email is bounced, bounce message comes to a unique email address (wikipedians+bob=example.org@wiki.net
) that also contains information about the undeliverable recipient address (bob@example.org
).
This way by creating catch all mailbox you can easily filter bounced email addresses.
Return-path email header
Return-path email header contains email address that delivery failures (bounces) should go to.
Return-path is added at the receiving end, from the SMTP’s “MAIL FROM” command. That’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 (“MAIL FROM”).
Proper VERP message
So how should the proper VERP message look like? Here are some points:
- It has From email header set to original sender:
wikipedians@wiki.net
. - It has To email header set to original recipient:
bob@example.org
. - It uses special, unique MAIL FROM address during SMTP conversation:
wikipedians+bob=example.org@wiki.net
. - It has Return-path email header set to this unique address (
wikipedians+bob=example.org@wiki.net
), usually as a result of setting this header with MAIL FROM value.
System.Net.Mail does not work
As Return-path header is usually replaced by “MAIL FROM” command .NET System.Net.Mail.SmtpClient class can not be used to create proper VERP messages. You can only set the from address, which System.Net.Mail will also use as the “MAIL FROM” during SMTP conversation.
Setting different Return-path does not help, as it is overridden.
Sending VERP messages in .NET
Sending VERP email messages with Mail.dll is extremely easy. You just need to use SmtpMail.CreateUsingVERP method to create SmtpMail object that can be sent using Smtp client. Simple as that:
// C# MailBuilder builder = new MailBuilder(); builder.Subject = @"Subject"; builder.Html = @"Body"; builder.From.Add(new MailBox("wikipedians@wiki.net")); builder.To.Add(new MailBox("bob@example.org")); IMail email = builder.Create(); SmtpMail smtpMail = SmtpMail.CreateUsingVERP(email); using (Smtp smtp = new Smtp()) { smtp.Connect("smtp.wiki.net"); smtp.UseBestLogin("user", "password"); smtp.SendMessage(smtpMail); smtp.Close(); }
' VB.NET Dim builder As MailBuilder = New MailBuilder() builder.Subject = "Subject" builder.Html = "Body" builder.From.Add(New MailBox("wikipedians@wiki.net")) builder.[To].Add(New MailBox("bob@example.org")) Dim email As IMail = builder.Create() Dim smtpMail As SmtpMail = SmtpMail.CreateUsingVERP(email) Using smtp As New Smtp() smtp.Connect("smtp.wiki.net") smtp.UseBestLogin("user", "password") smtp.SendMessage(smtpMail) smtp.Close() End Using
Processing bounced messages
Mail.dll email library also contains a useful tool for processing VERP addresses:
// C# VERPAddress verp = VERPAddress.Parse( "wikipedians+bob=example.org@wiki.net"); Console.WriteLine(verp.ToAddress); // "bob@example.org" Console.WriteLine(verp.FromAddress); // "wikipedians@wiki.net"
' VB.NET Dim verp As VERPAddress = VERPAddress.Parse( _ "wikipedians+bob=example.org@wiki.net") Console.WriteLine(verp.ToAddress) ' "bob@example.org" Console.WriteLine(verp.FromAddress) ' "wikipedians@wiki.net"
You need to use IMAP or POP3 component to receive bounced messages.
// C# using(Imap imap = new Imap()) { imap.Connect("imap.example.com"); // or ConnectSSL for SSL imap.Login("wikipedians@wiki.net", "password"); imap.SelectInbox(); foreach (long uid in imap.Search(Flag.Unseen)) { var eml = imap.GetMessageByUID(uid); IMail email = new MailBuilder().CreateFromEml(eml); // wikipedians+bob=example.org@wiki.net VERPAddress verp = VERPAddress.Parse(email.To[0]); Console.WriteLine(verp.ToAddress); // "bob@example.org" } imap.Close(); }
' VB.NET Using imap As New Imap() imap.Connect("imap.example.com") ' or ConnectSSL for SSL imap.Login("wikipedians@wiki.net", "password") imap.SelectInbox() For Each uid As Long In imap.Search(Flag.Unseen) Dim eml = imap.GetMessageByUID(uid) Dim email As IMail = New MailBuilder().CreateFromEml(eml) ' wikipedians+bob=example.org@wiki.net Dim verp As VERPAddress = VERPAddress.Parse(email.[To](0)) Console.WriteLine(verp.ToAddress) ' "bob@example.org" Next imap.Close() End Using
VERP drawbacks
The only drawback of this methods is, that email messages must be sent one by one. Even if the actual message is the same, “undisclosed recipients and many BCC addresses” technique can not be used.
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.
In most cases this is not a serious problem as most newsletters are personalized this days, at least with the simplest “Hi [FirstName] [LastName]” email template.
Specify ‘MAIL FROM’ address manually
Mail.dll email component is very flexible and you can always specify ‘MAIL FROM’ address directly:
// C# IMail email = ... SmtpMail smtpMail = CreateFrom(email); smtpMail.From = "wikipedians+bob=example.org@wiki.net"; using (Smtp smtp = new Smtp()) { smtp.Connect("smtp.wiki.net"); smtp.UseBestLogin("user", "password"); smtp.SendMessage(smtpMail); smtp.Close(); }
' VB.NET Dim email As IMail = ... Dim smtpMail As SmtpMail = CreateFrom(email) smtpMail.From = "wikipedians+bob=example.org@wiki.net" Using smtp As New Smtp() smtp.Connect("smtp.wiki.net") smtp.UseBestLogin("user", "password") smtp.SendMessage(smtpMail) smtp.Close() End Using
This might be useful, if you want to add additional information, besides the original recipient email address, such as mailing id.