Downloading email messages with IMAPX - c#

I just started using the open-source library called IMAPX to interact with my IMAP mailbox. I am following this article on CodeProject. I can login properly and retrieve the email folders. But the problem is, the article seems to be incomplete which is leaving me in the middle of the road. Firstly the Retrieving Email Folder's part didn't work. I had to do a workaround.Now, I am trying to download the emails of a folder.The article, regarding this issue, has only a few line of code:
private void foldersList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = foldersList.SelectedItem as EmailFolder;
if(item != null)
{
// Load the folder for its messages.
loadFolder(item.Title);
}
}
private void loadFolder(string name)
{
ContentFrame.Content = new FolderMessagesPage(name);
}
The article doesn't explain anything about FolderMessagesPage . So, I made a test page named FolderMessagesPage. I literally have no idea what to put in that page. Can anybody please guide me?

Unfortunately now I'm having some problems in accessing the article on Code Project, but if you need to retrieve the emails, you can start with the following sample code which retrieves the emails from the Inbox folder. I think that might work for you as well.
private static readonly ImapClient _client = new ImapX.ImapClient(ServerImapName, ImapPort, ImapProtocol, false);
if (!_client.Connect())
{
throw new Exception("Error on conncting to the Email server.");
}
if (!_client.Login(User, Password))
{
throw new Exception("Impossible to login to the Email server.");
}
public static List<string> GetInboxEmails()
{
var lstInEmails = new List<string>();
// select the inbox folder
Folder inbox = _client.Folders.Inbox;
if (inbox.Exists > 0)
{
var arrMsg = inbox.Search("ALL", ImapX.Enums.MessageFetchMode.Full);
foreach (var msg in arrMsg)
{
var subject = msg.Subject;
var mailBody = msg.Body.HasHtml ? msg.Body.Html : msg.Body.Text;
lstInEmails.Add(string.Concat(subject, " - ", mailBody );
}
}
return lstInEmails;
}
Hope it helps.
Good bytes.

Related

UWP: EmailMessage uses comma instead of semicolon

I want to create a new mail in the default mail app using UWP. Therefore I've written the following code:
List<string> emailAddresses = new List<string>();
public MainPage()
{
this.InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
emailAddresses = new List<string>();
emailAddresses.Add("xx1#yyy.zzz");
emailAddresses.Add("xx2#yyy.zzz");
await ComposeEmail();
}
async Task ComposeEmail()
{
var emailMessage = new Windows.ApplicationModel.Email.EmailMessage();
foreach (string mailadress in emailAddresses)
{
var emailRecipient = new Windows.ApplicationModel.Email.EmailRecipient(mailadress);
emailMessage.To.Add(emailRecipient);
}
await Windows.ApplicationModel.Email.EmailManager.ShowComposeNewEmailAsync(emailMessage);
}
But the recipients in the mail which is created by this code are comma separated. If I try to send this mail with MS Outlook I'll get the message that I have to insert the recepients semicolon separated.
But I don't find a way to change this. I've also searched with Google - but I haven't found anything.
Does anyone know how I can solve this?
Thank you in forward.
Best regards
Matthias

How to get the MessageId from all exchange items

Hello I recently got into development around EWS. One of the issue came up to me is that a client ask me to import emails into database and he wants to detect the duplicate based on InternetMessageID this way he doesn't have to import the duplicate emails and my code came up to this point.
private static string GetInternetMessageID(Microsoft.Exchange.WebServices.Data.Item email)
{
EmailMessage emailMsg = email as EmailMessage;
string returnId = string.Empty;
if ((emailMsg != null)) {
try {
emailMsg.Load();
//loads additional info, without calling this ToRecipients (and more) is empty
} catch (ArgumentException ex) {
//retry
email.Load();
}
returnId = emailMsg.InternetMessageId;
} else {
//what to do?
}
return returnId;
}
I can handle regular emails, but for special exchange objects such as contact, Calendar, Posts etc it does not work because it could not cast it to an EmailMessage object.
And I know you can extract the internetMessageId from those objects. Because the client used to have another software that extract this ID for them, maybe the property is not called internetMessageID, I think I probally have to extract it from the internetMessageHeader. However when ever I try to get it from the item object it just throws me an error. How do I get the internet messageID from these "Special" exchange items?
PS i am aware of item.id.UniqueID however that is not what I want as this id changes if I move items from folder to another folder in exchange
Only objects that have been sent via the Transport service will have an InternetMessageId so things like Contacts and Tasks because they aren't messages and have never been routed via the Transport service will never have an Internet MessageId. You probably want to look at using a few properties to do this InternetMessageId can be useful for messages PidTagSearchKey https://msdn.microsoft.com/en-us/library/office/cc815908.aspx is one that can be used (if you good this there are various examples of using this property).
If your going to use it in Code don't use the method your using to load the property on each item this is very inefficient as it will make a separate call for each object. Because these I'd's are under 256 Kb just retrieve then when using FindItems. eg
ExtendedPropertyDefinition PidTagSearchKey = new ExtendedPropertyDefinition(0x300B, MapiPropertyType.Binary);
ExtendedPropertyDefinition PidTagInternetMessageId = new ExtendedPropertyDefinition(0x1035, MapiPropertyType.String);
PropertySet psPropSet = new PropertySet(BasePropertySet.IdOnly);
psPropSet.Add(PidTagSearchKey);
psPropSet.Add(PidTagInternetMessageId);
ItemView ItemVeiwSet = new ItemView(1000);
ItemVeiwSet.PropertySet = psPropSet;
FindItemsResults<Item> fiRess = null;
do
{
fiRess = service.FindItems(WellKnownFolderName.Inbox, ItemVeiwSet);
foreach (Item itItem in fiRess)
{
Object SearchKeyVal = null;
if (itItem.TryGetProperty(PidTagSearchKey, out SearchKeyVal))
{
Console.WriteLine(BitConverter.ToString((Byte[])SearchKeyVal));
}
Object InternetMessageIdVal = null;
if (itItem.TryGetProperty(PidTagInternetMessageId, out InternetMessageIdVal))
{
Console.WriteLine(InternetMessageIdVal);
}
}
ItemVeiwSet.Offset += fiRess.Items.Count;
} while (fiRess.MoreAvailable);
If you need larger properties like the Body using the LoadPropertiesForItems Method https://blogs.msdn.microsoft.com/exchangedev/2010/03/16/loading-properties-for-multiple-items-with-one-call-to-exchange-web-services/

Using Mailkit to save attachments using IMAP

I have a need to find a particular email on a Google IMAP server and then save the attachments from the email. I think I have it all figured out except for the part of determining what the file name is of the attachment.
Below is my code so far, I am hoping that someone can point me in the right direction to determine the file name.
I have Googled and SO'd but have not been able to find something using the attachment approach.
internal class MailKitHelper
{
private void SaveAttachementsForMessage(string aMessageId)
{
ImapClient imapClient = new ImapClient();
imapClient.Connect("imap.google.com", 993, SecureSocketOptions.Auto);
imapClient.Authenticate("xxxx", "xxxx");
HeaderSearchQuery searchCondition = SearchQuery.HeaderContains("Message-Id", aMessageId);
imapClient.Inbox.Open(FolderAccess.ReadOnly);
IList<UniqueId> ids = imapClient.Inbox.Search(searchCondition);
foreach (UniqueId uniqueId in ids)
{
MimeMessage message = imapClient.Inbox.GetMessage(uniqueId);
foreach (MimeEntity attachment in message.Attachments)
{
attachment.WriteTo("WhatIsTheFileName"); //How do I determine the file name
}
}
}
}
And the winner is.....
attachment.ContentDisposition.FileName

Cancel webclient Async request

Hopefully an easy question for you all but I'm really struggling.
I've only recently started programming and have just had an app certified to the WP7 app store but noticed a bug myself that i would like to fix before making the app public.
Basically I have a search box where the user enters a chemical name and a webservice returns an image and its molecular weight. What i would like to do is cancel the webclient if the user navigates away from the page before the download is completed or if a new search is made before the previous is completed (this currently crashes the app as I believe you can only have one request at a time??)
private void searchCactus()
{
WebClient imgClient = new WebClient();
imgClient.OpenReadCompleted += new OpenReadCompletedEventHandler(imgClient_OpenReadCompleted);
WebClient mwClient = new WebClient();
mwClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(mwClient_DownloadStringCompleted);
if (DeviceNetworkInformation.IsNetworkAvailable == false)
{
MessageBox.Show("No network found, please check network availability and try again");
}
else if (compoundSearchBox.Text.Contains("?"))
{
MessageBox.Show("\"?\" Not Permitted");
return;
}
else if (compoundSearchBox.Text != "")
{
progBar1.IsIndeterminate = true;
string imageuri = "http://cactus.nci.nih.gov/chemical/structure/" + compoundSearchBox.Text + "/image?format=png&width=300&height=300";
string mwURI = "http://cactus.nci.nih.gov/chemical/structure/" + compoundSearchBox.Text + "/mw";
imgClient.OpenReadAsync(new Uri(#imageuri), imgClient);
mwClient.DownloadStringAsync(new Uri(#mwURI), mwClient);
// //lower keyboard
this.Focus();
}
else MessageBox.Show("Enter Search Query");
}
I tried implementing the following button but it does not work
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
imgClient.CancelAsync();
mwClient.CancelAsync();
}
as "the name 'mwClient' does not exist in the current context"
I would be very grateful if anybody could provide some guidance
Just put the two clients into fields in your class.

using c# .net libraries to check for IMAP messages from gmail servers [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Does anyone have any sample code in that makes use of the .Net framework that connects to googlemail servers via IMAP SSL to check for new emails?
I'd recommend looking at MailKit as it is probably the most robust mail library out there and it's Open Source (MIT).
One of the awesome things about MailKit is that all network APIs are cancelable (something I haven't seen available in any other IMAP library).
It's also the only library that I know of that supports threading of messages.
using System;
using System.Net;
using System.Threading;
using MailKit.Net.Imap;
using MailKit.Search;
using MailKit;
using MimeKit;
namespace TestClient {
class Program
{
public static void Main (string[] args)
{
using (var client = new ImapClient ()) {
using (var cancel = new CancellationTokenSource ()) {
client.Connect ("imap.gmail.com", 993, true, cancel.Token);
// If you want to disable an authentication mechanism,
// you can do so by removing the mechanism like this:
client.AuthenticationMechanisms.Remove ("XOAUTH");
client.Authenticate ("joey", "password", cancel.Token);
// The Inbox folder is always available...
var inbox = client.Inbox;
inbox.Open (FolderAccess.ReadOnly, cancel.Token);
Console.WriteLine ("Total messages: {0}", inbox.Count);
Console.WriteLine ("Recent messages: {0}", inbox.Recent);
// download each message based on the message index
for (int i = 0; i < inbox.Count; i++) {
var message = inbox.GetMessage (i, cancel.Token);
Console.WriteLine ("Subject: {0}", message.Subject);
}
// let's try searching for some messages...
var query = SearchQuery.DeliveredAfter (DateTime.Parse ("2013-01-12"))
.And (SearchQuery.SubjectContains ("MailKit"))
.And (SearchQuery.Seen);
foreach (var uid in inbox.Search (query, cancel.Token)) {
var message = inbox.GetMessage (uid, cancel.Token);
Console.WriteLine ("[match] {0}: {1}", uid, message.Subject);
}
client.Disconnect (true, cancel.Token);
}
}
}
}
}
The URL listed here might be of interest to you
http://www.codeplex.com/InterIMAP
which was extension to
http://www.codeproject.com/KB/IP/imaplibrary.aspx?fid=91819&df=90&mpp=25&noise=5&sort=Position&view=Quick&fr=26&select=2562067#xx2562067xx
As the author of the above project i can say that yes it does support SSL.
I am currently working on a new version of the library that will be completely asynchronous to increase the speed with which it can interact with IMAP servers.
That code, while not complete, can be downloaded, along with the original synchronous library (which also supports SSL), from the code plex site linked to above.
Cross posted from the other similar question. See what happens when they get so similar?
I've been searching for an IMAP solution for a while now, and after trying quite a few, I'm going with AE.Net.Mail.
There is no documentation, which I consider a downside, but I was able to whip this up by looking at the source code (yay for open source!) and using Intellisense. The below code connects specifically to Gmail's IMAP server:
// Connect to the IMAP server. The 'true' parameter specifies to use SSL
// which is important (for Gmail at least)
ImapClient ic = new ImapClient("imap.gmail.com", "name#gmail.com", "pass",
ImapClient.AuthMethods.Login, 993, true);
// Select a mailbox. Case-insensitive
ic.SelectMailbox("INBOX");
Console.WriteLine(ic.GetMessageCount());
// Get the first *11* messages. 0 is the first message;
// and it also includes the 10th message, which is really the eleventh ;)
// MailMessage represents, well, a message in your mailbox
MailMessage[] mm = ic.GetMessages(0, 10);
foreach (MailMessage m in mm)
{
Console.WriteLine(m.Subject);
}
// Probably wiser to use a using statement
ic.Dispose();
I'm not affiliated with this library or anything, but I've found it very fast and stable.
Lumisoft.net has both IMAP client and server code that you can use.
I've used it to download email from Gmail. The object model isn't the best, but it is workable, and seems to be rather flexible and stable.
Here is the partial result of my spike to use it. It fetches the first 10 headers with envelopes, and then fetches the full message:
using (var client = new IMAP_Client())
{
client.Connect(_hostname, _port, _useSsl);
client.Authenticate(_username, _password);
client.SelectFolder("INBOX");
var sequence = new IMAP_SequenceSet();
sequence.Parse("0:10");
var fetchItems = client.FetchMessages(sequence, IMAP_FetchItem_Flags.Envelope | IMAP_FetchItlags.UID,
false, true);
foreach (var fetchItem in fetchItems)
{
Console.Out.WriteLine("message.UID = {0}", fetchItem.UID);
Console.Out.WriteLine("message.Envelope.From = {0}", fetchItem.Envelope.From);
Console.Out.WriteLine("message.Envelope.To = {0}", fetchItem.Envelope.To);
Console.Out.WriteLine("message.Envelope.Subject = {0}", fetchItem.Envelope.Subject);
Console.Out.WriteLine("message.Envelope.MessageID = {0}", fetchItem.Envelope.MessageID);
}
Console.Out.WriteLine("Fetching bodies");
foreach (var fetchItem in client.FetchMessages(sequence, IMAP_FetchItem_Flags.All, false, true)
{
var email = LumiSoft.Net.Mail.Mail_Message.ParseFromByte(fetchItem.MessageData);
Console.Out.WriteLine("email.BodyText = {0}", email.BodyText);
}
}
There is no .NET framework support for IMAP. You'll need to use some 3rd party component.
Try Mail.dll email component, it's very affordable and easy to use, it also supports SSL:
using(Imap imap = new Imap())
{
imap.ConnectSSL("imap.company.com");
imap.Login("user", "password");
imap.SelectInbox();
List<long> uids = imap.Search(Flag.Unseen);
foreach (long uid in uids)
{
string eml = imap.GetMessageByUID(uid);
IMail message = new MailBuilder()
.CreateFromEml(eml);
Console.WriteLine(message.Subject);
Console.WriteLine(message.Text);
}
imap.Close(true);
}
Please note that this is a commercial product I've created.
You can download it here: https://www.limilabs.com/mail.
MailSystem.NET contains all your need for IMAP4. It's free & open source.
(I'm involved in the project)
the source to the ssl version of this is here: http://atmospherian.wordpress.com/downloads/
Another alternative: HigLabo
https://higlabo.codeplex.com/documentation
Good discussion: https://higlabo.codeplex.com/discussions/479250
//====Imap sample================================//
//You can set default value by Default property
ImapClient.Default.UserName = "your server name";
ImapClient cl = new ImapClient("your server name");
cl.UserName = "your name";
cl.Password = "pass";
cl.Ssl = false;
if (cl.Authenticate() == true)
{
Int32 MailIndex = 1;
//Get all folder
List<ImapFolder> l = cl.GetAllFolders();
ImapFolder rFolder = cl.SelectFolder("INBOX");
MailMessage mg = cl.GetMessage(MailIndex);
}
//Delete selected mail from mailbox
ImapClient pop = new ImapClient("server name", 110, "user name", "pass");
pop.AuthenticateMode = Pop3AuthenticateMode.Pop;
Int64[] DeleteIndexList = new.....//It depend on your needs
cl.DeleteEMail(DeleteIndexList);
//Get unread message list from GMail
using (ImapClient cl = new ImapClient("imap.gmail.com"))
{
cl.Port = 993;
cl.Ssl = true;
cl.UserName = "xxxxx";
cl.Password = "yyyyy";
var bl = cl.Authenticate();
if (bl == true)
{
//Select folder
ImapFolder folder = cl.SelectFolder("[Gmail]/All Mail");
//Search Unread
SearchResult list = cl.ExecuteSearch("UNSEEN UNDELETED");
//Get all unread mail
for (int i = 0; i < list.MailIndexList.Count; i++)
{
mg = cl.GetMessage(list.MailIndexList[i]);
}
}
//Change mail read state as read
cl.ExecuteStore(1, StoreItem.FlagsReplace, "UNSEEN")
}
//Create draft mail to mailbox
using (ImapClient cl = new ImapClient("imap.gmail.com"))
{
cl.Port = 993;
cl.Ssl = true;
cl.UserName = "xxxxx";
cl.Password = "yyyyy";
var bl = cl.Authenticate();
if (bl == true)
{
var smg = new SmtpMessage("from mail address", "to mail addres list"
, "cc mail address list", "This is a test mail.", "Hi.It is my draft mail");
cl.ExecuteAppend("GMail/Drafts", smg.GetDataText(), "\\Draft", DateTimeOffset.Now);
}
}
//Idle
using (var cl = new ImapClient("imap.gmail.com", 993, "user name", "pass"))
{
cl.Ssl = true;
cl.ReceiveTimeout = 10 * 60 * 1000;//10 minute
if (cl.Authenticate() == true)
{
var l = cl.GetAllFolders();
ImapFolder r = cl.SelectFolder("INBOX");
//You must dispose ImapIdleCommand object
using (var cm = cl.CreateImapIdleCommand()) Caution! Ensure dispose command object
{
//This handler is invoked when you receive a mesage from server
cm.MessageReceived += (Object o, ImapIdleCommandMessageReceivedEventArgs e) =>
{
foreach (var mg in e.MessageList)
{
String text = String.Format("Type is {0} Number is {1}", mg.MessageType, mg.Number);
Console.WriteLine(text);
}
};
cl.ExecuteIdle(cm);
while (true)
{
var line = Console.ReadLine();
if (line == "done")
{
cl.ExecuteDone(cm);
break;
}
}
}
}
}
LumiSoft.ee - works great, fairly easy. Compiles with .NET 4.0.
Here are the required links to their lib and examples.
Downloads Main:
http://www.lumisoft.ee/lsWWW/Download/Downloads/
Code Examples:
are located here: ...lsWWW/Download/Downloads/Examples/
.NET:
are located here: ...lsWWW/Download/Downloads/Net/
I am putting a SIMPLE sample up using their lib on codeplex (IMAPClientLumiSoft.codeplex.com). You must get their libraries directly from their site. I am not including them because I don't maintain their code nor do I have any rights to the code. Go to the links above and download it directly. I set LumiSoft project properties in my VS2010 to build all of it in .NET 4.0 which it did with no errors.
Their samples are fairly complex and maybe even overly tight coding when just an example. Although I expect that these are aimed at advanced level developers in general.
Their project worked with minor tweaks. The tweaks: Their IMAP Client Winform example is set in the project properties as "Release" which prevents VS from breaking on debug points. You must use the solution "Configuration Manager" to set the project to "Active(Debug)" for breakpoints to work. Their examples use anonymous methods for event handlers which is great tight coding... not real good as a teaching tool. My project uses "named" event method handlers so you can set breakpoints inside the handlers. However theirs is an excellent way to handle inline code. They might have used the newer Lambda methods available since .NET 3.0 but did not and I didn't try to convert them.
From their samples I simplified the IMAP client to bare minimum.

Categories