Can I send files via email using MailKit? - c#

As the title, is MailKit supported to send file?
If yes, how can I do it?

Yes. This is explained in the documentation as well as the FAQ.
From the FAQ:
How do I create a message with attachments?
To construct a message with attachments, the first thing you'll need to do is create a multipart/mixed container which you'll then want to add the message body to first. Once you've added the body, you can then add MIME parts to it that contain the content of the files you'd like to attach, being sure to set the Content-Disposition header value to the attachment. You'll probably also want to set the filename parameter on the Content-Disposition header as well as the name parameter on the Content-Type header. The most convenient way to do this is to simply use the MimePart.FileName property which
will set both parameters for you as well as setting the Content-Disposition header value to attachment if it has not already been set to something else.
var message = new MimeMessage ();
message.From.Add (new MailboxAddress ("Joey", "joey#friends.com"));
message.To.Add (new MailboxAddress ("Alice", "alice#wonderland.com"));
message.Subject = "How you doin?";
// create our message text, just like before (except don't set it as the message.Body)
var body = new TextPart ("plain") {
Text = #"Hey Alice,
What are you up to this weekend? Monica is throwing one of her parties on
Saturday. I was hoping you could make it.
Will you be my +1?
-- Joey
"
};
// create an image attachment for the file located at path
var attachment = new MimePart ("image", "gif") {
Content = new MimeContent (File.OpenRead (path)),
ContentDisposition = new ContentDisposition (ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64,
FileName = Path.GetFileName (path)
};
// now create the multipart/mixed container to hold the message text and the
// image attachment
var multipart = new Multipart ("mixed");
multipart.Add (body);
multipart.Add (attachment);
// now set the multipart/mixed as the message body
message.Body = multipart;
A simpler way to construct messages with attachments is to take advantage of the
BodyBuilder class.
var message = new MimeMessage ();
message.From.Add (new MailboxAddress ("Joey", "joey#friends.com"));
message.To.Add (new MailboxAddress ("Alice", "alice#wonderland.com"));
message.Subject = "How you doin?";
var builder = new BodyBuilder ();
// Set the plain-text version of the message text
builder.TextBody = #"Hey Alice,
What are you up to this weekend? Monica is throwing one of her parties on
Saturday. I was hoping you could make it.
Will you be my +1?
-- Joey
";
// We may also want to attach a calendar event for Monica's party...
builder.Attachments.Add (#"C:\Users\Joey\Documents\party.ics");
// Now we just need to set the message body and we're done
message.Body = builder.ToMessageBody ();
For more information, see Creating Messages.

#jstedfast brought pretty cool solution, here are a few more examples of simple ways to just send a file as an attachment (pdf document in this case, but can be applied to any file type).
var message = new MimeMessage();
// add from, to, subject and other needed properties to your message
var builder = new BodyBuilder();
builder.HtmlBody = htmlContent;
builder.TextBody = textContent;
// you can either create MimeEntity object(s)
// this might get handy in case you want to pass multiple attachments from somewhere else
byte[] myFileAsByteArray = LoadMyFileAsByteArray();
var attachments = new List<MimeEntity>
{
// from file
MimeEntity.Load("myFile.pdf"),
// file from stream
MimeEntity.Load(new MemoryStream(myFileAsByteArray)),
// from stream with a content type defined
MimeEntity.Load(new ContentType("application", "pdf"), new MemoryStream(myFileAsByteArray))
}
// or add file directly - there are a few more overloads to this
builder.Attachments.Add("myFile.pdf");
builder.Attachments.Add("myFile.pdf", myFileAsByteArray);
builder.Attachments.Add("myFile.pdf", myFileAsByteArray , new ContentType("application", "pdf"));
// append previously created attachments
foreach (var attachment in attachments)
{
builder.Attachments.Add(attachment);
}
message.Body = builder.ToMessageBody();
Hope it helps.

You can also send multiple files using this approach directly.
**Note: files used here is IEnumerable files **
try
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress(emailService.FromFullName, emailService.FromEmail));
message.To.AddRange(emailsToSend.Select(x => new MailboxAddress(x)));
message.Subject = subject;
var builder = new BodyBuilder();
builder.HtmlBody = body;
foreach (var attachment in files)
{
if (attachment.Length > 0)
{
string fileName = Path.GetFileName(attachment.FileName);
builder.Attachments.Add(fileName, attachment.OpenReadStream());
}
}
message.Body = builder.ToMessageBody();
}

Related

Text/Plain Attachment content show up in body as well as in attachment

