Skip to content

eric-b/DSN-Parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mail Delivery Status Notification (DSN) parser

What is it ?

It's a single file you can drop in your project. You can also install the nuget package.

There is two helper methods to identify and parse a report as defined by RFC 3464.

MailDeliveryInfo.IsDsn(string partialMessage)

This method should be used only if the complete message has not yet been downloaded.

Reads only the headers and returns true essentially if :

  • First header is: Return-path: <>
  • Content-Type contains report-type=delivery-status

Means that MailDeliveryInfo.TryCreate() should return a result for that message.

MailDeliveryInfo.TryCreate(string rawMessage)

Evaluates MailDeliveryInfo.IsDsn(rawMessage) and tries to parse the report. Returns null if it fails or if it is not a report.

Informations parsed

Basically, each instance of MailDeliveryInfo defines:

  • a date,
  • the raw report (with Content-Type: message/delivery-status),
  • a list of status, each associated with an e-mail (see below),
  • an arbitrary Uid property (not filled by the helper methods): can be used by the caller to store the report identifier (from POP3 for example).

The headers of the original (not delivered) message are also accessible.

Each status defines basically:

  • an action (ie "Failed", "Delayed", "Delivered", "Relayed" or "Expanded"),
  • a status code (ie. "5.1.1"),
  • a classification string (ie. "PermanentFailure/AddressingStatus/BadDestinationMailboxAddress"),
  • a diagnostic code (ie "smtp; 550-5.1.1 The email account that you tried to reach does not exist.").

Example usage

if (MailDeliveryInfo.IsDsn(PARTIAL_MESSAGE)) // PARTIAL_MESSAGE: headers only
{
	var report = MailDeliveryInfo.TryCreate(RAW_MESSAGE); // RAW_MESSAGE: full message
	if (report != null)
	{
	    Console.WriteLine("{0}\r\n{2}\r\nRaw report:\r\n{1}",
		report.Date,
		report.RawReport,
		string.Join(Environment.NewLine,
		    report.Status
		    .Select(t =>
			string.Format("{0}: {1} ({2})",
			t.Key,
			t.Value.GetMostSignificantClassificationString(),
			t.Value.MostSignificantStatusCode))
		    .ToArray()));
	}
	else
	{
	    Console.WriteLine("Failed to parse this message.");
	}
}
else
{
	Console.WriteLine("Not a DSN.");
}

// Output:
/*
04/05/2012 15:25:09
[email protected]: PermanentFailure/AddressingStatus/BadDestinationMailboxAddress (5.1.1)
Raw report:
Content-Description: Delivery report
Content-Type: message/delivery-status

Reporting-MTA: dns; xxx
Arrival-Date: Fri, 04 May 2012 15:25:09 +0200

Final-Recipient: rfc822; [email protected]
Status: 5.1.1
Action: failed
Last-Attempt-Date: Fri, 04 May 2012 15:25:09 +0200
Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at
550 5.1.1 http://support.google.com/mail/bin/answer.py?answer=6596 t12si10077186weq.36
*/

Limitations, caveats, known bugs

Let me know if you have troubles with use of this library.

About

Parser for Delivery Status Notification messages (DSN)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages