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);
Related
So I am sending an Email in .net like so. I am receiving the email that I am reading from the file with the stream reader but it is returned as HTML code instead of the actual layout. Is there an attribute I am forgetting to set?
public static async Task WelcomeEmail(string emailAdresse)
{
var fromAddress = new MailAddress(Constants.EMAILUSER, "Test");
const string fromPassword = Constants.EMAILPW;
var toAddress = new MailAddress(emailAdresse);
string subject = "Wilkommen";
string body;
var assembly = typeof(Email).GetTypeInfo().Assembly;
string[] resources = assembly.GetManifestResourceNames();
Stream stream = assembly.GetManifestResourceStream("InteriorCircle.Resources.welcome_mail.html");
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{
body = streamReader.ReadToEnd();
}
var smtp = new SmtpClient
{
Host = Constants.EMAILSERVER,
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var txt = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
smtp.Send(txt);
}
}
var msg = new AE.Net.Mail.MailMessage
{
Subject = subject,
Body = bodyhtml,
From = new System.Net.Mail.MailAddress("myemail")
};
foreach (string add in vendorEmailList.Split(','))
{
if (string.IsNullOrEmpty(add))
continue;
msg.To.Add(new System.Net.Mail.MailAddress(add));
}
msg.ReplyTo.Add(msg.From); // Bounces without this!!
msg.ContentType = "text/html";
////attachment code
foreach (string path in attachments)
{
var bytes = File.ReadAllBytes(path);
string mimeType = MimeMapping.GetMimeMapping(path);
AE.Net.Mail.Attachment attachment = new AE.Net.Mail.Attachment(bytes, mimeType, Path.GetFileName(path), true);
msg.Attachments.Add(attachment);
}
////end attachment code
var msgStr = new StringWriter();
msg.Save(msgStr);
Message message = new Message();
message.Raw = Base64UrlEncode(msgStr.ToString());
var result = gmailService.Users.Messages.Send(message, "me").Execute();
This code is working without attachment but with attachment instead of attachment directly byte[] is appearing in inbox.
If i remove msg.ContentType = "text/html" this line then it is working but html not rendering in email, appearing as plain text.
I want to send both HTML body and attachment, Please help.
MailMessage mail = new MailMessage();
mail.Subject = subject;
mail.Body = bodyhtml;
mail.From = new MailAddress("myemail");
mail.IsBodyHtml = true;
foreach (string add in vendorEmailList.Split(','))
{
if (string.IsNullOrEmpty(add))
continue;
mail.To.Add(new MailAddress(add));
}
foreach (string add in userEmailList.Split(','))
{
if (string.IsNullOrEmpty(add))
continue;
mail.CC.Add(new MailAddress(add));
}
foreach (string path in attachments)
{
//var bytes = File.ReadAllBytes(path);
//string mimeType = MimeMapping.GetMimeMapping(path);
Attachment attachment = new Attachment(path);//bytes, mimeType, Path.GetFileName(path), true);
mail.Attachments.Add(attachment);
}
MimeKit.MimeMessage mimeMessage = MimeMessage.CreateFromMailMessage(mail);
Message message = new Message();
message.Raw = Base64UrlEncode(mimeMessage.ToString());
var result = gmailService.Users.Messages.Send(message, "me").Execute();
I found solution after lot of efforts. Instead of AE.Net.Mail.MailMessage used System.Net.Mail.MailMessage and MimeKit to convert it to raw string. And now html body with attachment is working fine.
try adding IsBodyHtml = true
new AE.Net.Mail.MailMessage
{
Subject = subject,
Body = bodyhtml,
From = new System.Net.Mail.MailAddress("myemail")
IsBodyHtml = true
};
i got a mail message which is not a MIME message
can not get Content-Type
can not get attachment
how to convert this message into MIME message
foreach (AE.Net.Mail.Lazy<MailMessage> message in messages)
{
MailMessage m = message.Value;
string sender = m.From.Address;
ICollection<Attachment> cc = m.Attachments;
foreach (Attachment aa in cc)
{
System.IO.File.WriteAllBytes(#"C:\Users\LAB-User2\Desktop\EmailAttachments\" + aa.Filename, aa.GetData());
}
}
Update
does this disposition work for non-mime message?
public string GetDisposition()
{
return this["Content-Disposition"]["boundary"];
}
string disposition = Headers.GetDisposition();
if (!string.IsNullOrEmpty(disposition))
{
//else this is a multipart Mime Message
using (var subreader = new StringReader(line + Environment.NewLine + reader.ReadToEnd()))
ParseMime(subreader, disposition);
}
else
{
//SetBody((line + Environment.NewLine + reader.ReadToEnd()).Trim());
}
can i send non-mime email to myself ? so that i can receive mime format email?
when i try this, i can not email to myself
ImapClient imap = new ImapClient("imap.gmail.com", "hello#gmail.com", "pwd", ImapClient.AuthMethods.Login, 993, true, true);
//imap.Connect("imap.gmail.com", 993, true, true);
imap.SelectMailbox("INBOX");
//MailMessage[] mm = imap.GetMessages(imap.GetMessageCount() - 1, imap.GetMessageCount() - 10, false, false);
AE.Net.Mail.Lazy<AE.Net.Mail.MailMessage>[] messages = imap.SearchMessages(SearchCondition.Unseen(), false);
// Run through each message:
foreach (AE.Net.Mail.Lazy<AE.Net.Mail.MailMessage> message in messages)
{
AE.Net.Mail.MailMessage mm = message.Value;
//create the mail message
//var mail = new MailMessage();
var mail = new System.Net.Mail.MailMessage();
//set the addresses
mail.From = new MailAddress("me#mycompany.com", "demo");
mail.To.Add("hello#gmail.com");
//set the content
mail.Subject = "This is an email";
//first we create the Plain Text part
//var plainView = AlternateView.CreateAlternateViewFromString("This is my plain text content, viewable by those clients that don't support html", null, "text/plain");
//then we create the Html part
//var htmlView = AlternateView.CreateAlternateViewFromString("<b>this is bold text, and viewable by those mail clients that support html</b>", null, "text/html");
ICollection<AE.Net.Mail.Attachment> cc = mm.AlternateViews;
foreach (AE.Net.Mail.Attachment aa in cc)
{
try
{
System.IO.File.WriteAllBytes(#"C:\Users\LAB-User2\Desktop\EmailAttachments\" + aa.Filename, aa.GetData());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//mail.AlternateViews.Add(b);
}
var plainView = AlternateView.CreateAlternateViewFromString(mm.Raw, null, "text/plain");
mail.AlternateViews.Add(plainView);
//send the message
var smtp = new SmtpClient("smtp.gmail.com", 587); //specify the mail server address
smtp.Credentials = new System.Net.NetworkCredential("hello#gmail.com", "pwd");
smtp.EnableSsl = true;
smtp.Send(mail);
smtp = null;
mail.Dispose();
You can use this sample:
//create the mail message
var mail = new MailMessage();
//set the addresses
mail.From = new MailAddress("me#mycompany.com");
mail.To.Add("you#yourcompany.com");
//set the content
mail.Subject = "This is an email";
//first we create the Plain Text part
var plainView = AlternateView.CreateAlternateViewFromString("This is my plain text content, viewable by those clients that don't support html", null, "text/plain");
//then we create the Html part
var htmlView = AlternateView.CreateAlternateViewFromString("<b>this is bold text, and viewable by those mail clients that support html</b>", null, "text/html");
mail.AlternateViews.Add(plainView);
mail.AlternateViews.Add(htmlView);
//send the message
var smtp = new SmtpClient("127.0.0.1"); //specify the mail server address
smtp.Send(mail);
I'm creating a mailBody via
using (var streamWriter = new StreamWriter(fooFileName, false, Encoding.UTF8))
{
streamWriter.Write(fooMessage);
}
now i'm consuming this file with
var mailMessage = new System.Net.Mail.MailMessage
{
From = fooSender,
To =
{
fooRecipient
},
Subject = fooSubject,
SubjectEncoding = Encoding.UTF8,
BodyEncoding = Encoding.UTF8
};
// fooMediaType can be
// - System.Net.Mime.MediaTypeNames.Text.Html
// - System.Net.Mime.MediaTypeNames.Text.Plain
var alternateView = new System.Net.Mail.AlternateView(fooFileName, fooMediaType);
mailMessage.AlternateViews.Add(alternateView);
If I'm using non-umlauts, everything works fine, but as soon as I'm using umlauts in my alternateView, they get broken.
So how can I set some sort of encoding on the alternateView that everything is working?
var alternateView = new AlternateView(fooFileName, fooMediaType)
{
ContentType =
{
CharSet = Encoding.UTF8.WebName
}
};
Why can't I send xls,doc and other files - it does work for jpg,txt and others.
private void BuildAndSend(string pTo,string pCC,string pSubject,string pBody)
{
// building the mail
System.Net.Mail.MailAddress toAddress = new System.Net.Mail.MailAddress(pTo);
System.Net.Mail.MailAddress fromAddress = new System.Net.Mail.MailAddress("mymail#gmail.com");
System.Net.Mail.MailMessage mm = new System.Net.Mail.MailMessage(fromAddress, toAddress);
mm.Subject = pSubject ;
mm.Body = pBody;
System.Net.Mail.MailAddress cc = new System.Net.Mail.MailAddress(pCC);
mm.CC.Add(cc);
addAttachments(mm);
mm.IsBodyHtml = true;
mm.BodyEncoding = System.Text.Encoding.UTF8;
//sending the mail
sendMail(mm);
}
private void addAttachments(System.Net.Mail.MailMessage mm)
{
string attachmentFile;
for (int i = 0; i < lstAttachments.Items.Count ; i++)
{
string fileFullName = pullDictionary[i];
attachmentFile = fileFullName;
System.Net.Mail.Attachment mailAttachment = new System.Net.Mail.Attachment(attachmentFile);
mm.Attachments.Add(mailAttachment);
}
}
private void sendMail(System.Net.Mail.MailMessage mm)
{
try
{
// loging in into sending user account
string smtpHost = "smtp.gmail.com";
string userName = "mymail#gmail.com";//sending Id
string password = "mypass";
System.Net.Mail.SmtpClient mClient = new System.Net.Mail.SmtpClient();
mClient.Port = 587;
mClient.EnableSsl = true;
mClient.UseDefaultCredentials = false;
mClient.Credentials = new NetworkCredential(userName, password);
mClient.Host = smtpHost;
mClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
mClient.Send(mm);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
if you can show me another way to send these files it will be great as well
If your jpegs and text files are going I'm guessing your problem may be in your path to some of the other file types or in the size of some of these other files (just a wild guess really as the code you posted looks ok).
// this looks suspect
string fileFullName = pullDictionary[i];
attachmentFile = fileFullName;
Here is a snippet of some working code. Note that I've never set either the mm.BodyEncoding = System.Text.Encoding.UTF8; or mClient.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; properties explicitly and have had success. (Probably just an unrelated observation...)
MailMessage m = new MailMessage(_gmailEmail, _to);
m.Subject = _emailSubject;
m.Body = _body;
for (int i = 0; i < lstAttachments.Items.Count ; i++) // your list
m.Attachments.Add(new Attachment("\path\to\file\to\attach\here"));
You mentioned that you'd like to see something different... Well, your attachment code looks fine so I thought I'd provide some code that allows you to embed images inline in your email rather than as an attachment:
// the below adds embedded images an email...
AlternateView avHtml = AlternateView.CreateAlternateViewFromString(
_body, null, System.Net.Mime.MediaTypeNames.Text.Html);
LinkedResource pic = new LinkedResource("\path\to\file\to\embed\here", System.Net.Mime.MediaTypeNames.Image.Jpeg);
pic.ContentId = "IMAGE1"; // just make sure this is a unique string if you have > 1
avHtml.LinkedResources.Add(pic);
m.AlternateViews.Add(avHtml);
Post some specific error messages/exceptions caught and you'll get more help...