我正在使用mailkit在asp.net core 2.0中实现电子邮件服务器。关于我的情况,我必须发送电子邮件并需要以电子邮件发送状态返回反馈。我已经实现了电子邮件发送部分,并且可以正常工作。
我知道尝试抓捕是一个选择,但是我的情况还不够。因为只有在网络错误或身份验证失败时才会发生例外。但是,如果某些收件人电子邮件无效,则不会发生异常。
我必须为列表中的每封电子邮件返回电子邮件发送状态。但是,如果有无效的电子邮件或其他错误,我将无法捕获。
我看到了一个名为 MessageSent 的事件。但是我不知道执行该事件以及它是否符合我的条件。
这是我的完整代码。
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);
}
}
答案 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!");
}