Reputation: 1731
I'm implementing email server in asp.net core 2.0 with mailkit. About my scenario, I have to send email and need to return feedback with the email sent status.I have implemented email send part and it's working fine.
I know try catch is a one option.But it's not enough with my situation. Because exception will be occurred only when network error or authentication failure. But exception won't occur if some receiver email is invalid.
I have to return email sent status for each email in List.But If there is invalid email or another error I can't catch it.
I saw a event called MessageSent. But I don't know to implement that event and whether it's match with my condition.
This is my full code.
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);
}
}
Upvotes: 2
Views: 7314
Reputation: 161
You need override the GetDeliveryStatusNotifications class, something like this:
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;
}
}
}
Upvotes: 2
Reputation: 1731
We can get MessageSent like this.It's confirm email is send by smtp service.But it's not returning email receive status.
Eg: my smtp server is gmail and i'm sending email to yahoo email address. Using MessageSent we can confirm that email is dispatch from smtp gmail client.But we can't get the received status of yahoo email.
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!");
}
Upvotes: -2
Reputation: 1642
There is a good explanation of MailKit's MessageSent here - https://stackoverflow.com/a/48132905/1105937
TLDR: Use the try/catch as that will tell you if the message was sent or not..
var IsEmailSent = false;
try
{
emailClient.Send(email);
IsEmailSent = true;
}
catch (Exception ex)
{
}
You won't be able to tell if the users email address does not exist for privacy issues, but the person who sent the email will get any bounce back messages.
If you send out all the emails using a generic email address like [email protected] then add the app user (the person sending the email) as a "reply to" email so they will recieve a copy of any bounce backs as they occur.
Upvotes: 1