To retrieve messages from e-mail servers, you can use MailBee.NET IMAP and MailBee.NET POP3 components. Their main classes are Imap and Pop3, respectively.
These classes can also be used to manage e-mails and folders, such as delete messages, move them between folders, upload into a folder, search messages for various criteria, manage folders, and so on. Some of this extra functionality is available only with IMAP.
E-mail messages can be downloaded completely (with all the text bodies and attachments), header-only, and mixed mode (such as headers and text body but no attachments). Again, only IMAP provides the full set of features.
Once the e-mail is downloaded, you can parse it, examine any of its properties, work with attachments, embedded pictures and other linked resources , save it into a file or stream, and process it in any other way. And you can send it again (for instance, create a reply to the message and then send the reply with MailBee.NET SMTP component).
The file format of e-mails which is used by SMTP, IMAP and POP3 protocols is called MIME. Therefore, the main class which represents an e-mail message in MailBee.NET is MailBee.Mime.MailMessage. This class can both parse and build e-mails in MIME format.
Imap and Pop3 classes return downloaded e-mails as MailMessage objects (for single e-mails) and collections (for ranges of e-mails).
Also, IMAP protocol can return some additional information with the message, which is called envelope. Thus, when using Imap class, you'll be mostly dealing with collections of envelopes rather than messages. Of course, an IMAP envelope provides access to the contained e-mail message as well.
The POP3 protocol is very simple and provides only basic features of e-mail retrieval.
The IMAP protocol (also known as IMAP4) provides much more functions and should be used whenever possible.
The only reason to prefer POP3 is if your server simply does not support IMAP (for instance, built-in e-mail server of MS Windows Server 2003/2008).
Note that MS Exchange DOES support IMAP (although it can be turned off by default, but the same is true for POP3). Moreover, some popular services like Gmail.com simply do not work with POP3 correctly.
E-mail retrieval and management | IMAP | POP3 |
---|---|---|
Get entire message with attachments | + | + |
Get multiple entire messages | + | + |
Get message header of one or multiple e-mails | + | + |
Get message header and the beginning of body section (body preview) | + | + |
Detect attachments without downloading entire e-mail | + | +/- |
Discover attachment filenames without downloading entire e-mail | + | |
Get text body without downloading entire e-mail | + | |
Get particular attachments without downloading entire e-mail | + | |
Search for new e-mails | + | +/- |
Search for any criteria | + | |
Message flags (Seen, Answered, Flagged, etc) | + | |
Server folders other than Inbox (Drafts, Trash, etc) | + | |
E-mail push (instant notification on new e-mail arrival - IDLE) | +/? | |
Message envelope (e.g. e-mail arrival date) | + | |
Get mailbox quota | +/? | |
Upload e-mail to server | + | |
Copy or move e-mails between folders | + | |
Custom commands | + | + |
Secure authentication | + | + |
Integrated Windows Authentication | + | + |
OAuth 2.0 with Gmail | + | + |
OAuth 2.0 with Outlook.com, Live.com, Hotmail.com | + | |
Connection via proxy (SOCKS4, SOCKS5, HTTP) | + | + |
Exceptions and error codes | + | + |
Monitor progress with events | + | + |
File and memory logging of session with e-mail server | + | + |
Can be used in web (ASP.NET), desktop and console applications | + | + |
+/- The feature is available with significant limitations.
+/? The feature is optional to the protocol implementation.
As soon as the e-mail has been downloaded from the server, MailMessage object comes into play and it's no longer important with which protocol the message was retrieved from the server. The capabilities of e-mail parsing and further processing are protocol-independent.
Some features require licenses for other components of MailBee.NET family. Note that MailBee.NET Objects license includes all individual component licenses.
E-mail parsing and post-processing | License required |
---|---|
Parse entire e-mail with header section, text bodies, and attachments | |
Parse e-mail received in header-only mode | |
Parse e-mail received as header + incomplete body (body preview) | |
Parse standalone text body part or attachment received via IMAP | |
Load e-mail from file, memory, stream, Outlook, XML, System.Net.Mail.MailMessage | |
Access all headers, sender and recipients, text bodies, linked resources, and attachments | |
Make plain-text version of HTML-only e-mail | |
Extract linked resources (e.g. embedded pictures) | |
Get HTML body and save linked resources as files | |
Get HTML body and create dynamic URLs to linked resources (for web apps) | |
Save any plain-text or HTML e-mail as message.htm and linked files | |
Adjust HTML body (e.g. make links open in a new window) | |
Remove unsafe content from HTML (e.g. scripts) | |
Analyze HTML (e.g. find and process all external images) | |
Non-Latin characters in headers, body, attachment filenames (e.g. UTF-8) | |
Save all or selected attachments | |
Save attachment to file, stream or memory | |
Decode winmail.dat (MS TNEF) and extract all attachments and RTF body | |
Date, DateReceived, Importance, Priority, Sensitivity | |
From, ReplyTo, To, CC, and BCC (as collection and as string) | |
Serialize e-mail to XML | |
Save MIME data of e-mail to file, stream, memory | |
Convert e-mail to Outlook .MSG format | Outlook |
Convert e-mail to System.Net.Mail.MailMessage | |
Re-send via SMTP or upload back to IMAP server | SMTP or IMAP |
Check DKIM and DomainKeys signature | |
Check if e-mail is SPAM | AntiSpam |
Check S/MIME signature and decrypt encrypted e-mail | Security |
Check if e-mail is bounced message or delivery report | |
Access to every MIME part, time stamps (Received headers), full e-mail size, and UID |
As you can see, all the functions of parsing and processing e-mail are also available if you load e-mail from file or memory (it's not necessary to download e-mail only from IMAP or POP3 server). And you can also load e-mails from XML, System.Net.Mail.MailMessage, Outlook .MSG or .PST file.
A word on things you should not expect from IMAP and POP3:
IMAP and POP3 protocols are all about managing e-mail in the account but not about managing the account itself.
To change e-mail account password or otherwise manage an account, you'll need to check if your e-mail server supports some kind of a proprietary API for this. It can be ActiveX/COM based, REST, specialized network protocol, and so on.
For instance, some e-mail servers like Plesk Panel support POPPASSD service running at port 106, which lets you remotely change the password with POP3-alike commands.
To start using MailBee.NET in your projects, add MailBee.NET Objects reference to your project. You can use NuGet Packager Manager console for that:
Install-Package MailBee.NET
If NuGet is not an option (for instance, you have older version of Visual Studio), see below.
The example below is for Visual Studio 2010, but the idea remains the same for any other version. For instance, Import namespaces and set license key topic of SMTP guide features similar actions in their Visual Studio 2008 version.
In Project menu (Website menu for ASP.NET project), click Add a reference:
If Website menu does not appear in the menu bar, you should select your ASP.NET project in Solution Explorer first. This will replace Project menu with Website menu.
In Visual Studio 2010, Add Reference dialog may look differently for desktop/console and ASP.NET web applications. The below is for desktop/console. The ASP.NET version may look pretty much like in Visual Studio 2008.
Under Assemblies/Extensions tab, locate MailBee.NET:
In newer versions of Visual Studio, path to the dll is not shown by default so you may need to hover mouse cursor over to see the path (and determine the version). In this case, it's .NET 4.5 version of MailBee.NET.dll:
Click Add Reference and then Close. MailBee.NET entry should appear in References list of your project.
Now, import MailBee.NET namespaces to the beginning of your source code files where you'll use MailBee.NET.
When working with IMAP or POP3, you'll typically need some of these namespaces:
using MailBee; using MailBee.Mime; using MailBee.ImapMail; using MailBee.Pop3Mail;
Imports MailBee Imports MailBee.Mime Imports MailBee.ImapMail Imports MailBee.Pop3Mail
If you're using other components (e.g. S/MIME functionality, HTML processor, bounce e-mail parser, etc), you may also need to import their namespaces as well. For instance:
using MailBee.Security; using MailBee.Html; using MailBee.BounceMail;
Imports MailBee.Security Imports MailBee.Html Imports MailBee.BounceMail
Now, you need to specify your trial or permanent MailBee.NET license key to unlock the product. If you do not yet have a key, you can generate the trial key with "Get a Trial Key" utility (available in Programs / MailBee.NET Objects menu).
You can specify the key in a number of ways (Windows registry, app.config or web.config file, directly in the code). This guide shows two methods of that: hard-coded key and key stored in app.config (web.config for ASP.NET).
Using Windows registry is not recommended as your application may be lacking permission to access the required registry branches. If you still need to use the registry (e.g. if your application is distributed with the source code so that you cannot embed the key there), refer to Using License Keys topic in MailBee.NET Objects documentation for details.
Before the first use and creating any instances of Imap or Pop3 classes, set the static MailBee.Global.LicenseKey property to assign the license key. It's assumed you've already imported MailBee.ImapMail (or MailBee.Pop3Mail) namespace with using
(C#) or Imports
(VB) directives.
MailBee.Global.LicenseKey = "MN100-0123456789ABCDEF-0123";
MailBee.Global.LicenseKey = "MN100-0123456789ABCDEF-0123"
You can also create and unlock instances of Imap and Pop3 classes, passing the license key as a parameter of a constructor, such as Imap(string). Again, it's assumed you've already imported MailBee.ImapMail (or MailBee.Pop3Mail) namespace.
Imap imp = newImap("MN100-0123456789ABCDEF-0123");
Dim imp As New Imap("MN100-0123456789ABCDEF-0123")
Alternatively, you can add app.config to your project (if you do not already have it there) and specify MailBee.NET SMTP license key there.
For ASP.NET application, web.config is always available so that you can immediately edit it, but for other application types you may have to add app.config manually.
The below we are using Visual Studio 2010. For a Visual Studio 2008 version, refer to a similar topic in SMTP guide.
In Projects menu, click Add New Item:
Select Application Configuration File and click Add:
In app.config, locate <appSettings/>
entry in <configuration>
section (if it's not there, create it), and add MailBee.NET license key as follows:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="MailBee.Global.LicenseKey" value="MN100-0123456789ABCDEF-0123"/> </appSettings> </configuration>
Note that <appSettings>
may also appear as <applicationSettings>
in your case.
If <appSettings>
originally looked as <appSettings/>
(self-closing tag syntax), you'll need to unfold it to <appSettings></appSettings>
so that you could insert <add key .../>
there.
The above also applies to ASP.NET application and web.config.
You can also specify the key in machine.config file. This will enable access to the license key to all applications on the computer so that there will be no need to specify the license key in each application separately. For instance, this is the preferred way if you a hosting provider willing to let your hosting clients create and run applications which use MailBee.NET without disclosing your license key to them.
You can download e-mails in a single of code using these static methods of Imap or Pop3 classes:
For all the samples in this guide, we assume the license key is already set (such as in app.config file), and these namespaces are imported: MailBee.Mime, and MailBee.ImapMail or MailBee.Pop3Mail.
This sample downloads the last e-mail in Inbox via POP3, and displays its HTML body text if any:
MailMessage msg = Pop3.QuickDownloadMessage("pop.domain.com", "jdoe", "secret", -1); Console.WriteLine(msg.BodyHtmlText);
Dim msg As MailMessage = Pop3.QuickDownloadMessage("pop.domain.com", "jdoe", "secret", -1) Console.WriteLine(msg.BodyHtmlText)
Note that you'll get an exception in case if the Inbox is empty.
You may also get an exception if the server requires SSL. See Retrieve e-mail from server which requires SSL for details.
The next sample downloads the first e-mail in Inbox via IMAP, and displays its plain-text body. If the e-mail contains only HMTL body, MailBee.NET will convert the HMTL into plain-text automatically:
MailMessage msg = Imap.QuickDownloadMessage("imap.domain.com", "jdoe", "secret", "Inbox", 1); msg.Parser.HtmlToPlainMode = HtmlToPlainAutoConvert.IfNoPlain; Console.WriteLine(msg.BodyPlainText);
Dim msg As MailMessage = Imap.QuickDownloadMessage("imap.domain.com", "jdoe", "secret", "Inbox", 1) msg.Parser.HtmlToPlainMode = HtmlToPlainAutoConvert.IfNoPlain Console.WriteLine(msg.BodyPlainText)
If the Inbox is empty, you'll get an exception.
The sample below downloads headers for all e-mails in a POP3 inbox, and displays their subjects:
MailMessageCollection msgs = Pop3.QuickDownloadMessages("pop.company.com", "jdoe@company.com", "secret", 0); if (msgs.Count > 0) { foreach (MailMessage msg in msgs) { Console.WriteLine(msg.Subject); } } else { Console.WriteLine("Inbox is empty"); }
Dim msgs As MailMessageCollection = _ Pop3.QuickDownloadMessages("pop.company.com", "jdoe@company.com", "secret", 0) If msgs.Count > 0 Then Dim msg As MailMessage For Each msg In msgs Console.WriteLine(msg.Subject) Next msg Else Console.WriteLine("Inbox is empty") End If
As you can see, this sample can handle the situation when the Inbox is empty.
The next sample completely downloads all e-mails in IMAP inbox, and displays the size of every attachment found (making no difference between real attachments and linked resources):
MailMessageCollection msgs = Imap.QuickDownloadMessages("pop.company.com", "jdoe@company.com", "secret", "Inbox"); if (msgs.Count > 0) { foreach (MailMessage msg in msgs) { if (msg.Attachments.Count > 0) { Console.WriteLine("Attachment size list for message " + msg.UidOnServer.ToString()); foreach (Attachment attach in msg.Attachments) { Console.WriteLine(attach.Size.ToString()); } } else { Console.WriteLine("Message " + msg.UidOnServer.ToString() + " has no attachments"); } Console.WriteLine(); } } else { Console.WriteLine("Inbox is empty"); }
Dim msgs As MailMessageCollection = _ Imap.QuickDownloadMessages("pop.company.com", "jdoe@company.com", "secret", "Inbox") If msgs.Count > 0 Then Dim msg As MailMessage For Each msg In msgs If msg.Attachments.Count > 0 Then Console.WriteLine("Attachment size list for message " & msg.UidOnServer.ToString()) Dim attach As Attachment For Each attach In msg.Attachments Console.WriteLine(attach.Size.ToString()) Next attach Else Console.WriteLine("Message " & msg.UidOnServer.ToString() & " has no attachments") End If Console.WriteLine() Next msg Else Console.WriteLine("Inbox is empty") End If
These single-line methods which don't require you to create instances of Imap or Pop3 classes, however, have some drawbacks:
The main purpose of the single-line methods is for quick testing during the development process. For instance, if you're developing some sort of e-mail viewer, you can temporarily use a quick method there to have some e-mail to test your e-mail viewer with, without the need of implementing production-level e-mail retrieval code at the moment when you're focused on other tasks.
The samples below download the last e-mail in Inbox and save all its attachments into a local folder (skipping linked resources like inline images). The first sample uses "quick" method to download the e-mail while the second sample creates an instance of Imap or Pop3 class.
Download e-mail with Imap.QuickDownloadMessage or Pop3.QuickDownloadMessage method:
MailMessage imapMsg = Imap.QuickDownloadMessage("imap.company.com", "jdoe@company.com", "secret", "Inbox", -1); imapMsg.Attachments.SaveAll("C:\\Docs", true); MailMessage popMsg = Pop3.QuickDownloadMessage("pop.company.com", "jdoe@company.com", "secret", -1); popMsg.Attachments.SaveAll("C:\\Docs", true);
Dim imapMsg As MailMessage = _ Imap.QuickDownloadMessage("imap.company.com", "jdoe@company.com", "secret", "Inbox", -1) imapMsg.Attachments.SaveAll("C:\Docs", True) Dim popMsg As MailMessage = _ Pop3.QuickDownloadMessage("pop.company.com", "jdoe@company.com", "secret", -1) popMsg.Attachments.SaveAll("C:\Docs", True)
Download e-mail normally, with Imap.DownloadEntireMessage or Pop3.DownloadEntireMessage method:
Imap imp = new Imap(); imp.Connect("imap.company.com"); imp.Login("jdoe@company.com", "secret"); imp.SelectFolder("Inbox"); MailMessage imapMsg = imp.DownloadEntireMessage(imp.MessageCount, false); imp.Disconnect(); imapMsg.Attachments.SaveAll("C:\\Docs", true); Pop3 pop = new Pop3(); pop.Connect("pop.company.com"); pop.Login("jdoe@company.com", "secret"); MailMessage popMsg = pop.DownloadEntireMessage(pop.InboxMessageCount); pop.Disconnect(); popMsg.Attachments.SaveAll("C:\\Docs", true);
Dim imp As New Imap() imp.Connect("imap.company.com") imp.Login("jdoe@company.com", "secret") imp.SelectFolder("Inbox") Dim imapMsg As MailMessage = imp.DownloadEntireMessage(imp.MessageCount, False) imp.Disconnect() imapMsg.Attachments.SaveAll("C:\Docs", True) Dim pop As New Pop3() pop.Connect("pop.company.com") pop.Login("jdoe@company.com", "secret") Dim popMsg As MailMessage = pop.DownloadEntireMessage(pop.InboxMessageCount) pop.Disconnect() popMsg.Attachments.SaveAll("C:\Docs", True)
From now on, we'll always create instances of Imap and Pop3 class when accessing e-mail on the server.
Also note that we disconnect from the server BEFORE saving attachments. Although it's not required, this lets the application free the connection not waiting until all the attachments get saved (which might take some time). Shortly speaking, just a little optimization here.
Assuming you downloaded an e-mail and got a MailMessage object, you can then get its HTML body via BodyHtmlText property. However, if the message has images attached, they may not be displayed. It's needed to either save these attachments locally and then modify IMG SRC of these images in the HTML body to reflect saved local files locations or embed these images directly in the HTML body with data:base64 URIs. The latter approach is very easy to use:
string html = msg.GetHtmlWithBase64EncodedRelatedFiles();
Dim html As String = msg.GetHtmlWithBase64EncodedRelatedFiles()
You can then load this HTML content in any browser control or send it as a response to the client in case of a web application.
If embedding into HTML body is not an option for you, you can also store embedded images on the filesystem of the server using MailMessage.GetHtmlAndSaveRelatedFiles method or on an external storage (e.g. Amazon S3 or whatever) using MailMessage.GetHtmlAndRelatedFilesInMemory method.
If you need to correcty display e-mail addresses with non-Latin domain names (they are usually encoded in Punycode), you can decode them in human-readable form with EmailAddress.FromIdnAddress, EmailAddressCollection.FromIdnAddress or EmailAddress.UnescapeIdnDomain methods.
It's safe to use these methods even if the address is not encoded (the methods will return the same value as on input).
string humanReadableEmail = msg.From.FromIdnAddress().Email;
Dim humanReadableEmail As String = msg.From.FromIdnAddress().Email
Note that POP3 and IMAP samples of downloading e-mail can be very close to each other. The main differences are:
This makes it easy to adapt most POP3 samples to IMAP (or vice versa, IMAP to POP3):
Imap.SelectFolder("Inbox")
after calling Imap.Connect(serverName)
.Pop3.DownloadEntireMessage(index)
with Imap.DownloadEntireMessage(index, indexIsUid)
.Pop3.DownloadMessageHeader(index)
with Imap.DownloadMessageHeader(index, indexIsUid)
.Imap.Close()
to purge the deleted messages (if you deleted some messages during the current session).Given the above and for brevity's sake, many samples in this tutorial feature only POP3 or IMAP support, with the appropriate comments in protocol-specific portions. The samples which are completely specific to IMAP or POP3 are accompanied with a special note.
if you deal with ranges of e-mails (e.g. you need to display a page of 20 e-mails, from 11th to 30th), you should know about yet another difference between how ranges are specified in POP3 and IMAP:
Operations other than downloading e-mail (such as search for new e-mails), can be very different between POP3 and IMAP (and even not always possible with POP3 at all).
This sample gets headers of all e-mails in the Inbox, and prints From, To, Subject for every e-mail whose header was downloaded:
Imap imp = new Imap(); imp.Connect("imap.company.com"); imp.Login("jdoe@company.com", "secret"); imp.SelectFolder("Inbox"); MailMessageCollection msgs = imp.DownloadMessageHeaders(Imap.AllMessages, false); // POP3 version: msgs = pop.DownloadMessageHeaders(); imp.Disconnect(); foreach (MailMessage msg in msgs) { Console.WriteLine("From: " + msg.From.ToString()); Console.WriteLine("To: " + msg.To.ToString()); Console.WriteLine("Subject: " + msg.Subject); Console.WriteLine(); }
Dim imp As New Imap() imp.Connect("imap.company.com") imp.Login("jdoe@company.com", "secret") imp.SelectFolder("Inbox") Dim msgs As MailMessageCollection = imp.DownloadMessageHeaders(Imap.AllMessages, False) ' POP3 version: msgs = pop.DownloadMessageHeaders() imp.Disconnect() Dim msg As MailMessage For Each msg In msgs Console.WriteLine("From: " & msg.From.ToString()) Console.WriteLine("To: " & msg.To.ToString()) Console.WriteLine("Subject: " & msg.Subject)) Console.WriteLine() Next msg
Because ranges are set differently in POP3 and IMAP, two different samples in this topic.
This sample downloads the last 10 e-mails in Inbox via POP3:
Pop3 pop = new Pop3(); pop.Connect("mail.domain.com"); pop.Login("jdoe", "secret"); if (pop.InboxMessageCount > 0) { // If the inbox contains less than 10 e-mails, adjust to that. int msgCount = pop.InboxMessageCount > 10 ? 10 : pop.InboxMessageCount; // As e-mail indices on the server start with 1 (not 0), must add 1. MailMessageCollection msgs = pop.DownloadMessageHeaders(pop.InboxMessageCount - msgCount + 1, msgCount); foreach (MailMessage msg in msgs) { Console.WriteLine("Message #" + msg.IndexOnServer.ToString()); Console.WriteLine("From: " + msg.From.ToString()); Console.WriteLine("To: " + msg.To.ToString()); Console.WriteLine("Subject: " + msg.Subject); Console.WriteLine(); } } else { Console.WriteLine("Inbox is empty"); } pop.Disconnect();
Dim pop As New Pop3() pop.Connect("mail.domain.com") pop.Login("jdoe", "secret") If pop.InboxMessageCount > 0 Then ' If the inbox contains less than 10 e-mails, adjust to that. Dim msgCount As Integer = IIf(pop.InboxMessageCount > 10, 10, pop.InboxMessageCount) ' As e-mail indices on the server start with 1 (not 0), must add 1. Dim msgs As MailMessageCollection = _ pop.DownloadMessageHeaders(pop.InboxMessageCount - msgCount + 1, msgCount) Dim msg As MailMessage For Each msg In msgs Console.WriteLine("Message #" & msg.IndexOnServer.ToString()) Console.WriteLine("From: " & msg.From.ToString()) Console.WriteLine("To: " & msg.To.ToString()) Console.WriteLine("Subject: " & msg.Subject) Console.WriteLine() Next msg Else Console.WriteLine("Inbox is empty") End If pop.Disconnect()
The IMAP version of the sample:
Imap imp = new Imap(); imp.Connect("mail.domain.com"); imp.Login("jdoe", "secret"); imp.SelectFolder("Inbox"); if (imp.MessageCount > 0) { // If the inbox contains less than 10 e-mails, adjust to that. int msgCount = imp.MessageCount > 10 ? 10 : imp.MessageCount; // As e-mail indices on the server start with 1 (not 0), must add 1. int firstIndex = imp.MessageCount - msgCount + 1; int lastIndex = imp.MessageCount; MailMessageCollection msgs = imp.DownloadMessageHeaders( firstIndex.ToString() + ":" + lastIndex.ToString(), false); foreach (MailMessage msg in msgs) { Console.WriteLine("Message #" + msg.IndexOnServer.ToString()); Console.WriteLine("From: " + msg.From.ToString()); Console.WriteLine("To: " + msg.To.ToString()); Console.WriteLine("Subject: " + msg.Subject); Console.WriteLine(); } } else { Console.WriteLine("Inbox is empty"); } imp.Disconnect();
Dim imp As New Imap() imp.Connect("mail.domain.com") imp.Login("jdoe", "secret") imp.SelectFolder("Inbox") If imp.MessageCount > 0 Then ' If the inbox contains less than 10 e-mails, adjust to that. Dim msgCount As Integer = IIf(imp.MessageCount > 10, 10, imp.MessageCount) ' As e-mail indices on the server start with 1 (not 0), must add 1. Dim firstIndex As Integer = imp.MessageCount - msgCount + 1 Dim lastIndex As Integer = imp.MessageCount Dim msgs As MailMessageCollection = imp.DownloadMessageHeaders( _ firstIndex.ToString() & ":" & lastIndex.ToString(), False) Dim msg As MailMessage For Each msg In msgs Console.WriteLine("Message #" & msg.IndexOnServer.ToString()) Console.WriteLine("From: " & msg.From.ToString()) Console.WriteLine("To: " & msg.To.ToString()) Console.WriteLine("Subject: " & msg.Subject) Console.WriteLine() Next msg Else Console.WriteLine("Inbox is empty") End If imp.Disconnect()
Actually, IMAP ranges are much more powerful, they are rather sets than ranges. For instance, you can list multiple individual messages or ranges in a single set, separating them with commas. Example: 5,17,24:30,45:60,122.
You can also use the IMAP syntax like 10:*. It means "select all e-mails from 10th to the last e-mail in the folder".
Let's assume we need to completely download all new e-mails and display the attachment count for every downloaded message.
With IMAP, it's very simple as the IMAP server can track new e-mails itself:
Imap imp = new Imap(); imp.Connect("mail.domain.com"); imp.Login("john.doe@company.com", "secret"); imp.SelectFolder("Inbox"); UidCollection uids = (UidCollection)imp.Search(true, "NEW", null); if (uids.Count > 0) { MailMessageCollection msgs = imp.DownloadEntireMessages(uids.ToString(), true); foreach (MailMessage msg in msgs) { Console.WriteLine("Message #" + msg.IndexOnServer.ToString() + " has " + msg.Attachments.Count + " attachment(s)"); } } else { Console.WriteLine("No new messages"); } imp.Disconnect();
Dim imp As New Imap() imp.Connect("mail.domain.com") imp.Login("john.doe@company.com", "secret") imp.SelectFolder("Inbox") Dim uids As UidCollection = CType(imp.Search(True, "NEW", Nothing), UidCollection) If uids.Count > 0 Then Dim msgs As MailMessageCollection = imp.DownloadEntireMessages(uids.ToString(), True) Dim msg As MailMessage For Each msg In msgs Console.WriteLine("Message #" & msg.IndexOnServer.ToString() & _ " has " & msg.Attachments.Count & " attachment(s)") Next msg Else Console.WriteLine("No new messages") End If imp.Disconnect()
The sample above uses Unique-IDs (UIDs) instead of ordinal message numbers but it would work with message numbers too provided that nobody access the same mailbox simultaneously.
Also note that all the e-mails found are then downloaded with a single command. This may or may not be acceptable in your case. This is fast but may consume too much memory if there are many new e-mails are they are big. Usually, downloading multiple e-mails in a single command makes sense when you download just message headers (because they are quite small).
With POP3, the server knows nothing about new e-mails and you'll need to find out which e-mails are new by yourself.
Even with IMAP, you may also need to implement search for new e-mails manually in case if your idea of which e-mails are new is different from what your server thinks on the same matters. For the server, the e-mail is no longer new if anyone has already selected the folder which contains this e-mail (even if this person never downloaded the e-mail).
If you need to detect not the e-mails which just arrived but all the e-mails you have never seen (and never downloaded), use UNSEEN search flag instead of NEW.
Imap.DeleteMessages, Pop3.DeleteMessage, Pop3.DeleteMessages methods mark e-mails for deletion.
However, none of these methods actually delete e-mails from the mailbox. To purge e-mails marked as deleted, you should properly close the POP3 session with Pop3.Disconnect or close the IMAP folder with Imap.Close. However, there can be exceptions from this rule (Gmail is an example).
This sample deletes and purges all e-mails in Inbox (don't run it on your working e-mail account as you'll lose all the e-mails there):
Imap imp = new Imap(); imp.Connect("mail.domain.com"); imp.Login("john.doe@company.com", "secret"); imp.SelectFolder("Inbox"); imp.DeleteMessages(Imap.AllMessages, false); imp.Close(); imp.Disconnect();
Dim imp As New Imap() imp.Connect("mail.domain.com") imp.Login("john.doe@company.com", "secret") imp.SelectFolder("Inbox") imp.DeleteMessages(Imap.AllMessages, False) imp.Close() imp.Disconnect()
The POP3 version:
Pop3 pop = new Pop3(); pop.Connect("mail.domain.com"); pop.Login("john.doe@company.com", "secret"); pop.DeleteMessages(); pop.Disconnect();
Dim pop As New Pop3() pop.Connect("mail.domain.com") pop.Login("john.doe@company.com", "secret") pop.DeleteMessages() pop.Disconnect()
Note that some servers may, for instance, not let you delete e-mail via POP3 or may simply ignore the deletion request. The typical example of a non-standard POP3 and IMAP behaviour is Gmail. See Gmail IMAP and POP3 issues topic for details.
This sample creates an empty e-mail with "Message draft" text in the subject and attempts to upload it into Drafts folder on the IMAP server. If the server responds with a negative reply (probably because the folder does not exist), the sample tries to upload into Inbox then:
Imap imp = new Imap(); imp.Connect("mail.domain.com"); imp.Login("john.doe@company.com", "secret"); MailMessage msg = new MailMessage(); msg.Subject = "Message draft"; try { Console.WriteLine("Upload to Drafts"); imp.UploadMessage(msg, "Drafts"); } catch (MailBeeImapNegativeResponseException e) { Console.WriteLine(e.Message); Console.WriteLine("Upload to inbox"); imp.UploadMessage(msg, "Inbox"); } imp.Disconnect();
Dim imp As New Imap() imp.Connect("mail.domain.com") imp.Login("john.doe@company.com", "secret") Dim msg As New MailMessage() msg.Subject = "Message draft" Try Console.WriteLine("Upload to Drafts") imp.UploadMessage(msg, "Drafts") Catch e As MailBeeImapNegativeResponseException Console.WriteLine(e.Message) Console.WriteLine("Upload to inbox") imp.UploadMessage(msg, "Inbox") End Try imp.Disconnect()
You can also upload e-mails you just sent with SMTP, get the UID assigned to the uploaded e-mail, set flags and date, and so on.
Just supply the folder name in Imap.SelectFolder call (or Imap.ExamineFolder for read-only access to the folder).
This sample attempts to select "Sent Items" folder. If the server responds with a negative reply, the sample downloads the list of all available folders and displays their names:
Imap imp = new Imap(); imp.Connect("imap.domain.com"); imp.Login("john.doe", "secret"); try { imp.SelectFolder("Sent Items"); } catch (MailBeeImapNegativeResponseException e) { Console.WriteLine(e.Message); Console.WriteLine(); Console.WriteLine("The available folders are:"); FolderCollection folders = imp.DownloadFolders(); foreach (Folder f in folders) { Console.WriteLine(f.Name); } } imp.Disconnect();
Dim imp As New Imap() imp.Connect("imap.domain.com") imp.Login("john.doe", "secret") Try imp.SelectFolder("Sent Items") Catch e As MailBeeImapNegativeResponseException Console.WriteLine(e.Message) Console.WriteLine() Console.WriteLine("The available folders are:") Dim folders As FolderCollection = imp.DownloadFolders() Dim f As Folder For Each f In folders Console.WriteLine(f.Name) Next f End Try imp.Disconnect()
For Gmail.com, Outlook.com and some other popular services MailBee.NET detects SSL settings automatically. For instance. just specify the host name as imap.gmail.com for IMAP or pop.gmail.com for POP3.
It also works with Live.com, Outlook.com, Hotmail.com. At the moment of writing, the host names to specify are imap-mail.outlook.com and pop-mail.outlook.com for all these domains.
For other IMAP-over-SSL and POP3-over-SSL services, you'll need to set the SSL port explicitly.
The standard IMAP-over-SSL port is 993:
Imap imp = new Imap(); imp.Connect("imap.domain.com", 993);
Dim imp As New Imap() imp.Connect("imap.domain.com", 993)
The standard POP3-over-SSL port is 995:
Pop3 pop = new Pop3(); pop.Connect("pop.domain.com", 995);
Dim pop As New Pop3() pop.Connect("pop.domain.com", 995)
By default, MailBee.NET uses the most secure SSL protocol supported by the server (usually, TLS). This is controlled by Imap.SslProtocol and Pop3.SslProtocol properties.
You can also enable STARTTLS mode to use SSL over regular 143 or 110 port by any of these methods: - Set Imap.SslMode or Pop3.SslMode property to SslStartupMode.UseStartTls value BEFORE connecting to the server. - Or, call Imap.StartTls/Pop3.StartTls AFTER connecting to the server.
Gmail.com, being mostly a web-based e-mail service, provides quite a special implementation of IMAP and POP3 protocols. This topic describes some issues that you should know about.
To configure IMAP and POP3 settings of your Gmail account, open Forwarding and POP/IMAP tab:
POP3 notes:
IMAP notes:
imp
is Imap instance).UidCollection uc = (UidCollection)imp.Search(true, "TEXT " + ImapUtils.ToLiteral("Some text"), "utf-8");
Dim uc As UidCollection = CType(imp.Search(True, "TEXT " & ImapUtils.ToLiteral("Some text"), "utf-8"), UidCollection)
Or you can use Google-specific method which gives you all the power of Google search syntax:
UidCollection uc = (UidCollection)imp.Search(true, "TEXT " + ImapUtils.GmailSearch("Some text"), "utf-8");
Dim uc As UidCollection = CType(imp.Search(True, "TEXT " & ImapUtils.GmailSearch("Some text"), "utf-8"), UidCollection)
If you experience Web login required error in Gmail IMAP or POP3, open https://www.google.com/accounts/DisplayUnlockCaptcha page in the browser and confirm your identity to Google. After that, IMAP and POP3 access should be working again.
If you need to disable the auto-detection of Gmail SSL settings, set MailBee.Global.AutodetectPortAndSslMode to false.
This topic is mainly for MS Exchange 2007-2016 and Office 365 (which is powered by MS Exchange 2016). For MS Exchange 2003, many of the issues described below do not apply. Sadly, IMAP and POP3 support in MS Exchange has degraded in newer versions.
The major specifics of MS Exchange POP3 and IMAP access is that MS Exchange mostly targets Outlook clients which work with MS Exchange via MAPI, not POP3 or IMAP. Therefore, neither IMAP nor POP3 is even enabled in MS Exchange by default. Make sure the service required for your application is running.
IMAP/POP access can also be blocked on a user level. Make sure the e-mail account you're using has IMAP/POP access enabled. However, Administrator user cannot have IMAP/POP access enabled under any circumstances.
You'll need to connect via SSL or use secure authentication. MS Exchange 2010 supports only GSSAPI which is, however, supported by MailBee.NET either.
Feature set of MS Exchange is also more limited than in most other IMAP servers. For instance, you cannot use search with international charsets (such as UTF-8). Only ASCII is supported.
You may consider switching to EWS (Exchange Web Services) when working with MS Exchange or Office 365 server. See Ews topic for examples.
You can enable logging of IMAP or POP3 conversation between MailBee.NET client and the server in a number of ways. You can use logging into a file or memory, subscribe to Imap.LogNewEntry or Pop3.LogNewEntry event which raises each time a new log record is about to be created, and much more.
Logging is useful for trouble-shooting and tracking all the activity for later use. The code below enables logging of all the activity of Imap and Pop3 objects into a file and clears that file:
Imap imp = new Imap(); imp.Log.Enabled = true; imp.Log.Filename = "C:\\Temp\\imap_log.txt"; imp.Log.Clear(); Pop3 pop = new Pop3(); pop.Log.Enabled = true; pop.Log.Filename = "C:\\Temp\\pop3_log.txt"; pop.Log.Clear();
Dim imp As New Imap() imp.Log.Enabled = True imp.Log.Filename = "C:\Temp\imap_log.txt" imp.Log.Clear() Dim pop As New Pop3() pop.Log.Enabled = True pop.Log.Filename = "C:\Temp\pop3_log.txt" pop.Log.Clear()
Typical issues you may face and their possible remedy:
As a general suggestion, read carefully the exception message as it may already provide some useful information, and always enable logging when you face any connectivity errors. The log file is a very helpful source of the debug information which you can use to understand and fix the issue or send it to AfterLogic Support Team for further analysis.
To learn how to enable logging, see Log file of IMAP and POP3 session topic. To submit the log file to AfterLogic, create a ticket at http://helpdesk.afterlogic.com and upload the file there.
In case if certain e-mail cannot be parsed properly, you can save it as .EML file using MailMessage.SaveMessage method, and then open it in Mozilla Thunderbird. Does it look correctly there? If it's displayed OK, you can then submit it to AfterLogic as described above.
Copyright © 2006-2024 AfterLogic Corporation. All rights reserved.