Getting Started with SMTP, POP, & IMAP

IPWorks has components to work with the traditional mail protocols SMTP, POP, and IMAP. The guide below highlights each of these with examples. Working with modern mail REST API's (Office365, Gmail, etc.) is covered in our guide to Cloud Mail.

Introduction

SMTP sends mail, while IMAP and POP retrieve mail and manage mailboxes. All common authentication methods, as well as SSL/TLS connections, are supported and easily configured. Check out each section below for more.

Authentication

Authentication functions identically on all mail components. Set the AuthMechanism property to what the mail server expects. All AuthMechanisms other than amXOAUTH2 require setting User and Password. amXOAUTH2 examples can be found here.

This example will apply when using amUserPassword, amCRAMMD5, amNTLM, amAPOP, amSASLPlain, amSASLDigestMD5, and amKerberos.

Smtp mail = new Smtp();
mail.User = "MyUser";
mail.Password = "MyPassword";
mail.MailServer = "smtp.server.com";
mail.AuthMechanism = SmtpAuthMechanisms.amUserPassword; // Default
mail.Connect();

SMTP

Applicable Components: SMTP FileMailer HtmlMailer

IPWorks has several components for SMTP. The examples below use HtmlMailer and get progressively more advanced. The last example uses the SMTP and MIME components.

Send a Basic Email

Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "A Most Basic Email";
mail.MessageText = "Dear Madam,\n\nThis is just a plaintext message.\n\nRegards,\nJohn";
mail.Send();

Send an HTML Email

Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "A Simple HTML Email";
mail.MessageHTML = "<h2>A Title Might Go Here</h2><p>Followed by some text</p>";
// MessageText will automatically be populated with an equivalent plaintext
// representation of MessageHTML, unless overwritten.
mail.Send();

Embed an Image

There are three ways to embed an image into an HTML email.

// Provide filepath directly to src attribute
Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "An HTML Email with Embedded Image";
mail.MessageHTML = "<h2>A Title Might Go Here</h2><p>Followed by an image:</p><img src='C:\\path\\to\\image.jpg' />";
mail.Send();
// Add image and specify cid
Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "An HTML Email with Embedded Image";
mail.ParseHTML = false;
mail.MessageHTML = "<h2>A Title Might Go Here</h2><p>Followed by an image:</p><img src='cid:1234' />";
HTMLImage image = new HTMLImage("C:\\path\\to\\image.jpg");
image.ImageType = "image/jpeg";
image.Id = "1234";
mail.Images.Add(image);
mail.Send();
// Provide base64 data to src attribute
Netcode nc = new Netcode();
nc.DecodedFile = "C:\\path\\to\\image.jpg";
nc.Format = NetcodeFormats.fmtBase64;
nc.Encode();
string base64Image = nc.EncodedData;
Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "An HTML Email with Embedded Image";
mail.Config("ConvertImgData2CID=true");
mail.MessageHTML = "<h2>A Title Might Go Here</h2><p>Followed by an image:</p><img src='data:image/jpg;base64," + base64Image + "' />";
mail.Send();

Add an Attachment

Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "A Email with Attachment";
mail.MessageHTML = "<h2>A Title Might Go Here</h2><p>Please read this important attachment.</p>";
mail.AddAttachment("C:\\temp\\test.txt");
mail.Send();

Advanced Example using SMTP & MIME

This example uses SMTP and MIME together to send a message with a plaintext part, HTML part, embedded image, and attachment. This combination provides the most control when constructing a message.

// This type of email message is as a "nested" MIME message (i.e. There
// is one MIME message wrapped inside another MIME message).

