Reply to an email

You can use Mail.dll to easy reply to an HTML and plain-text emails.

ReplyBuilder class allows you to specify custom HTML and plain-text reply templates. Mail.dll will parse HTML, extract body part, and build-in template engine will do the rest to create nicely formatted reply with all attachments, To and Cc fields set.

The next great thing is that plain-text version of the email is generated automatically.

You can also take advantage of ReplyAll method that makes it easy to reply to all: senders of the message and all To and Cc recipients

In our example we’ll use Mail.dll .NET IMAP component to download first message from an IMAP server. Then we’ll use ReplyBuilder to create a reply email message. Finally we’ll use Mail.dll SMTP client to send this message.

// C#

IMail original = GetFirstMessage();

ReplyBuilder replyBuilder = original.Reply();

// You can specify your own, custom, body and subject templates:
replyBuilder.HtmlReplyTemplate = @"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">
    <html>
    <head>
        <meta http-equiv=""Content-Type"" content=""text/html; charset=UTF-8"" />
        <title>[Subject]</title>
    </head>
    <body>
    [Html]
    <br /><br />
    On [Original.Date] [Original.Sender.Name] wrote:
    <blockquote style=""margin-left: 1em; padding-left: 1em; border-left: 1px #ccc solid;"">
        [QuoteHtml]
    </blockquote>
    </body>
    </html>";
replyBuilder.SubjectReplyTemplate = "Re: [Original.Subject]";

replyBuilder.Html = "Alice, <br/><br/>thanks for your email.";

MailBuilder builder = replyBuilder.ReplyToAll(
    new MailBox("bob@example.org", "Bob"));

// You can add attachments to your reply
//builder.AddAttachment("report.csv");

IMail reply = builder.Create();

using (Smtp smtp = new Smtp())
{
    smtp.Connect("smtp.example.com"); // or ConnectSSL
    smtp.UseBestLogin("user", "password");
    smtp.SendMessage(reply);
    smtp.Close();
}

static IMail GetFirstMessage()
{
    IMail email;
    using (Imap imap = new Imap())
    {
        imap.Connect("imap.example.com"); // or ConnectSSL if you want to use SSL
        imap.UseBestLogin("user", "password");
        List<long> uids = imap.GetAll();
        if (uids.Count == 0)
            throw new Exception("There are no messages");
        var eml = imap.GetMessageByUID(uids[0]); 
        email = new MailBuilder().CreateFromEml(eml);                
        imap.Close();
    }
    return email;
}
' VB.NET

Dim original As IMail = GetFirstMessage()

Dim replyBuilder As ReplyBuilder = original.Reply()

' You can specify your own, custom, body and subject templates:
replyBuilder.HtmlReplyTemplate = _
"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">" + _
" <html>" +  _
" <head>" +  _
"    <meta http-equiv=""Content-Type"" content=""text/html; charset=UTF-8"" />" +  _
"    <title>[Subject]</title>" +  _
" </head>" +  _
" <body>" +  _
"  [Html]" +  _
"  <br /><br />" +  _
"  On [Original.Date] [Original.Sender.Name] wrote:" +  _
"  <blockquote style=""margin-left: 1em; padding-left: 1em; border-left: 1px #ccc solid;"">" +  _
"    [QuoteHtml]" +  _
"  </blockquote>" +  _
" </body>" +  _
" </html>"
replyBuilder.SubjectReplyTemplate = "Re: [Original.Subject]"

Dim builder As MailBuilder = replyBuilder.ReplyToAll( _
    New MailBox("bob@example.org", "Bob"))

' You can add attachments to your reply
'builder.AddAttachment("report.csv")

Dim reply As IMail = builder.Create()

Using smtp As New Smtp()
	smtp.Connect("smtp.example.com") ' or ConnectSSL
	smtp.UseBestLogin("user", "password")
	smtp.SendMessage(reply)
	smtp.Close()
End Using

Private Shared Function GetFirstMessage() As IMail
	Dim email As IMail
	Using imap As New Imap()
		imap.Connect("imap.example.com")
		' or ConnectSSL if you want to use SSL
		imap.UseBestLogin("user", "password")
		Dim uids As List(Of Long) = imap.GetAll()
		If uids.Count = 0 Then
			Throw New Exception("There are no messages")
		End If
		Dim eml = imap.GetMessageByUID(uids(0))
		email = New MailBuilder().CreateFromEml(eml)
		imap.Close()
	End Using
	Return email
End Function

