Mailkit: How get email delivery status when send by SMTP

Created on 19 Dec 2017  Â·  9Comments  Â·  Source: jstedfast/MailKit

using (var client = new SmtpClient())
            {
                client.MessageSent += Client_MessageSent;

                client.ServerCertificateValidationCallback = (s, c, h, e) => true;
                client.AuthenticationMechanisms.Remove("XOAUTH2");
                client.Timeout = 10 * 1000;
                client.Connect("smtp.server", 25, false);
                client.Send(message);
                client.Disconnect(true);
            }

After i send out the email, how to monitor the user whether deliveried ?

question

Most helpful comment

correct.

All 9 comments

You'll receive an email containing a multipart/report that contains a child with a mime-type of message/delivery-status.

MimeKit has classes to parse these, but it is up to you to interpret them.

See: http://www.mimekit.net/docs/html/T_MimeKit_MultipartReport.htm and http://www.mimekit.net/docs/html/T_MimeKit_MessageDeliveryStatus.htm

Thanks jstedfast。
These documents I have seen yesterday. But I did‘t know how to implement it, not find any example.

I need follow these steps to get delivery status?

1. When send email ,add delivery notification

        protected override DeliveryStatusNotification? GetDeliveryStatusNotifications(MimeMessage message, MailboxAddress mailbox)
        {
            // In this example, we only want to be notified of failures to deliver to a mailbox.
            // If you also want to be notified of delays or successful deliveries, simply bitwise-or
            // whatever combination of flags you want to be notified about.
            return DeliveryStatusNotification.Success | DeliveryStatusNotification.Delay | DeliveryStatusNotification.Failure;
        }

2. Create a new application, Use POP3Client get all received message.

        private static void ReceiveMessage()
        {           
            using (var client = new Pop3Client())
            {
                client.ServerCertificateValidationCallback = (s, c, h, e) => true;
                client.Connect("10.16.98.34", 110, false);
                // Note: since we don't have an OAuth2 token, disable
                // the XOAUTH2 authentication mechanism.
                client.AuthenticationMechanisms.Remove("XOAUTH2");
                //client.Authenticate("joey", "password");

                for (int i = 0; i < client.Count; i++)
                {
                    var message = client.GetMessage(i);
                    Console.WriteLine("Subject: {0}", message.Subject);
                }

                client.Disconnect(true);
            }
        }

3. After received message, Analyse message, check is whether delivered, or failed?

correct.

Hi jstedfast

Use Pop3Client,I received the message,The type is "MimeMessage", How can I get MessageDeliveryStatus? and how to check the status is success or failure?

Another question. When we received message, How to identify the status report message is original sent email. use InReplyTo ?

The message itself will always be a MimeMessage. The Body will probably be a MultipartReport or, at the very least, it'll be another type of Multipart that will contain the MultipartReport. Either way, the MultipartReport will contain the MessageDeliveryStatus.

I'm not entirely sure what you are asking about the InReplyTo.

If you are asking how to know which message the delivery status is in reference to, then you need to check the StatusGroups property of the MessageDeliveryStatus and check for the Original-Envelope-Id field.

e.g. like this:

foreach (var statusGroup in messageDeliveryStatus.StatusGroups) {
    // The Original-Envelope-Id will match the string that you returned in the custom SmtpClient.GetEnvelopeId() method
    var envelopeId = statusGroup["Original-Envelope-Id"];

    // This value will be in the form "rfc822;[email protected]"
    var recipient = statusGroups["Original-Recipient"];
    var address = recipient != null ? recipient.Split (';')[1] : null;

    // The Action value will be "failed", "delayed", etc.
    var action = statusGroups["Action"];
}

For more details, read RFC 3464, section 2.3

Merry Christmas!

The following is my demo. I can get MultipartReport, But who to convert to messageDeliveryStatus. Not find any property or method in MultipartReport.

using (var client = new Pop3Client())
                {
                    client.ServerCertificateValidationCallback = (s, c, h, e) => true;
                    client.Connect("pop3.server", 110, false);
                    // Note: since we don't have an OAuth2 token, disable
                    // the XOAUTH2 authentication mechanism.
                    client.AuthenticationMechanisms.Remove("XOAUTH2");

                    for (int i = 0; i < client.Count; i++)
                    {
                        var message = client.GetMessage(i);
                        if (message.Body is MultipartReport report)
                        {
                            Console.WriteLine("ReportType: {0}", report.ReportType);
                            Console.WriteLine("MessageId: {0}", message.MessageId);
                        }

                        client.DeleteMessage(i);
                    }
                    client.Disconnect(true);
                }

My application is base .net core2.0.
Mailkit version:2.0.0

You really need to read the relative MIME specifications rather than just guessing. There's only so much the MimeKit API can do, the rest hinges upon your willingness to read the specs so you understand how everything fits together.

If you were trying to download a web page and all of the images that it references without understanding anything about HTML or HTTP, you wouldn't get very far even if you had access to System.Net.HttpClient, would you?

I hope the following code will help:

var message = client.GetMessage(i);
var report = message.Body as MultipartReport;

if (report != null && report.ReportType.ToLowerInvariant () == "delivery-status")
{
    foreach (var deliveryStatus in report.OfType<MessageDeliveryStatus> ()) {
        foreach (var statusGroup in deliveryStatus.StatusGroups) {
            // The Original-Envelope-Id will match the string that you returned in the custom SmtpClient.GetEnvelopeId() method
            var envelopeId = statusGroup["Original-Envelope-Id"];

            // This value will be in the form "rfc822;[email protected]"
            var recipient = statusGroups["Original-Recipient"];
            var address = recipient != null ? recipient.Split (';')[1] : null;

            // The Action value will be "failed", "delayed", etc.
            var action = statusGroups["Action"];
        }
    }
}

If you still need help with your project, I would appreciate a donation because I only have so much free time.

Thanks.

Was this page helpful?
0 / 5 - 0 ratings