Environment: Windows 10,VisualStudio 2017,C#
Mailkit/Mimekit version 2.0.1
PROBLEM:Text/Plain Attachment content show up in body as well as in attachment. I do not won't attachment content to show up in body.
I am trying to create mail,using MimeKit.BodyBuilder class like this:
var mail = new MailMessage();
mail.To.Add(new MailboxAddress("name1","name1#def.com");
mail.From.Add(new MailboxAddress("name2","name2#def.com");
var builder = new BodyBuilder();
builder.textBody = "";
buider.Attachments.Add(file);
mail.body = builder.ToMessageBody(); //PROBLEM shows up here.
when I send this mail, iff attached file is of Text/Plain it is showing up in the body also. Note this problem doesn't occur when the attachment is xml,json.
Note, I am not explicitly setting content type as I am following the sample program provided in the MimeKit documentation.
I am enclosing BodyBuilder::ToMessageBody() relevant code below for your ready reference.
BEGIN CODE - MIMEKIT.....
public MimeEntity ToMessageBody ()
{
MultipartAlternative alternative = null;
MimeEntity body = null;
if (!string.IsNullOrEmpty (TextBody)) {
var text = new TextPart ("plain");
text.Text = TextBody;
if (!string.IsNullOrEmpty (HtmlBody)) {
alternative = new MultipartAlternative ();
alternative.Add (text);
body = alternative;
} else {
body = text;
}
}
....
if (Attachments.Count > 0) {
var mixed = new Multipart ("mixed");
if (body != null)
mixed.Add (body);
foreach (var attachment in Attachments)
mixed.Add (attachment);
body = mixed;
}
return body ?? new TextPart ("plain") { Text = string.Empty };
}
END CODE...MIMEKIT....
I'll appreciate someone can point out that problem.
thank you in advance,
regards Atish.
The problem is that you aren't setting a text or html body, so the receiving client shows the text attachment because it has nothing else to show.
I've changed the code so that if you set the TextBody to string.Empty, it just adds an empty inline text part as the message body, so now receiving clients should just show an empty body.

Add list-unsubscribe header with Amazon SES

I'm searching for an working C# example to add list-unsubscribe header with Amazon SES.
After reading that Amazon-SES now supports adding Headers I was searching for an C# example but was unable to find one.
I couldn't find nice API like they have for Java. For C#, I found two alternative.
The easiest option is probably to switch to the SMTP interface and .Net's native SMTP classes (or a third-party library): Send an Email Using SMTP with C#
The example code is using the MailMessage class from System.Net.Mail:
// Create and build a new MailMessage object
MailMessage message = new MailMessage();
message.IsBodyHtml = true;
message.From = new MailAddress(FROM,FROMNAME);
message.To.Add(new MailAddress(TO));
message.Subject = SUBJECT;
message.Body = BODY;
// Comment or delete the next line if you are not using a configuration set
message.Headers.Add("X-SES-CONFIGURATION-SET", CONFIGSET);
Another (less attractive) option is to use SendRawEmailRequest. With this API, you have to encode the message along with its headers, attachments, and other data, in a MemoryStream.
Example code, from the AWS SDK .Net documentation - SES - RawMessage:
var sesClient = new AmazonSimpleEmailServiceClient();
var stream = new MemoryStream(
Encoding.UTF8.GetBytes("From: johndoe#example.com\n" +
"To: janedoe#example.com\n" +
"Subject: You're invited to the meeting\n" +
"Content-Type: text/plain\n\n" +
"Please join us Monday at 7:00 PM.")
);
var raw = new RawMessage
{
Data = stream
};
var to = new List<string>() { "janedoe#example.com" };
var from = "johndoe#example.com";
var request = new SendRawEmailRequest
{
Destinations = to,
RawMessage = raw,
Source = from
};
sesClient.SendRawEmail(request);

MimeKit add attachments to a message loaded from mht file

Hi We are trying to develop a mail sending system using MailKit. We have a set of Email Templates which are created using WORD and saved as MHTML files. The whole thing is working fine, when we use MailKit to create a MimeMessage from the MHT file.
But post creating this message, I am not able to see a way of adding attachments to this.
Currently we are trying the following.
private void SendEmail(string templatePath, List<string> attachments)
{
// Load the MHT Template
var mimeMessage = MimeMessage.Load(templatePath);
mimeMessage.From.Add(new MailBoxAddress("test#Test.com"));
mimeMessage.To.Add(new MailBoxAddress("test#Test.com"));
foreach (var attachment in attachments)
{
var fileAttachment = new MimePart()
{
ContentObject = new ContentObject(File.OpenRead(Path.Combine(attachment), ContentEncoding.Default),
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Binary,
FileName = Path.GetFileName(attachment)
};
// Attachments is a read only Enumerable here.
mimeMessage.Attachments.Add
}
}
I add the attachment by the BodyBuilder:
BodyBuilder _body = new BodyBuilder
{
HtmlBody = message
};
_body.Attachments.Add(_fileName, _stream);
_email.Body = _body.ToMessageBody();
See this post stackoverflow
You will need to traverse the MIME tree structure of the message until you find the Multipart that you would like to add the "attachment" to and then use the Multipart.Add() method.
Keep in mind that a message is a nested tree structure and not a well-defined structure which has only 1 message body (or even just 2) and a list of attachments. It's a whole lot more complicated than that, so there's literally no way for MimeMessage.Attachments to "do the right thing".
For the general case, you can probably get away with something like this:
var message = MimeMessage.Load(fileName);
var attachment = new MimePart("application", "octet-stream") {
FileName = attachmentName,
ContentTransferEncoding = ContentEncoding.Base64,
Content = new MimeContent(attachmentStream)
};
if (!(message.Body is Multipart multipart &&
multipart.ContentType.Matches("multipart", "mixed"))) {
// The top-level MIME part is not a multipart/mixed.
//
// Attachments are typically added to a multipart/mixed
// container which tends to be the top-level MIME part
// of the message (unless it is signed or encrypted).
//
// If the message is signed or encrypted, though, we do
// do not want to mess with the structure, so the correct
// thing to do there is to encapsulate the top-level part
// in a multipart/mixed just like we are going to do anyway.
multipart = new Multipart("mixed");
// Replace the message body with the multipart/mixed and
// add the old message body to it.
multipart.Add(message.Body);
message.Body = multipart;
}
// Add the attachment.
multipart.Add(attachment);
// Save the message back out to disk.
message.WriteTo(newFileName);

Hiding Inline Attachments from Recipient

I'm trying to generate a MailMessage and set various attachments to it. The inline attachments always appear to the recipient as either jpeg, png, or other image files if I add them as an Attachment type. The code I used for this approach:
var mailMessage = new MailMessage();
// Set To, From, Body, Subject, etc.
foreach(var att in self.Attachments) {
byte[] content = att.GetBytes();
var attachment = new Attachment(new MemoryStream(content), att.Name);
if(att.IsInline){
attachment.ContentId = att.Name;
attachment.ContentDisposition.Inline = true;
attachment.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
}
mailMessage.Attachments.Add(attachment)
}
var view = AlternateView.CreateAlternateViewFromString(mailMessage.Body, Encoding.UTF8, MediaTypeNames.Text.Html);
mailMessage.AlternateViews.Add(view);
If I add them as a LinkedResource then they show up as dat files in the attachment section. Code:
var mailMessage = new MailMessage();
// Set To, From, Body, Subject, etc.
var view = AlternateView.CreateAlternateViewFromString(mailMessage.Body, Encoding.UTF8, MediaTypeNames.Text.Html);
foreach(var att in self.Attachments) {
byte[] content = att.GetBytes();
if(att.IsInline) {
var inline = new LinkedResource(new MemoryStream(content), att.ContentType);
inline.ContentId = att.Name;
view.LinkedResources.Add(inline);
}
else {
mailMessage.Attachments.Add(new Attachment(new MemoryStream(content),
att.Name));
}
}
mailMessage.AlternateViews.Add(view);
Both approaches generate the correct email and inject the inline attachments into the body of the email. Neither show the inline attachments in the attachment section while previewing the email in outlook. Both show the inline attachments when receiving the email in outlook. I have made sure that the outlook settings are as follows in the mail section of Outlook Options: "Compose message in this format: HTML" and "When sending messages in Rich Text format to Internet recipients: Convert to HTML format".
Any suggestions would be greatly appreciated as the additional attachments are creating confusion to the end users.
I stumbled on this question having had the same problem, and for me the solution was to add the type of the attachment.
Change this
var inline = new LinkedResource("logo.png");
To this
var inline = new LinkedResource("logo.png", "image/png");
It looks as if you are already doing this, but perhaps that wasn't working as intended?
Thanks to this page for providing the answer:
https://www.codeproject.com/articles/31897/embed-an-image-in-email-using-asp-net

Umlauts in iPhone v-card

I need to send e-mails to iPhone users with .vcf files for adding contacts. The problem is that contact name has umlaut symbols and they displays incorrectly.
Also I noticed that if I send the same text in the body of email or open composed vcf file in notepad the symbols displays correctly.
public void SendEmail(string to, string subject, string body)
{
using (var message = new MailMessage())
{
message.To.Add(new MailAddress(to));
message.Subject = subject;
message.SubjectEncoding = Encoding.UTF8;
message.BodyEncoding = Encoding.UTF8;
message.HeadersEncoding = Encoding.UTF8;
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(body)))
{
string attachamentName = string.Format("{0}.vcf", subject);
Attachment attachment = new Attachment(stream, MediaTypeNames.Application.Octet) { Name = attachamentName };
attachment.ContentDisposition.DispositionType = DispositionTypeNames.Attachment;
message.Attachments.Add(attachment);
using (var client = new SmtpClient())
{
client.Send(message);
}
}
}
}
Can someone please help me?
UPDATE: Sorry, have to edit code sample, I've accidentally submit the wrong one.
UPDATE #2: It looks like it is not only iPhone problem, Outlook also does not recognize umlauts.
UPDATE #3: Added full code for sending e-mail
Try changing to:
BEGIN:VCARD\r\nVERSION:2.1\r\nN;CHARSET=LATIN1:Fältskog;Agnetha\r\nFN;CHARSET=LATIN1:Agnetha Fältskog\r\nORG:\r\nTITLE:\r\nEND:VCARD
Just from reading elsewhere - looks like the format needs this CHARSET tag on each field, and seems that either LATIN1 or iso-8859-1 character sets, rather than utf-8 need to be specified for these.
Try to change
VERSION:2.1\r\n
to
VERSION:3.0\r\n
After that you don't need CHARSET-Tags for fields with umlauts,
it should work as expected.

Categories

Resources