In the reply templates (HtmlReplyTemplate, TextReplyTemplate, SubjectReplyTemplate) you have access to following fields:

  • string Subject – subject of the reply (e.g. [Subject])
  • string Text – plain text of the reply (e.g. [Test])
  • string Html – html of the reply (e.g. [Html])
  • string QuoteText – original text quoted using ‘>’ chars (e.g. [QuoteText])
  • string QuoteHtml – body contents of original html or original text converted to html (e.g. [QuoteHtml])
  • IMail Original – original email you are relying to and all its properties (e.g. [Original.Subject], [Original.Sender.Address])

Please note that you can use any template and data to generate actual reply email (ReplyBuilder.Html and ReplyBuilder.Text).

Extract plain text from HTML email

Mail.dll MIME and email component may be used to get the plain-text body and HTML body from any email message.

If a message contains plain-text, no conversion is necessary. It’s simply a matter of using the Text property of IMail interface.

If however the email does not contain plain-text and only HTML content is available, GetTextFromHtml method may be used to convert the HTML to plain-text.

The internal conversion process is much more sophisticated than what can be accomplished with the simple regular-expression code. Converting HTML to plain text is much more than simply removing HTML tags from an HTML document.

Mail.dll contains full-blown HTML parser that handles script tags, comments, CDATA and even incorrectly formatted HTML.

The following C# and VB.NET code extracts plain-text from the HTML body of the email message:

// C#

IMail email = ...

string text = ""; 
if (email.IsText)
    text = email.Text;
else if (email.IsHtml)
    text = email.GetTextFromHtml();
Console.WriteLine(text);

' VB.NET

Dim email As IMail = ...

Dim text As String = ""
If email.IsText Then
    text = email.Text
ElseIf email.IsHtml Then
    text = email.GetTextFromHtml()
End If
Console.WriteLine(text)

You can also use GetBodyAsText method that returns body in plain text format (it uses IMail.Text property or GetTextFromHtml method).

// C#

IMail email = ...

string text = email.GetBodyAsText();
Console.WriteLine(text);

' VB.NET

Dim email As IMail = ...

Dim text As String = email.GetBodyAsText()
Console.WriteLine(text)

Send email to multiple recipients

In this post we’ll show how to send email message to multiple recipients.

If your email should look differently for each recipient (customized “Hello [FirstName] [LastName]” message) take a look at:

If your email looks exactly the same for each recipient the easiest way is to use BCC field (Blind-Carbon-Copy), and specify Undisclosed recipients group as the message recipient:

MailBuilder builder = new MailBuilder();
builder.From.Add(new MailBox("alice@example.com", "Alice"));

builder.To.Add(new MailGroup("Undisclosed recipients"));

builder.Bcc.Add(new MailBox("bob@example.com", "Bob"));
builder.Bcc.Add(new MailBox("tom@example.com", "Tom"));
builder.Bcc.Add(new MailBox("john@example.com", "John"));

Here’s entire sample, that creates email message, connects to SMTP server and sends the message:

// C# version

MailBuilder builder = new MailBuilder();
builder.From.Add(new MailBox("alice@example.com", "Alice"));

builder.To.Add(new MailGroup("Undisclosed recipients"));

builder.Bcc.Add(new MailBox("bob@example.com", "Bob"));
builder.Bcc.Add(new MailBox("tom@example.com", "Tom"));
builder.Bcc.Add(new MailBox("john@example.com", "John"));

builder.Subject = "Put subject here";
builder.Html = "Put <strong>HTML</strong> message here.";

// Plain text is automatically generated, but you can change it:
//builder.Text = "Put plain text message here.";

IMail email = builder.Create();

// Send the message
using (Smtp smtp = new Smtp())
{
    smtp.Connect("server.example.com");   // or ConnectSSL for SSL
    smtp.UseBestLogin("user", "password"); // remove if not needed

    smtp.SendMessage(email);

    smtp.Close();
}
' VB.NET version

Dim builder As New MailBuilder()
builder.From.Add(New MailBox("alice@example.com", "Alice"))
builder.[To].Add(New MailGroup("Undisclosed recipients"))

builder.Bcc.Add(New MailBox("bob@example.com", "Bob"))
builder.Bcc.Add(New MailBox("tom@example.com", "Tom"))
builder.Bcc.Add(New MailBox("john@example.com", "John"))

builder.Subject = "Put subject here"
builder.Htm = "Put <strong>HTML</strong> message here."

' Plain text is automatically generated, but you can change it:
'builder.Text ="Put plain text message here."

Dim email As IMail = builder.Create()

' Send the message
Using smtp As New Smtp()
	smtp.Connect("server.example.com")    ' or ConnectSSL for SSL
	smtp.UseBestLogin("user", "password")  ' remove if not needed

	smtp.SendMessage(email)

	smtp.Close()
End Using

Save raw eml file using IMAP and POP3

There are times that you need to save raw email data in eml format.

This tutorial shows how to use Mail.dll POP3 and IMAP clients to achieve this goal.

