Rebex Mail Pack
IMAP, POP3, SMTP, EWS, MSG, MS Graph, MIME, S/MIME libraries for .NET
Download 30-day free trial Buy from $299More .NET libraries
-
Rebex File Transfer Pack
FTP and SFTP together
-
Rebex Total Pack
All Rebex .NET libraries together
Back to feature list...
MIME and MailMessage
On this page:
- High-level MailMessage API
- Support for many email formats
- Saving and loading
- Saving to MIME and Outlook MSG formats
- Plain text messages
- HTML messages
- Attachments
- Embedded messages
- Creating replies
- Custom headers
- Mail body views and resources
- Embedding images into HTML messages
- Loading TNEF/winmail.dat messages
- RTF to HTML converter
- Message options
- Low-level MIME API
High-level MailMessage API
Rebex.Mail.MailMessage
class represents an email message. It provides a simple high-level API
and supports numerous mail message formats.
// create Mail message var message = new Rebex.Mail.MailMessage(); // fill some fields message.From = "alice@example.org"; message.To = "bob@example.org"; message.Subject = "Test"; // add text and HTML bodies message.BodyText = "This is plain-text body."; message.BodyHtml = "This is <strong>HTML</strong> body."; // save message message.Save(@"C:\MyData\mail.eml"); // send message Smtp.Send(message, smtpServer);
' create Mail message Dim message = New Rebex.Mail.MailMessage() ' fill some fields message.From = "alice@example.org" message.To = "bob@example.org" message.Subject = "Test" ' add text and HTML bodies message.BodyText = "This is plain-text body." message.BodyHtml = "This is <strong>HTML</strong> body." ' save message message.Save("C:\MyData\mail.eml") 'send message Smtp.Send(message, smtpServer)
MimeMessage
class.
Support for many email formats
Rebex Mail Pack supports the following message formats:
- RFC 822/2822/5322 - Internet Message Format (often uses the '.eml' extension).
- MIME - Multipurpose Internet Mail Extensions. Adds support for attachments, HTML bodies, etc.
- UUEncode - legacy email extension. Adds support for attachments.
- Outlook MSG - MS Outlook native format (uses '.msg' extension).
- MS-TNEF - Microsoft's proprietary email extension format (also known as 'winmail.dat', a name used by its container attachments).
Note: MailMessage
class supports all of these formats. MimeMessage
only supports MIME and RFC 822/2822/5322.
A separate Rebex MSG library contains OutlookMessage
class which allows you to work
with Outlook .msg messages directly.
Saving and loading
MailMessage
and MimeMessage
objects can be easily saved to a disk or a stream.
The MailMessage
object is saved in MIME format by default, but also supports Outlook MSG format.
The MimeMessage
object only supports the MIME format.
// create mail var mail = new Rebex.Mail.MailMessage(); // fill some fields // ... // save mail to disk in MIME format mail.Save(@"C:\MyData\mail.eml"); // save mail to stream in MIME format var stream = new MemoryStream(); mail.Save(stream);
' create mail Dim mail = New Rebex.Mail.MailMessage() ' fill some fields ' ... ' save mail to disk mail.Save("C:\MyData\mail.eml") ' save mail to stream Dim stream = New MemoryStream() mail.Save(stream)
An existing mail message can be loaded from a disk or a stream.
MailMessage
object detects the message format automatically.
MimeMessage
object only supports the MIME format.
// load mail from disk var mail1 = new Rebex.Mail.MailMessage(); mail1.Load(@"C:\MyData\mail.eml"); // load mail from stream var mail2 = new Rebex.Mail.MailMessage(); mail2.Load(stream);
' load mail from disk Dim mail1 = New Rebex.Mail.MailMessage() mail1.Load("C:\MyData\mail.eml") ' load mail from stream Dim mail2 = New Rebex.Mail.MailMessage() mail2.Load(stream)
Note: When using MailMessage.Load
and MailMessage.Save
to load and save a single mail message,
you might not end up with an exact copy of the original message.
The copy will be equivalent to original, but its structure and headers might have been changed (normalized).
Additionally, when loading and saving Outlook MSG, some non-MIME headers may be lost (if necessary, you can prevent losing some headers by
setting enabling MailMessage.Options
' LoadMsgProperties).
Saving to MIME and Outlook MSG formats
To save an instance of MailMessage
object in specific format, use the MailFormat
argument:
// create mail var mail = new Rebex.Mail.MailMessage(); // fill some fields // ... // save mail as MIME message mail.Save(@"C:\MyData\mail.eml", MailFormat.Mime); // save mail as Outlook MSG message mail.Save(@"C:\MyData\mail.msg", MailFormat.OutlookMsg);
' create mail Dim mail = New Rebex.Mail.MailMessage() ' fill some fields ' ... ' save mail as MIME message mail.Save("C:\MyData\mail.eml", MailFormat.Mime) ' save mail as Outlook MSG message mail.Save("C:\MyData\mail.msg", MailFormat.OutlookMsg)
Plain text messages
Plain text messages only contain a single 'text/plain' body and no attachments or resources. To create such message, only set the MailMessage.BodyText
property:
// create mail var mail = new Rebex.Mail.MailMessage(); // fill some fields // ... // add plain-text body mail.BodyText = "This is a plain-text body.";
' create mail Dim mail = New Rebex.Mail.MailMessage() ' fill some fields ' ... ' add plain-text body mail.BodyText = "This is a plain-text body."
HTML messages
HTML messages contains a 'text/html' body. To create such message, set the MailMessage.BodyHtml
property:
// create mail var mail = new Rebex.Mail.MailMessage(); // fill some fields // ... // add HTML body mail.BodyHtml = "This is an <strong>HTML</strong> body.";
' create mail Dim mail = New Rebex.Mail.MailMessage() ' fill some fields ' ... ' add HTML body mail.BodyHtml = "This is an <strong>HTML</strong> body."
Note: It's recommended to set BodyText
property as well to a plain text version of the HTML text.
This makes the message compatible recipients that don't support HTML or prefer plain text.
Attachments
To add an attachment to a mail message, use the Add
method on the MailMessage.Attachments
collection.
It is recommended to specify attachment's content type as well to make it possible for the receiving application to determine the attachment kind. Some e-mail clients
require this to display the attachments correctly.
// create mail var mail = new Rebex.Mail.MailMessage(); // add an attachment var attachment = new Attachment(@"C:\MyData\file.txt", null, Rebex.Mail.MediaTypeNames.Text.Plain); mail.Attachments.Add(attachment);
' create mail Dim mail = New Rebex.Mail.MailMessage() ' add an attachment Dim attachment = New Attachment("C:\MyData\file.txt", Nothing, Rebex.Mail.MediaTypeNames.Text.Plain) mail.Attachments.Add(attachment)
On the other side, when you are the receiver of the mail message, you can access to messages attachments through MailMessage.Attachments
collection
and read useful properties from the Attachment
object:
// print some info about mail attachments Console.WriteLine("Attachments: {0}", mail.Attachments.Count); foreach (Attachment att in mail.Attachments) { Console.WriteLine("{0} ({1}) [{2} B]", att.FileName, att.ContentType.MediaType, att.GetContentLength()); }
' print some info about mail attachments Console.WriteLine("Attachments: {0}", mail.Attachments.Count) For Each att As Attachment In mail.Attachments Console.WriteLine("{0} ({1}) [{2} B]", att.FileName, att.ContentType.MediaType, att.GetContentLength()) Next
Note: A special kind of attachments are called 'resources' and can be found in MailMessage.Resources
collection that resembles the Attachments
collection.
Unlike attachments, resources are supposed to contain embedded images and/or other media used by one of the message bodies (typically the HTML body).
Embedded messages
In addition to ordinary attachments that represent an attached file, Rebex Mail Pack supports
attached messages. Unlike ordinary attachments, these are parsed as MailMessage
or MimeMessage
objects and are
accessible through Attachment
object's ContentMessage
property.
// create mail message var mail = new Rebex.Mail.MailMessage(); mail.Subject = "Mail message"; // ... // create mail message to be embedded var embedded = new Rebex.Mail.MailMessage(); embedded.Subject = "Embedded message"; // ... // add the embedded message as an attachment mail.Attachments.Add(new Attachment(embedded));
' create mail message Dim mail = New Rebex.Mail.MailMessage mail.Subject = "Mail message" ' ... ' create mail message to be embedded Dim embedded = New Rebex.Mail.MailMessage embedded.Subject = "Embedded message" ' ... ' add the embedded message as an attachment mail.Attachments.Add(New Attachment(embedded))
Creating replies
MailMessage.CreateReply
method
makes it possible to easily create a reply to a specified message - it transfers the appropriate headers for you:
// create SMTP and IMAP client instances, connect, log in // ... // download a message to reply to MailMessage original = imap.GetMailMessage(uniqueId); // reply to all MailMessage reply = original.CreateReply("joe@example.org", ReplyBodyTransformation.None, true); reply.BodyText = "Hello, I agree.\n" + original.BodyText; // send the reply smtp.Send(reply);
' create SMTP And IMAP client instances, connect, log in ' ... ' download a message to reply to Dim original As MailMessage = imap.GetMailMessage(uniqueId) ' reply to all Dim reply As MailMessage = original.CreateReply("joe@example.org", ReplyBodyTransformation.None, True) reply.BodyText = "Hello, I agree.\n" & original.BodyText ' send the reply smtp.Send(reply)
Custom headers
Message headers are commonly used to store various e-mail metadata (such as
spam filtering score or mail agent name).
Both built-in and custom message headers can be accessed and manipulated using the Headers
collection,
available in both MailMessage
and MimeMessage
objects.
For example, to request delivery notification from the recipient, add the Disposition-Notification-To
header
before sending the message:
// create a new message var mail = new MailMessage(); // initialize it mail.From = "joe@example.org"; mail.To = "john@example.org"; // and request the read receipt mail.Headers.Add("Disposition-Notification-To", "joe@example.org");
' create a new message Dim mail = New MailMessage() ' initialize it mail.From = "joe@example.org" mail.To = "john@example.org" ' and request the read receipt mail.Headers.Add("Disposition-Notification-To", "joe@example.org")
Note: Not all mail clients support DSN requests and most of those that do ask the user for permission before sending them.
Mail body views and resources
A mail message can contain couple of alternate views of the message body.
The most common case is that the message contains a formated HTML body and a plain-text body.
These two views can be accessed with MailMessage.BodyText
and MailMessage.BodyHtml
properties.
However, if you need more control over the views or if you need to work with views that are not HTML or plain-text,
the MailMessage
object provides AlternateViews
collection (see RTF to HTML convertor sample code).
In addition to AlternateViews
, the MailMessage
object provides a related
Resources
collection. It is simmilar to Attachments
collection, but
contains items linked from within the HTML body (such as embedded images).
Embedding images into HTML messages
Embedding an image into an HTML message consists of three steps:
- Generate a CID (content ID) to identify the image.
- Include
<img src='cid:ImageId' />
element within the HTML body. - Add the image to collection of linked resources, with its
Content-ID
set.
// create mail var mail = new Rebex.Mail.MailMessage(); // fill some fields // ... // generate a content ID for the image string imageId = "image001@rebex.net"; // add HTML body mail.BodyHtml = string.Format("This is embedded image: <img src='cid:{0}'/>", imageId); // add image to linked resources var resource = new Rebex.Mail.LinkedResource( @"C:\MyData\image.jpg", Rebex.Mail.MediaTypeNames.Image.Jpeg); resource.ContentId = imageId; mail.Resources.Add(resource);
' create mail Dim mail = New Rebex.Mail.MailMessage() ' fill some fields ' ... ' generate a content ID for the image Dim imageId = "image001@rebex.net" ' add HTML body mail.BodyHtml = String.Format("This is embedded image: <img src='cid:{0}'/>", imageId) ' add image to linked resources Dim resource = New Rebex.Mail.LinkedResource( "C:\MyData\image.jpg", Rebex.Mail.MediaTypeNames.Image.Jpeg) resource.ContentId = imageId mail.Resources.Add(resource)
Loading TNEF/winmail.dat messages
Microsoft Outlook makes it possible to create a mail message in three formats: plain text, HTML and RTF.
Unlike plain text and HTML, a RTF message is created in proprietary format called MS-TNEF, which is also known as winmail.dat. It is a MIME message with a single attachment (called 'winmail.dat' or 'win.dat') that contains the actual content of the message (the RTF body and all attached objects) in a non-standard format that is notorious for being incomatible with a large number of third-party email clients.
When loading a message to MailMessage
object, the attached MS-TNEF file is parsed and the whole message is converted into a standard MIME format.
Because almost no third-party email clients supports MIME messages with RTF bodies, the MailMessage
object converts the RTF body to HTML and adds both
forms to MailMessage.AlternateViews
collection (as "text/rtf" and "text/hmtl", which is accessible through MailMessage.BodyHtml
).
The original attached objects from winmail.dat are made accessible by MailMessage.Attachments
collection as common attachments.
Following code shows, how to load MS-TNEF message, get the RTF body and its HTML equivalent:
// load TNEF mail var mail = new Rebex.Mail.MailMessage(); mail.Load(@"C:\MyData\TNEF-mail.eml"); // get the HTML equivalent of RTF body string html = mail.BodyHtml; // find the original RTF body string rtf = null; foreach (AlternateView view in mail.AlternateViews) { if (view.ContentType.MediaType == Rebex.Mail.MediaTypeNames.Text.Rtf) rtf = view.ContentString; }
' load TNEF mail Dim mail = New Rebex.Mail.MailMessage() mail.Load("C:\MyData\TNEF-mail.eml") ' get the HTML equivalent of RTF body Dim html As String = mail.BodyHtml ' find the original RTF body Dim rtf As String = Nothing For Each view As AlternateView In mail.AlternateViews If view.ContentType.MediaType = Rebex.Mail.MediaTypeNames.Text.Rtf Then rtf = view.ContentString End If Next
RTF to HTML converter
The MailMessage
class contains RTF to HTML convertor, to make displaying emails easier (since HTML is more supported than RTF).
The conversion is applied when loading a MailMessage
with RTF body (most often when loading MS-TNEF or Outlook MSG messages).
However, you can easily utilize this functionality to convert RTF text to HTML:
// create RTF stream string rtfString = @"{\rtf1\ansi This is \b rich\b0 \i text\i0}"; var rtfStream = new MemoryStream(Encoding.ASCII.GetBytes(rtfString)); // create mail with RTF body var view = new Rebex.Mail.AlternateView(rtfStream, Rebex.Mail.MediaTypeNames.Text.Rtf); var mail = new Rebex.Mail.MailMessage(); mail.AlternateViews.Add(view); // save mail to stream var stream = new MemoryStream(); mail.Save(stream); // load mail from stream stream.Position = 0; mail.Load(stream); // get converted HTML text string html = mail.BodyHtml;
' create RTF stream Dim rtfString As String = "{\rtf1\ansi This is \b rich\b0 \i text\i0}" Dim rtfStream = New MemoryStream(Encoding.ASCII.GetBytes(rtfString)) ' create mail with RTF body Dim view = New Rebex.Mail.AlternateView(rtfStream, Rebex.Mail.MediaTypeNames.Text.Rtf) Dim mail = New Rebex.Mail.MailMessage() mail.AlternateViews.Add(view) ' save mail to stream Dim stream = New MemoryStream() mail.Save(stream) ' load mail from stream stream.Position = 0 mail.Load(stream) ' get converted HTML text Dim html As String = mail.BodyHtml
Message options
The MailMessage
and MimeMessage
objects have the Options
property,
which makes it possible to tweak various behaviors.
The following code only loads the message headers. It is useful, when you have a lot of messages, but you only need to display basic info stored in headers (loading and parsing whole message would be slow).
// create mail var mail = new Rebex.Mail.MailMessage(); // set option to parse only headers mail.Settings.OnlyParseHeaders = true; // load headers of the message mail.Load(@"C:\MyData\mail.eml"); // print some values stored in headers Console.WriteLine("Date: {0}", mail.Date); Console.WriteLine("From: {0}", mail.From); Console.WriteLine("To: {0}", mail.To); Console.WriteLine("Subject: {0}", mail.Subject);
' create mail Dim mail = New Rebex.Mail.MailMessage() ' set option to parse only headers mail.Settings.OnlyParseHeaders = True ' load headers of the message mail.Load("C:\MyData\mail.eml") ' print some values stored in headers Console.WriteLine("Date: {0}", mail.Date) Console.WriteLine("From: {0}", mail.From) Console.WriteLine("To: {0}", mail.To) Console.WriteLine("Subject: {0}", mail.Subject)
Low-level MIME API
Rebex.Mime.MimeMessage
class represents a MIME message. It provides a low-level API for
manipulating the tree of MIME entities and can be even used to work with MIME entities that don't represent
mail messages. It gives you more control, but it's not as simple as MailMessage
.
MimeMessage
object gives you full control over the MIME entity tree.
This can be useful, but it also leads to more complicated code compared to MailMessage
object.
The following code generates a simple mail message:
// create MIME message var mime = new Rebex.Mime.MimeMessage(); // fill some fields mime.From = "joe@example.org"; mime.To = "john@example.org"; mime.Subject = "Test"; // set correct content-type of MIME message mime.ContentType = new ContentType("multipart/mixed"); // add text and HTML bodies { // create new node for MIME tree var bodies = new Rebex.Mime.MimeEntity(); // set correct content-type for MIME bodies bodies.ContentType = new ContentType("multipart/alternative"); // add text body var bodyText = new Rebex.Mime.MimeEntity(); bodyText.SetContent("This is plain-text body.", Rebex.Mail.MediaTypeNames.Text.Plain); bodies.Parts.Add(bodyText); // add HTML body var bodyHtml = new Rebex.Mime.MimeEntity(); bodyHtml.SetContent("This is <strong>HTML</strong> body.", Rebex.Mail.MediaTypeNames.Text.Html); bodies.Parts.Add(bodyHtml); mime.Parts.Add(bodies); } // add an attachment var attachment = new Rebex.Mime.MimeEntity(); attachment.ContentDisposition = new ContentDisposition("attachment"); attachment.SetContentFromFile(@"C:\MyData\file.txt", "file.txt", Rebex.Mail.MediaTypeNames.Text.Plain); mime.Parts.Add(attachment);
' create MIME message Dim mime = New Rebex.Mime.MimeMessage() ' fill some fields mime.From = "joe@example.org" mime.To = "john@example.org" mime.Subject = "Test" ' set correct content-type of MIME message mime.ContentType = New ContentType("multipart/mixed") ' add text and HTML bodies If True Then ' create new node for MIME tree Dim bodies = New Rebex.Mime.MimeEntity() ' set correct content-type for MIME bodies bodies.ContentType = New ContentType("multipart/alternative") ' add text body Dim bodyText = New Rebex.Mime.MimeEntity() bodyText.SetContent("This is plain-text body.", Rebex.Mail.MediaTypeNames.Text.Plain) bodies.Parts.Add(bodyText) ' add HTML body Dim bodyHtml = New Rebex.Mime.MimeEntity() bodyHtml.SetContent("This is <strong>HTML</strong> body.", Rebex.Mail.MediaTypeNames.Text.Html) bodies.Parts.Add(bodyHtml) mime.Parts.Add(bodies) End If ' add an attachment Dim attachment = New Rebex.Mime.MimeEntity() attachment.ContentDisposition = New ContentDisposition("attachment") attachment.SetContentFromFile("C:\MyData\file.txt", "file.txt", Rebex.Mail.MediaTypeNames.Text.Plain) mime.Parts.Add(attachment)
MimeMessage
makes it possible to access low-level functionality that is hidden by MailMessage
.
For example, it can be used to contruct any kind of MIME tree or to add adding custom header to attachments:
// create an attachment var attachment = new Rebex.Mime.MimeEntity(); attachment.ContentDisposition = new ContentDisposition("attachment"); attachment.SetContent(source); // add custom header to the attachment attachment.Headers.Add("X-My-Header-Name", "Some value");
' create an attachment Dim attachment = New Rebex.Mime.MimeEntity() attachment.ContentDisposition = New ContentDisposition("attachment") attachment.SetContent(source) ' add custom header to the attachment attachment.Headers.Add("X-My-Header-Name", "Some value")
Tip: Unless you need to work directly with the MIME tree and its entities, we strongly recommend using the simpler
MailMessage
object.
MailMessage
, which supports RFC 822/2822/5322, MIME, UUEncode, Outlook MSG and MS-TNEF (winmail.dat),
the MimeMessage
object only supports RFC 822/2822/5322 and MIME.
Back to feature list...