|
|
aspNetIMAP
|
 |
Subscribe to category: aspNetIMAP
by Dave
8. May 2012 08:23
aspNetIMAP Supports the IDLE Command
The IDLE command is a little different than the other IMAP commands. When the IDLE command is used, aspNetIMAP turns into a listening component. It listens for updates from the IMAP server. IMAP servers will usually send an Idle update response back, if messages are deleted, or new messages come in. When a update is sent back, from the server to aspNetIMAP, the IdleResponse event is raised. While aspNetIMAP is in Idle mode, no other commands can be sent against the server, until .IdleStop() is called.
The following steps are used to implement the Idle command (full code can be found below).
1)First we select a folder, in this example, the Inbox
MailFolder inbox = imap.SelectInbox();
2)Then we wire up the event, that will get called every time an Idle update is sent to aspNetIMAP //wire up the idle event inbox.IdleResponse += new IdleResponseEventHandler(OnIdleResponse);
3) Start Idling inbox.Idle();
4)Now we wait. In this example, we are looping through a command promprt, until the user enters the word "stop". We could have just as easily implemented this in a windows form, in a button click event. And, subsequently, clicked another button to stop idling. string line = Console.ReadLine().ToLower(); while (line != "stop") {
line = Console.ReadLine().ToLower(); }
5) Stop Idling inbox.IdleStop();
6)Get the last unseen message (usually the message that just came in, and caused the Idle event to be raised). //get the latest messges that just came in string unSeenSet = inbox.SearchClient.NotSeenSet();
The full example can be found below. In this example, we are creating a console.exe application. We could also convert this to windows form code just as easily.
[C#]
//in this example, use a console application, to wait for IDLE updates
private string gmailUsername = "test@gmail.com";
private string gmailPassword = "secret";
void IMAPGmail2IdleTest()
{
IMAP4 imap = OpenIMAPGmail();
//get the inbox folder
MailFolder inbox = imap.SelectInbox();
//wire up the idle event
inbox.IdleResponse += new IdleResponseEventHandler(OnIdleResponse);
Console.WriteLine("starting to idle...");
inbox.Idle();
string line = Console.ReadLine().ToLower();
while (line != "stop")
{
line = Console.ReadLine().ToLower();
}
Console.WriteLine("Stopping Idling...");
inbox.IdleStop();
//get the latest messges that just came in
string unSeenSet = inbox.SearchClient.NotSeenSet();
if ((unSeenSet != null) && (unSeenSet.Trim().Length > 0))
{
//convert to an array
int[] unseenUnquieIds = inbox.MessageClient.ToUniqueIds(unSeenSet);
int latestUniqueId = unseenUnquieIds[unseenUnquieIds.Length - 1];
//download the latest uniqueId message
MimeMessage message = inbox.FetchClient.Message(latestUniqueId, IndexType.UniqueId, true);
if (message != null)
{
if (message.Subject != null)
{
Console.WriteLine(message.Subject.Value);
}
else
{
Console.WriteLine("No subject");
}
}
}
imap.Disconnect();
}
private IMAP4 OpenIMAPGmail()
{
IMAP4 imap = new IMAP4("imap.gmail.com");
//create and load the ssl socket
AdvancedIntellect.Ssl.SslSocket ssl = new AdvancedIntellect.Ssl.SslSocket();
ssl.IgnoreInvalidCertificates = true;
imap.LoadSslSocket(ssl);
//logging on the ssl socket
ssl.Logging = true;
ssl.LogPath = "c:\\temp\\ssl.log";
//rest of the IMAP properties
imap.Port = 993;
//any logging for troubleshooting
imap.Logger = new IMAPLog();
imap.Logger.Path = "c:\\temp\\imap.log";
imap.Logger.Overwrite = true;
imap.Connect();
imap.Username = gmailUsername;
imap.Password = gmailPassword;
imap.Login();
return imap;
}
void OnIdleResponse(object sender, IdleResponseEventArgs e)
{
//write out the response sent from the server
string response = System.Text.Encoding.ASCII.GetString(e.Data, 0, e.DataCount);
Console.WriteLine(response);
}
[VB.NET]
'in this example, use a console application, to wait for IDLE updates
Private gmailUsername As String = "test@gmail.com"
Private gmailPassword As String = "secret"
Private Sub IMAPGmail2IdleTest()
Dim imap As IMAP4 = OpenIMAPGmail()
'get the inbox folder
Dim inbox As MailFolder = imap.SelectInbox()
'wire up the idle event
AddHandler inbox.IdleResponse, AddressOf Me.OnIdleResponse
Console.WriteLine("starting to idle...")
inbox.Idle()
Dim line As String = Console.ReadLine().ToLower()
While line <> "stop"
line = Console.ReadLine().ToLower()
End While
Console.WriteLine("Stopping Idling...")
inbox.IdleStop()
'get the latest messges that just came in
Dim unSeenSet As String = inbox.SearchClient.NotSeenSet()
If (unSeenSet IsNot Nothing) AndAlso (unSeenSet.Trim().Length > 0) Then
'convert to an array
Dim unseenUnquieIds As Integer() = inbox.MessageClient.ToUniqueIds(unSeenSet)
Dim latestUniqueId As Integer = unseenUnquieIds(unseenUnquieIds.Length - 1)
'download the latest uniqueId message
Dim message As MimeMessage = inbox.FetchClient.Message(latestUniqueId, IndexType.UniqueId, True)
If message IsNot Nothing Then
If message.Subject IsNot Nothing Then
Console.WriteLine(message.Subject.Value)
Else
Console.WriteLine("No subject")
End If
End If
End If
imap.Disconnect()
End Sub
Private Function OpenIMAPGmail() As IMAP4
Dim imap As New IMAP4("imap.gmail.com")
'create and load the ssl socket
Dim ssl As New AdvancedIntellect.Ssl.SslSocket()
ssl.IgnoreInvalidCertificates = True
imap.LoadSslSocket(ssl)
'logging on the ssl socket
ssl.Logging = True
ssl.LogPath = "c:\temp\ssl.log"
'rest of the IMAP properties
imap.Port = 993
'any logging for troubleshooting
imap.Logger = New IMAPLog()
imap.Logger.Path = "c:\temp\imap.log"
imap.Logger.Overwrite = True
imap.Connect()
imap.Username = gmailUsername
imap.Password = gmailPassword
imap.Login()
Return imap
End Function
Private Sub OnIdleResponse(sender As Object, e As IdleResponseEventArgs)
'write out the response sent from the server
Dim response As String = System.Text.Encoding.ASCII.GetString(e.Data, 0, e.DataCount)
Console.WriteLine(response)
End Sub
As always, if anyone has any questions, feel free to contact me using the Contact Us page found at this link. Thanks! Dave Wanta
by Dave
9. March 2012 00:13
Message count in Gmail using aspNetIMAP
I recently had a customer pulling their hair out over this issue, so I thought I post something about it.
Sometimes when using aspNetIMAP (or any other IMAP client for that matter), the message count returned for a folder will not match what you actually see as a count in Gmail's web interface. The discrepancy is due to the conversational view. Gmail has an option to view messages as conversations. If you turn that option off (found under General | Settings in Gmail), you will get the true message count of messages in that folder.
by Dave
8. March 2011 00:58
I recently had a request about fetching different parts of a message from an IMAP server. They wanted to get the following information as easily as possible:
Flags Message Size Importance Attachment Names Customer Headers Recipients
The IMAP protocol does not support fetching this information in a single network call. However, all of these values can be fetched for a single message, using multiple calls. aspNetIMAP can do this for you in a nice, neat object called the MimeEnvelope object. The MimeEnvelope object fetches all of the above data, and more.
Below is a code example that demonstrates using the MimeEnvelope object.
C#
IMAP4 imap = new IMAP4();
imap.Server = "192.168.1.4";
imap.Username = "dave@example.com";
imap.Password = "test";
imap.Login();
MailFolder mf = imap.SelectInbox();
FetchClient fc = mf.FetchClient;
MimeEnvelope[] menvelopes = fc.MimeEnvelope( "1:*", IndexType.Ordinal );
foreach( MimeEnvelope menvelope in menvelopes)
{
//write out the attachment names
Response.Write( "Attachment Count: " + menvelope.AttachmentNames.Length );
if( menvelope.AttachmentNames.Length > 0 )
{
foreach( string attachmentName in menvelope.AttachmentNames )
{
Response.Write( attachmentName );
}
}
//write out the From, To, CC address information
Response.Write( menvelope.FromName );
Response.Write( menvelope.FromAddress );
//To addresses
foreach( string emailAddress in menvelope.To )
{
string name = menvelope.To[ emailAddress ];
Response.Write( name );
Response.Write( emailAddress );
}
//CC Addresses
foreach( string emailAddress in menvelope.CC )
{
string name = menvelope.CC[ emailAddress ];
Response.Write( name );
Response.Write( emailAddress );
}
//write out other information
Response.Write( "UniqueId: " + menvelope.UniqueId.ToString() );
Response.Write( "Size: " + menvelope.Size.ToString() );
Response.Write( "Flags: "+ menvelope.Flags.ToString() );
Response.Write( "InternalDate: " + menvelope.InternalDate.ToString( "f", DateTimeFormatInfo.InvariantInfo) );
Response.Write( "Date: " + menvelope.Date.ToString( "f", DateTimeFormatInfo.InvariantInfo) );
//subject
Response.Write( menvelope.Subject );
//priority
Response.Write( "Priority: " + menvelope.Priority.ToString() );
Response.Write( "IsAnswered: " + menvelope.IsAnswered().ToString() );
Response.Write( "IsDrafted: " + menvelope.IsDrafted().ToString() );
Response.Write( "IsFlagged: " + menvelope.IsFlagged().ToString() );
Response.Write( "IsRead: " + menvelope.IsRead().ToString() );
Response.Write( "IsRecent: " + menvelope.IsRecent ().ToString() );
//retrieve a specific header named 'x-organization'
Header h = menvelope.Headers[ "x-organization" ];
if( ( h != null ) && ( h.Value != null ) )
{
Response.Write( h.Value );
}
//write out the headers
Response.Write( menvelope.HeaderString );
//write out the bodystructure of the message
if( menvelope.BodyStructure != null )
{
Response.Write( menvelope.BodyStructure.ToString() );
}
}
imap.Disconnect();
VB.NET
Dim imap As New IMAP4()
imap.Server = "192.168.1.4"
imap.Username = "dave@example.com"
imap.Password = "test"
imap.Login()
Dim mf As MailFolder = imap.SelectInbox()
Dim fc As FetchClient = mf.FetchClient
Dim menvelopes As MimeEnvelope() = fc.MimeEnvelope("1:*", IndexType.Ordinal)
Dim menvelope As MimeEnvelope
For Each menvelope In menvelopes
'write out the attachment names
Response.Write(("Attachment Count: " + menvelope.AttachmentNames.Length))
If menvelope.AttachmentNames.Length > 0 Then
Dim attachmentName As String
For Each attachmentName In menvelope.AttachmentNames
Response.Write(attachmentName)
Next attachmentName
End If
'write out the From, To, CC address information
Response.Write(menvelope.FromName)
Response.Write(menvelope.FromAddress)
'To addresses
Dim emailAddress As String
For Each emailAddress In menvelope.To
Dim name As String = menvelope.To(emailAddress)
Response.Write(name)
Response.Write(emailAddress)
Next emailAddress
'CC Addresses
Dim emailAddress As String
For Each emailAddress In menvelope.CC
Dim name As String = menvelope.CC(emailAddress)
Response.Write(name)
Response.Write(emailAddress)
Next emailAddress
'write out other information
Response.Write(("UniqueId: " + menvelope.UniqueId.ToString()))
Response.Write(("Size: " + menvelope.Size.ToString()))
Response.Write(("Flags: " + menvelope.Flags.ToString()))
Response.Write(("InternalDate: " + menvelope.InternalDate.ToString("f", DateTimeFormatInfo.InvariantInfo)))
Response.Write(("Date: " + menvelope.Date.ToString("f", DateTimeFormatInfo.InvariantInfo)))
'subject
Response.Write(menvelope.Subject)
'priority
Response.Write(("Priority: " + menvelope.Priority.ToString()))
Response.Write(("IsAnswered: " + menvelope.IsAnswered().ToString()))
Response.Write(("IsDrafted: " + menvelope.IsDrafted().ToString()))
Response.Write(("IsFlagged: " + menvelope.IsFlagged().ToString()))
Response.Write(("IsRead: " + menvelope.IsRead().ToString()))
Response.Write(("IsRecent: " + menvelope.IsRecent().ToString()))
'retrieve a specific header named 'x-organization'
Dim h As Header = menvelope.Headers("x-organization")
If Not (h Is Nothing) And Not (h.Value Is Nothing) Then
Response.Write(h.Value)
End If
'write out the headers
Response.Write(menvelope.HeaderString)
'write out the bodystructure of the message
If Not (menvelope.BodyStructure Is Nothing) Then
Response.Write(menvelope.BodyStructure.ToString())
End If
Next menvelope
imap.Disconnect()
by Dave
2. March 2011 02:51
aspNetIMAP can easily fetch email from Gmail. To do this you must do the following:
a) Configure IMAP access in Gmail b) Download the AdvancedIntellect.Ssl.dll from www.advancedintellect.com/download.aspx c) Use aspNetIMAP over SSL at port 993 to connect.
Lets discuss this below.
Configure IMAP access in Gmail
Before you can access email, you must first configure IMAP in Gmail. To do this, log into Gmail, and click on the settings tab. You should see something similar to what is below. Basically, you want select "Enable IMAP".

Download the AdvancedIntellect.Ssl.dll Once you have IMAP configured in Gmail, you need to download the AdvancedIntellect,Ssl.dll plugin to use with aspNetIMAP. You can download the dll from: http://www.advancedintellect.com/download.aspx Gmail only allows you to connect over IMAP using SSL. The AdvancedIntellect,Ssl.dll allows you to do this.
Use aspNetIMAP over SSL at port 993 to connect. Once you've downloaded the dll, you can integrate it into your project.
If you are using VS.NET, import the dll into your application, and set a reference to it.
If you are not using VS.NET, you should be able to just copy the dll to your /bin directory.
Once that is done, the following code example will get you started. This example simply downloads the message count from your inbox, and loops through the headers of the individual messages.
C#
IMAP4 imap = new IMAP4( "imap.gmail.com" );
//create and load the ssl socket
AdvancedIntellect.Ssl.SslSocket ssl = new AdvancedIntellect.Ssl.SslSocket();
imap.LoadSslSocket( ssl );
//logging on the ssl socket
ssl.Logging = true;
ssl.LogPath = "c:\\ssl.log";
//rest of the IMAP properties
imap.Port = 993;
imap.Username = "MyAccount@gmail.com";
imap.Password = "MyPassword";
//any logging for troubleshooting
imap.Logger = new IMAPLog();
imap.Logger.Path = "c:\\imap.log";
imap.Logger.Overwrite = true;
imap.Connect();
imap.Login();
//get the message count
MailFolder inbox = imap.SelectInbox();
int count = inbox.MessageCount;
//write it out
Response.Write( count.ToString() );
FetchClient fc = inbox.FetchClient;
//get the headers for each message (IMAP is a '1' based index. Start at '1'
for( int i=1;i<=count;i++)
{
string headers = fc.Headers(i, IndexType.Ordinal );
//do some work on the headers
DoWork( headers );
}
imap.Disconnect();
VB.NET
Dim imap As New IMAP4("imap.gmail.com")
'create and load the ssl socket
Dim ssl As New AdvancedIntellect.Ssl.SslSocket()
imap.LoadSslSocket(ssl)
'logging on the ssl socket
ssl.Logging = True
ssl.LogPath = "c:\ssl.log"
'rest of the IMAP properties
imap.Port = 993
'any logging for troubleshooting
imap.Logger = New IMAPLog()
imap.Logger.Path = "c:\imap.log"
imap.Logger.Overwrite = True
imap.Connect()
imap.Username = "MyAccount@gmail.com"
imap.Password = "MyPassword"
imap.Login()
'get the message count
Dim inbox As MailFolder = imap.SelectInbox()
Dim count As Integer = inbox.MessageCount
'write it out
Response.Write(count.ToString())
Dim fc As FetchClient = inbox.FetchClient
'get the headers for each message (IMAP is a '1' based index. Start at '1'
Dim i As Integer
For i = 1 To count
Dim headers As String = fc.Headers(i, IndexType.Ordinal)
'do some work on the headers
DoWork(headers)
Next i
imap.Disconnect()
As always, if anyone has any questions, feel free to contact me over at the Contact Us web page.
Thanks, Dave Wanta
by Dave
17. February 2011 07:39
Today I had a request from Darren about how to read unread messages from an IMAP server. This is an excellent question. I should have added something like this to the help file.
To fetch unread messages, there are a number of classes we need to take advantage of in aspNetIMAP.
They are: IMAP4 -- the object used to manage the connection to the IMAP server MailFolder -- the object used to get access to the individual folder SearchClient -- the object used to search for unread messages FetchClient -- the object that actually fetches the content of the messages.
Without further delay, below is some sample code that can get you started for downloading unread messages.
//configure and connect to the IMAP server
IMAP4 imap = new IMAP4( "mail.blah.com", "dave@blah.com", "test" );
imap.Logger = new IMAPLog( "c:\\imap.log", false);
imap.Logger.Overwrite = true;
imap.Login();
//get the inbox
MailFolder inbox = imap.SelectInbox();
//get a list of message ids that are unread
SearchClient sc = inbox.SearchClient;
//return results as UniqueIds
sc.IndexType = IndexType.UniqueId;
string messageSet = inbox.SearchClient.NotSeenSet();
if( (messageSet == null ) || (messageSet.Length == 0 ) )
return;
char[] commaArray = new Char[] {','};
//trim any ending commas
if( messageSet.EndsWith(",") )
messageSet = messageSet.Trim( commaArray );
//split into individual message ids, so we can process 1 at a time.
string[] ids = messageSet.Split( commaArray);
//get an instance to the FetchClient
FetchClient fc = inbox.FetchClient;
foreach( string id in ids )
{
if( id.Length == 0 )
continue;
int uid = int.Parse(id);
//download the message
MimeMessage msg = fc.Message( uid, IndexType.UniqueId, true );
//process according to business rules
ProcessMessage( msg );
}
imap.Disconnect();
To keep the code short, it is left up to the user to implement exception handling.
As always, if anyone has any questions, comments or requests, please let me know.
Thanks! Dave Wanta
by Dave
9. November 2010 02:29
I have a number of customers who need to parse cell phone (mobile) generated emails. These emails come in configurations I never dreamed possible. Although they are technically Mime compliant, their individual parts can be ordered strangely, or have unique headers that normally aren't found in a standard message.
I was sent an email request from a developer (Thanks Cara!) about parsing a T-Mobile generated message. She needed to find and extract the text body part. If a text body part wasn't found, then the html body part was to be found, and converted to plain text. The other requirement was to find all of the images, and download (save) them to a directory.
Below is a code example is something I whipped up for her. She used it as a basis to get started with her application. Error checking has been left out, to keep the code short, workable, but complete.
As always, if anyone has any questions or comments, please let me know.
Thanks! Dave Wanta
string path = "t_mobile.eml";
MimeMessage m = MimeMessage.ParseFile( path );
MimePart textPart = m.TextMimePart;
if( textPart == null )
{
//try and find it, by finding the first inline text part
MimePartCollection inlineParts = m.InLineParts;
if( ( inlineParts != null ) && ( inlineParts.Count >0 ) )
{
foreach( MimePart part in inlineParts )
{
if( (part.Name != null ) && ( part.Name.EndsWith(".txt") ) && ( part.ContentTypeString == "text/plain") )
{
//then we found our part
textPart = part;
break;
}
}
}
}
string plainText = string.Empty;
if( textPart != null )
{
plainText = textPart.DecodedText();
}
if( plainText.Length == 0 )
{
//find the first html part.
//get the plain text from the html part
foreach( MimePart part in m.RetrieveAllParts() )
{
if( (part.ContentTypeString != null ) && ( part.ContentTypeString.ToLower() == "text/html") )
{
string html = part.DecodedText();
//convert the Html to plain formatted text
plainText = Utility.ConvertHtmlToText( html).Trim();
break;
}
}
}
//extract all images, and save them to the temp directory
foreach( MimePart part in m.RetrieveAllParts() )
{
if( part.IsImage() )
{
//normally, would need to check for images that already have the same filename
//and rename accordingly
//in this example, just save the images to the temp directory
part.Save("c:\\temp\\");
}
}
by Dave
9. November 2010 01:46
** NOTE: ALL OF OUR PRODUCTS RUN ON ALL VERSIONS OF .NET. **
The instructions below are for people using VS2010 and beyond.
--------------------------
As more and more people are upgrading to VS2010, and beyond, I am getting more of the following emails:
aspNetEmail (or any of our other products) doesn't work in later versions of Visual Studio. I usually get one of the following errors:
"aspNetEmail is not declared, it may be inaccessible due to its protection level."
Or
"The referenced assembly "…" could not be resolved because it has a dependency upon System.Web (or some other internal .NET namespace). Please remove references to assemblies not in the targeted framework or consider retargeting your project"
Usually these exceptions occur when the developer is building a client side application.
Starting in VS2010, VS tries to be too smart for it's own good. When you build a client application (console.exe, winform, etc…) VS limits the number of namespaces you need access too, because it thinks you shouldn't need them.
To change this behavior, what you need to do, is change the target framework from a subset of namespaces, to all of them.
To change this, in VS.NET Solution Explorer, Right-Click on your project, an select Properties. On the Application tab, set the Target Framework to be ".NET Framework XX". By default it is set to ".NET Framework XX Client Profile". Press Ctrl-S for save, and you are done.
Below are 2 pictures that display changing the target framework.
As always, if anyone has any questions, feel free to contact me.
Thanks! Dave Wanta

C# Screenshot:

VB.NET Screenshot (this option is found under the Compile tab. Then, click the "Advanced Compile Option" button.

Testimonial
|