Note that we don’t need to parse the emails, so we aren’t using MailBuilder class and IMail interface.

Samples provided use both POP3 and IMAP protocols and both C# and VB.NET.

Save email using IMAP:

The code below will search for all the emails with specified subject and write all these emails to your c: drive.

// C# code

using (Imap imap = new Imap())
{
    imap.Connect("imap.example.com");    // use ConnectSSL for SSL connection.
    imap.UseBestLogin("user", "password");

    imap.SelectInbox();

    List<long> uids = imap.Search(
        Expression.Subject("email subject"));

    foreach (long uid in uids)
    {
        var eml = imap.GetMessageByUID(uid);
        string fileName = string.Format(@"c:\email_{0}.eml", uid);
        File.WriteAllBytes(fileName, eml);
    }
    imap.Close();
}
' VB.NET code

Using imap As New Imap()
	imap.Connect("imap.example.com")    ' use ConnectSSL for SSL connection.
	imap.UseBestLogin("user", "password")

	imap.SelectInbox()

	Dim uids As List(Of Long) = imap.Search( _
		Expression.Subject("email subject"))

	For Each uid As Long In uids
		Dim eml = imap.GetMessageByUID(uid)
		Dim fileName As String = String.Format(@"c:\email_{0}.eml", uid)
		File.WriteAllBytes(fileName, eml)
	Next
	imap.Close()
End Using

Save email using POP3:

As POP3 protocol does not allow searching, the code below will write all emails to your c: drive. You can easily limit this to the specified uid.

// C# code

using (Pop3 pop3 = new Pop3())
{
    pop3.Connect("pop3.example.com");    // use ConnectSSL for SSL connection.
    pop3.UseBestLogin("user", "password");

    foreach (string uid in pop3.GetAll())
    {
        var eml = pop3.GetMessageByUID(uid));
        string fileName = string.Format(@"c:\email_{0}.eml", uid);
        File.WriteAllBytes(fileName, eml);
    }
    pop3.Close();
}
' VB.NET code

Using pop3 As New Pop3()
	pop3.Connect("pop3.example.com")    'use ConnectSSL for SSL connection.
	pop3.UseBestLogin("user", "password")

  For Each uid As String In pop3.GetAll()
		Dim eml = pop3.GetMessageByUID(uid)
		Dim fileName As String = String.Format("c:\email_{0}.eml", uid)
		File.WriteAllBytes(fileName, eml)
	Next
	pop3.Close()
End Using

You can download Mail.dll at: Mail.dll .NET email component

Import certificate, private or public keys (PEM, CER, PFX)

Encrypted private key, RSA private key in PEM file

PEM stands for Privacy Enhanced Mail format. The PEM format is the most common format that Certificate Authorities issue certificates in. PEM certificates usually have extensions such as .pem, .crt, .cer, and .key. They are Base64 encoded ASCII files.

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadEncryptedPrivateKeyFromFile(
   "EncryptedPrivateKey.pem", // "EncryptedRSAPrivateKey.pem"
   "cypher");

This code handles following formats:

PKCS #8 EncryptedPrivateKeyInfo Encrypted Format:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICojAcBgoqhkiG9w0BD .....

Private Key (Traditional SSLeay RSAPrivateKey format) Encrypted:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,24A667C253F8A1B9

mKz .....

You can remove the passphrase from the private key using openssl:
openssl rsa -in EncryptedPrivateKey.pem -out PrivateKey.pem

Unencrypted private key in PEM file

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadPrivateKeyFromFile("PrivateKey.pem");

This code handles following formats:

PKCS #8 PrivateKeyInfo Unencrypted:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0B ......

Private Key (Traditional SSLeay RSAPrivateKey format) Unencrypted:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCcHVm .....

Public key in PEM file

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadPublicKeyFromFile("PublicKey.pem")

This code handles following formats:

Public Key (SubjecPublicKeyInfo):

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEB .....

Certificate/private key in PFX file

X509Certificate2 certificate  = new X509Certificate2(
   "certificate.pfx",
   "",
   X509KeyStorageFlags.PersistKeySet)

if (certificate.HasPrivateKey)
{
  using (var rsa = (RSACryptoServiceProvider)certificate.PrivateKey)
  {
    // ...
  }
}

Certificate in PEM/CER file

Note: The private key is never stored in a .pem/.cer certificate file.

X509Certificate2 certificate = new X509Certificate2("certificate.cer");

-or-

PemReader pem = new PemReader();
X509Certificate2 certificate = pem.ReadCertificateFromFile("certificate.cer");

This code handles following formats:


-----BEGIN CERTIFICATE-----
MIIFsTCCA5mgAwIBAgIKYQ .....