I am using Mailkit library to send e-mails. This is the code to do so:
public async Task SendAsync(IdentityMessage message)
{
if (message == null)
return;
LinkedResource inline = new LinkedResource(System.Web.Hosting.HostingEnvironment.MapPath($"~/Images/logo.png"))
{
ContentId = Guid.NewGuid().ToString(),
ContentType = new ContentType("image/png")
{
Name = "logo.png"
}
};
var htmlBody = message.Body.Replace("{CID:LOGO}", String.Format("cid:{0}", inline.ContentId));
AlternateView avHtml = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
avHtml.LinkedResources.Add(inline);
using (MailMessage objMailMsg = new MailMessage())
{
objMailMsg.AlternateViews.Add(avHtml);
objMailMsg.Body = htmlBody;
objMailMsg.Subject = message.Subject;
objMailMsg.BodyEncoding = Encoding.UTF8;
Properties.Settings.Default.Reload();
string fromEmail = Properties.Settings.Default.FromMail;
string fromName = Properties.Settings.Default.FromName;
string smtpPassword = Properties.Settings.Default.PwdSmtp;
objMailMsg.From = new MailAddress(fromEmail, fromName);
objMailMsg.To.Add(message.Destination);
objMailMsg.IsBodyHtml = true;
MimeMessage mime = MimeMessage.CreateFromMailMessage(objMailMsg);
HeaderId[] headersToSign = new HeaderId[] { HeaderId.From, HeaderId.Subject, HeaderId.Date };
string domain = "example.cl";
string selector = "default";
DkimSigner signer = new DkimSigner(@"C:\inetpub\dkim.pem", domain, selector)
{
HeaderCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Relaxed,
BodyCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple,
AgentOrUserIdentifier = "@contact.example.cl",
QueryMethod = "dns/txt",
};
mime.Prepare(EncodingConstraint.EightBit);
signer.Sign(mime, headersToSign);
using (SmtpClient smtpClient = new SmtpClient())
{
await Task.Run(() =>
{
try
{
smtpClient.Connect(Properties.Settings.Default.ServidorSmtp, Properties.Settings.Default.PuertoSmtp, Properties.Settings.Default.SSLSmtp);
smtpClient.Authenticate(fromEmail, smtpPassword);
smtpClient.Send(mime);
smtpClient.Disconnect(true);
}
catch (Exception ex)
{
ErrorLog.Save(ex);
//InfoLog.Save(htmlBody);
}
});
}
}
}
Well.. when the e-mail arrives, e-mail client shows it correctly in HTML format. However, an HTML file is attached in the e-mail also.
That file is named, for example, Attached data without title 00391.html
. If I open that file in browser, the e-mail body is shown.
I have not found a way to change the name of that attachment.
Does anyone know?
The problem is probably this:
var htmlBody = message.Body.Replace("{CID:LOGO}", String.Format("cid:{0}", inline.ContentId));
AlternateView avHtml = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
// ...
objMailMsg.AlternateViews.Add(avHtml);
objMailMsg.Body = htmlBody;
You are setting the HTML body text as 2 different body parts. If you create the avHtml
part, you shouldn't also need to set objMailMsg.Body = htmlBody
.
When MailKit later converts the System.Net.Mail.MailMessage into a MimeMessage, it probably ends up with 2 duplicate parts, one that gets used as the actual HTML body and one that gets added as an attachment w/o a name (the receiving client likely assigns this part a random name which is what you are seeing).
Alternatively, you could remove the logic that creates a System.Net.Mail.MailMessage completely and just construct a MimeMessage and avoid potential issues in conversion.
var bodyBuilder = new BodyBuilder ();
var logo = bodyBuilder.LinkedResources.Add (System.Web.Hosting.HostingEnvironment.MapPath($"~/Images/logo.png"));
var htmlBody = message.Body.Replace("{CID:LOGO}", String.Format("cid:{0}", logo.ContentId));
bodyBuilder.HtmlBody = htmlBody;
Properties.Settings.Default.Reload();
string fromEmail = Properties.Settings.Default.FromMail;
string fromName = Properties.Settings.Default.FromName;
string smtpPassword = Properties.Settings.Default.PwdSmtp;
var mime = new MimeMessage ();
mime.From.Add (new MailboxAddress (fromName, fromEmail));
mime.To.Add (MailboxAddress.Parse (message.Destination));
mime.Subject = message.Subject;
mime.Body = bodyBuilder.ToMessageBody ();
HeaderId[] headersToSign = new HeaderId[] { HeaderId.From, HeaderId.Subject, HeaderId.Date };
string domain = "example.cl";
string selector = "default";
DkimSigner signer = new DkimSigner(@"C:\inetpub\dkim.pem", domain, selector)
{
HeaderCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Relaxed,
BodyCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple,
AgentOrUserIdentifier = "@contact.example.cl",
QueryMethod = "dns/txt",
};
mime.Prepare(EncodingConstraint.EightBit);
signer.Sign(mime, headersToSign);