For many email campaign applications, a critical task is to determine if an email is received by recipient or not. Parsing delivery report is a common way to get email status. The following sample demonstrates how to parse delivery-report.
Example
[Visual Basic, C#] The following example demonstrates how to parse the delivery report with EAGetMail POP3 & IMAP4 Component. To get the full samples of EAGetMail, please refer to Samples section.
[Visual Basic]
Imports EAGetMail
Public Sub ParseReport(ByVal emlFile As String)
Dim oMail As New Mail("TryIt")
oMail.Load(emlFile, False)
Dim contentType As String = oMail.Headers.GetValueOfKey("Content-Type").ToLower()
If contentType.IndexOf("multipart/report") = -1 Then
'not delivery report
Console.WriteLine("This is not a delivery report.")
Exit Sub
End If
Dim item As New HeaderItem("Content-Type", oMail.Headers.GetValueOfKey("Content-Type"))
Dim type As String = item.SubValue("report-type")
Dim recipient As String
Dim messageid As String
Dim status As String = "failed"
Dim atts() As Attachment = oMail.Attachments
If atts.Length > 0 Then
Dim att As Attachment
Dim src As String
att = atts(0)
src = System.Text.Encoding.Default.GetString(att.Content)
If String.Compare(type, "disposition-notification", True) = 0 Then
'this is a read receipt
status = "delivered"
messageid = GetHeaderValue("Original-Message-ID:", src)
recipient = GetHeaderValue("Final-Recipient:", src)
Else
'this is a delivery report
status = GetHeaderValue("Action:", src)
messageid = GetHeaderValue("Original-Message-ID:", src)
recipient = GetHeaderValue("Final-Recipient:", src)
If messageid.Length = 0 And atts.Length > 1 Then
'get message id from original headers/message
att = atts(1)
src = System.Text.Encoding.Default.GetString(att.Content)
messageid = GetHeaderValue("Message-ID:", src)
End If
End If
Else
'this delivery report doesn't contain the report attachment, parse the body text
status = "failed"
Dim src As String = oMail.TextBody
recipient = SearchFirstEmailAddr(src)
messageid = GetHeaderValue("Message-ID:", src)
End If
Dim pos As Integer = recipient.IndexOf(";")
If pos <> -1 Then
recipient = recipient.Substring(pos + 1)
End If
recipient = recipient.Trim("<>".ToCharArray())
Console.WriteLine("This is a delivery report.")
Console.WriteLine("Recipient: {0}", recipient)
Console.WriteLine("Message-ID: {0}", messageid)
Console.WriteLine("Status: {0}", status)
End Sub
Public Function GetHeaderValue(ByVal key As String, _
ByVal src As String) As String
Dim lines() As String = src.Split(Chr(10))
Dim count As Integer = lines.Length
For i As Integer = 0 To count - 1
Dim s As String = lines(i).Trim((" " & vbTab & vbCrLf).ToCharArray())
If s.Length > 0 Then
If (String.Compare(s, 0, key, 0, key.Length, True) = 0) Then
GetHeaderValue = s.Substring(key.Length).Trim((" " & vbTab & vbCrLf).ToCharArray())
Exit Function
End If
End If
Next
GetHeaderValue = ""
End Function
Public Function SearchFirstEmailAddr(ByVal src As String) As String
SearchFirstEmailAddr = ""
Dim pos As Integer = src.IndexOf("@")
If pos = -1 Then
Exit Function
End If
Dim addr As String
Dim endpos As Integer = src.IndexOfAny(("<> ;,:" & vbTab & vbCrLf).ToCharArray(), pos)
Dim startpos As Integer = src.LastIndexOfAny(("<> ;,:" & vbTab & vbCrLf).ToCharArray(), pos)
If endpos > 0 And startpos > 0 Then
addr = src.Substring(startpos, endpos - startpos).Trim(("<> ;,:" & vbTab & vbCrLf).ToCharArray())
End If
SearchFirstEmailAddr = addr
End Function
[C#]
using EAGetMail;
public static void ParseReport( string emlFile )
{
Mail oMail = new Mail("TryIt");
oMail.Load(emlFile, false );
string contentType = oMail.Headers.GetValueOfKey("Content-Type").ToLower();
if( contentType.IndexOf("multipart/report") == -1 )
{
//not delivery report
Console.WriteLine("This is not a delivery report.");
return;
}
HeaderItem item = new HeaderItem("Content-Type", oMail.Headers.GetValueOfKey("Content-Type"));
string type = item.SubValue("report-type");
string recipient = "";
string messageid = "";
string status = "failed";
Attachment[] atts = oMail.Attachments;
if( atts.Length > 0 )
{
Attachment att = atts[0];
string src = "";
src = System.Text.Encoding.Default.GetString(att.Content);
if( String.Compare(type, "disposition-notification", true ) == 0 )
{
//this is a read receipt
status = "delivered";
messageid = GetHeaderValue("Original-Message-ID:", src);
recipient = GetHeaderValue("Final-Recipient:", src);
}
else
{
//this is a delivery report
status = GetHeaderValue("Action:", src);
messageid = GetHeaderValue("Original-Message-ID:", src);
recipient = GetHeaderValue("Final-Recipient:", src);
if( messageid.Length == 0 && atts.Length > 1 )
{
//get message id from original headers/message
att = atts[1];
src = System.Text.Encoding.Default.GetString(att.Content);
messageid = GetHeaderValue("Message-ID:", src);
}
}
}
else
{
//this delivery report doesn't contain the report attachment, parse the body text
status = "failed";
string src = oMail.TextBody;
recipient = SearchFirstEmailAddr(src);
messageid = GetHeaderValue("Message-ID:", src);
}
int pos = recipient.IndexOf(";");
if( pos != -1 )
recipient = recipient.Substring(pos + 1);
recipient = recipient.Trim("<>".ToCharArray());
Console.WriteLine("This is a delivery report.");
Console.WriteLine("Recipient: {0}", recipient);
Console.WriteLine("Message-ID: {0}", messageid);
Console.WriteLine("Status: {0}", status);
}
private static string GetHeaderValue(
string key,
string src)
{
string [] lines = src.Split('\n');
int count = lines.Length;
for( int i = 0; i < count; i++ )
{
string s = lines[i].Trim( " \t\r\n".ToCharArray());
if( s.Length > 0 )
{
if( String.Compare( s, 0, key, 0, key.Length, true ) == 0 )
return s.Substring( key.Length).Trim( " \t\r\n".ToCharArray());
}
}
return "";
}
private static string SearchFirstEmailAddr( string src )
{
string addr = "";
int pos = src.IndexOf('@');
if( pos == -1 )
return "";
int endpos = src.IndexOfAny("<> ;,:\t\r\n".ToCharArray(), pos);
int startpos = src.LastIndexOfAny("<> ;,:\r\n\t".ToCharArray(), pos);
if( endpos > 0 && startpos > 0 )
addr = src.Substring(startpos, endpos - startpos).Trim("<> ;,:\r\n\t".ToCharArray());
return addr;
}
See Also
Using EAGetMail POP3 & IMAP4 Component
User Authentication and SSL Connection
Digital Signature and E-mail Encryption/Decryption
Unique Identifier (UIDL) in POP3 and IMAP4 protocol
Work with winmail.dat (TNEF Parser)
EAGetMail Namespace References
EAGetMail POP3 & IMAP4 Component Samples