如何使用asp.net core在mailkit中获取电子邮件的发送状态

时间:2018-09-07 06:15:31

标签: asp.net-core smtpclient mailkit

我正在使用mailkit在asp.net core 2.0中实现电子邮件服务器。关于我的情况,我必须发送电子邮件并需要以电子邮件发送状态返回反馈。我已经实现了电子邮件发送部分,并且可以正常工作。

我知道尝试抓捕是一个选择,但是我的情况还不够。因为只有在网络错误或身份验证失败时才会发生例外。但是,如果某些收件人电子邮件无效,则不会发生异常。 enter image description here

我必须为列表中的每封电子邮件返回电子邮件发送状态。但是,如果有无效的电子邮件或其他错误,我将无法捕获。

我看到了一个名为 MessageSent 的事件。但是我不知道执行该事件以及它是否符合我的条件。

enter image description here

这是我的完整代码。

  public void SendEmail(List<EmailMessage> emailMessages)
        {
            List<MimeMessage> emailQueue = new List<MimeMessage>();
            foreach (EmailMessage emailMessage in emailMessages)
            {
                var message = new MimeMessage();
                message.MessageId = emailMessage.MessageId;
                message.To.AddRange(emailMessage.ToAddresses.Select(x => new MailboxAddress(x.Name, x.Address)));
                message.From.AddRange(emailMessage.FromAddresses.Select(x => new MailboxAddress(x.Name, x.Address)));

                message.Subject = emailMessage.Subject;
               
                message.Body = new TextPart(TextFormat.Html)
                {
                    Text = emailMessage.Content
                };

                emailQueue.Add(message);
            }
           
            using (var emailClient = new SmtpClient())
            {                   
                emailClient.Connect(_emailConfiguration.SmtpServer, _emailConfiguration.SmtpPort, _emailConfiguration.EnableSSL);
               
                emailClient.AuthenticationMechanisms.Remove("XOAUTH2");

                emailClient.Authenticate(_emailConfiguration.SmtpUsername, _emailConfiguration.SmtpPassword);
                foreach (MimeMessage email in emailQueue)
                {
                    try
                    {
                         emailClient.Send(email);
                       
                    }
                    catch (Exception ex)
                    {
                        
                    }                       
                }
                emailClient.Disconnect(true);
            }
        }      

3 个答案:

答案 0 :(得分:1)

您需要重写GetDeliveryStatusNotifications类,如下所示:

using MailKit;
using MailKit.Net.Smtp;
using MimeKit;
using System;
using System.Collections.Generic;

namespace YourProject    
{
    public class CustomSmtpClient : SmtpClient
    {
        protected override DeliveryStatusNotification? GetDeliveryStatusNotifications(MimeMessage message, MailboxAddress mailbox)
        {
            if (!(message.Body is MultipartReport report) || report.ReportType == null || !report.ReportType.Equals("delivery-status", StringComparison.OrdinalIgnoreCase))
                return default;
            report.OfType<MessageDeliveryStatus>().ToList().ForEach(x => {
                x.StatusGroups.Where(y => y.Contains("Action") && y.Contains("Final-Recipient")).ToList().ForEach(z => {
                    switch (z["Action"])
                    {
                        case "failed":
                            Console.WriteLine("Delivery of message {0} failed for {1}", z["Action"], z["Final-Recipient"]);
                            break;
                        case "delayed":
                            Console.WriteLine("Delivery of message {0} has been delayed for {1}", z["Action"], z["Final-Recipient"]);
                            break;
                        case "delivered":
                            Console.WriteLine("Delivery of message {0} has been delivered to {1}", z["Action"], z["Final-Recipient"]);
                            break;
                        case "relayed":
                            Console.WriteLine("Delivery of message {0} has been relayed for {1}", z["Action"], z["Final-Recipient"]);
                            break;
                        case "expanded":
                            Console.WriteLine("Delivery of message {0} has been delivered to {1} and relayed to the the expanded recipients", z["Action"], z["Final-Recipient"]);
                            break;
                    }
                });
            });
            return default;
        }
    }
}

答案 1 :(得分:0)

这里有对MailKit的MessageSent的很好解释-https://stackoverflow.com/a/48132905/1105937

TLDR:使用try / catch,因为它会告诉您消息是否已发送。

var IsEmailSent = false;

try
{
    emailClient.Send(email);
    IsEmailSent = true;
}
catch (Exception ex)
{

}  

您将无法确定用户的电子邮件地址是否存在隐私问题,但发送电子邮件的人将收到任何退回邮件。

如果您使用通用电子邮件地址(例如do-not-reply@my-cool-app.com)发送所有电子邮件,则将应用程序用户(发送电子邮件的人)添加为“回复”电子邮件,以便他们会在出现反弹时获得任何副本。

答案 2 :(得分:-1)

我们可以这样获得 MessageSent 。它确认电子邮件是由smtp服务发送的,但它没有返回电子邮件的接收状态。

例如:我的smtp服务器是gmail,并且我正在将电子邮件发送到yahoo电子邮件地址。使用 MessageSent ,我们可以确认电子邮件是从smtp gmail客户端发送的,但是我们无法获取yahoo电子邮件的接收状态。

                foreach (MimeMessage email in emailQueue)
                {
                    try
                    {                      
                        emailClient.MessageSent += OnMessageSent;   
                        emailClient.Send(email);                    
                    }
                    catch (Exception ex)
                    {
                    }
    }
------------------------------------------------------------------------------     
        void OnMessageSent(object sender, MessageSentEventArgs e)
        {
            Console.WriteLine("The message was sent!");
          
        }