string imagePath = "C:\\path\\to\\image.jpg";
string imageName = imagePath.Substring(imagePath.LastIndexOf(@"\") + 1);
string attachmentPath = "C:\\path\\to\\attachment.pdf";
string attachmentName = attachmentPath.Substring(attachmentPath.LastIndexOf(@"\") + 1);
string innerMime = "";
string innerMimeHeaders = "";
Mime m = new Mime();

// First the inner message needs to be constructed.  
// It contains the HTML and plaintext portions.
m.ContentType = "multipart/alternative";

m.Parts.Add(new MIMEPart());
m.Parts[0].ContentType = "text/plain";
m.Parts[0].Encoding = MIMEPartEncodings.peQuotedPrintable;
m.Parts[0].DecodedString = "Plaintext message goes here.";

m.Parts.Add(new MIMEPart());
m.Parts[1].ContentType = "text/html";
m.Parts[1].Encoding = MIMEPartEncodings.peQuotedPrintable;
m.Parts[1].DecodedString = "<html><p>HTML message goes here</p><img src='" + imageName + "' /></html>";

m.EncodeToString();

// Save the inner part for later
innerMime = m.Message;
innerMimeHeaders = m.MessageHeadersString;

m.Reset();

// Next construct the outer part, which contains the inner 
// part, an inline image, and pdf attachment.
m.ContentType = "multipart/related";

m.Parts.Add(new MIMEPart());
m.Parts[0].DecodedString = innerMime;
m.Parts[0].Encoding = MIMEPartEncodings.peBinary;
m.Parts[0].Headers = innerMimeHeaders;

m.Parts.Add(new MIMEPart());
m.Parts[1].ContentType = "image/jpeg; name='" + imageName + "'";
m.Parts[1].Encoding = MIMEPartEncodings.peBase64;
m.Parts[1].Headers += "Content-Location: " + imageName;
m.Parts[1].DecodedStringB = File.ReadAllBytes(imagePath);

m.Parts.Add(new MIMEPart());
m.Parts[2].ContentType = "application/pdf; name='" + attachmentName + "'";
m.Parts[2].ContentDisposition = "attachment; name='" + attachmentName + "'; filename='" + attachmentName + "'";
m.Parts[2].Encoding = MIMEPartEncodings.peBase64;
m.Parts[2].DecodedStringB = File.ReadAllBytes(attachmentPath);

m.EncodeToString();

// Send the constructed message with Smtp
Smtp mail = new Smtp();
mail.MailServer = "smtp.server.com";
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "An Advanced Email Made with MIME";
mail.OtherHeaders = m.MessageHeadersString;
mail.Message = m.Message;

try
{
  mail.Send();
}
catch (Exception ex) { Console.WriteLine(ex.Message); }

IMAP

Applicable Components: IMAP

Use the IMAP component to retrieve mail and manage mailboxes. To connect to a server, set MailServer and optionally MailPort, then call Connect. This will both connect and begin authentication with the server. Afterwards select a mailbox by setting Mailbox and calling SelectMailbox. Once selected other operations may be performed. Check out the examples below.

Connect to a MailServer

Imap mail = new Imap();
mail.MailServer = "imap.server.com";
mail.User = "user@server.com";
mail.Password = "YourPassword";
mail.Connect();

List Available Mailboxes

Imap mail = new Imap();
mail.OnMailboxList += (obj, ev) => Console.WriteLine(ev.Mailbox);
// ...
mail.ListMailboxes();

Select a Mailbox

Imap mail = new Imap();
// ...
mail.Mailbox = "INBOX";
mail.SelectMailbox();

List all Messages in a Mailbox

To get basic information about all messages in the selected Mailbox, first select all messages with MessageSet. Messages will be numbered 1 through MessageCount. Then call FetchMessageInfo. The MessageInfo event will fire for every selected message and has metadata like Id, Subject, From, and more.

Imap mail = new Imap();
mail.OnMessageInfo += (obj, ev) => Console.WriteLine(ev.Subject + " " + ev.From + " " + ev.MessageDate);
// ...
mail.SelectMailbox();
mail.MessageSet = "1:" + mail.MessageCount;
mail.FetchMessageInfo();

Save Raw Message

It may be beneficial to save the raw message in RFC 822 format. Use FetchMessageHeaders and FetchMessageText to populate MessageHeadersString and MessageText. Combine these into the raw message.

Imap mail = new Imap();
// ...
mail.MessageSet = "1";
mail.FetchMessageHeaders();
mail.FetchMessageText();
Console.WriteLine(mail.MessageHeadersString + mail.MessageText);

Save Attachments

An attachment will be encoded as a single part. First call FetchMessageInfo to populate MessageParts, then iterate over the collection calling FetchMessagePart for any detected attachments. If LocalFile is set to a file name, the part is stored there. Otherwise the contents are stored in MessageText.

Imap mail = new Imap();
// ...
mail.MessageSet = "1";
mail.FetchMessageInfo();
foreach(MessagePart p in mail.MessageParts)
{
  if (p.ContentDisposition.ToLower().Contains("attachment"))
  {
    mail.LocalFile = "C:\\path\\to\\" + p.Filename;
    mail.FetchMessagePart(p.Id);
    //Console.WriteLine(mail.MessageText); // Contains the part if LocalFile=""
  }
}

Delete Messages

Imap mail = new Imap();
// ...
mail.MessageSet = "1:23";
mail.DeleteFromMailbox(); // Marks message(s) with 'Deleted' flag
mail.ExpungeMailbox();    // Removes all messages with 'Deleted' flag

POP

Applicable Components: POP

Use the POP component to retrieve mail. To connect to a server, set MailServer and optionally MailPort, then call Connect. This will both connect and begin authentication with the server. Set MessageNumber to select a message to operate on. Check out the examples below.

Connect to a MailServer

Pop mail = new Pop();
mail.MailServer = "pop.server.com";
mail.User = "user@server.com";
mail.Password = "YourPassword";
mail.Connect();

List all Messages in a Mailbox

To get basic information about all messages in the selected Mailbox, iterate 1 through MessageCount while calling RetrieveHeaders. The Header event will fire for every message header which can be parsed for metadata like Subject, From, Date, and more.

Pop mail = new Pop();
// ... 
string subject, date, from = "";
mail.OnHeader += (obj, ev) =>
{
  switch (ev.Field.ToLower())
  {
    case ("subject"):
      subject = ev.Value;
      break;
    case ("date"):
      date = ev.Value;
      break;
    case ("from"):
      from = ev.Value;
      break;
  }
};
// ...
for(int x = 1; x <= mail.MessageCount; x++)
{
  subject = date = from = "";
  mail.MessageNumber = x;
  mail.RetrieveHeaders();
  Console.WriteLine(subject + " | " + from + " | " + date);
}

Save a Raw Message

Pop mail = new Pop();
// ...
int msgNum = 1;
mail.MessageNumber = msgNum;
mail.Retrieve();
Console.WriteLine(mail.MessageHeadersString + mail.MessageText);

Save a Raw Message To Disk

Pop mail = new Pop();
// ...
int msgNum = 1;
mail.Config("IncludeHeaders=true");
mail.LocalFile = "C:\\path\\to\\raw" + msgNum + ".eml";
mail.MessageNumber = msgNum;
mail.Retrieve();

Delete A Message

Pop mail = new Pop();
// ...
mail.MessageNumber = 1;
mail.Delete();

Using SSL & TLS

Connecting to a secure server over a SSL/TLS connection is easily done: set SSLStartMode and, if needed, MailPort. Each sslStartMode is detailed below.

  • sslImplicit: SSL/TLS negotations start immediately on a dedicated SSL/TLS port.
  • sslExplicit: STARTTLS is sent in plaintext to a port that may use both plaintext and SSL/TLS. If the server response indicates SSL/TLS is supported, then negotiations begin.

This example sends mail over an implicit TLS connection. SSLStartMode works exactly the same on all mail components.

Htmlmailer mail = new Htmlmailer();
mail.MailServer = "smtp.server.com";
mail.MailPort = 465;
mail.SSLStartMode = HtmlmailerSSLStartModes.sslImplicit;
mail.SendTo = "recipient@friendly.com";
mail.From = "sender@server.com";
mail.Subject = "A Most Basic Email";
mail.MessageText = "Dear Madam,\n\nThis is just a message.\n\nRegards,\nJohn";
mail.Send();

Below are the official IANA port numbers for SMTP, IMAP, and POP.

SMTP IMAP POP
Plaintext 25 143 110
SSL/TLS 4651/5872 993 995

1sslImplicit 2sslExplicit

Your server may use different port numbers.

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.