Check for unread emails - c#

I'm looking for a way to check the number of unread emails on an email account.
Any tips?
EDIT: As described in the tags, for C#. As I learned IMAP is the way to go and I confirmed all email accounts I'm going to use have IMAP activated :)

POP
You can use OpenPOP.net to read emails using POP protocol. The problem with POP is that it does not hold details whether it was unread or not. So I think this will not be of much use to you. You have have your own way of downloading and tagging emails as read or unread.
IMAP
This question in SO has some links for examples using IMAP. IMAP has details about mail status(read/unread).
Please explain more about your requirement.

If what you want to do is get the number of unread messages in an IMAP folder, you can use MailKit to do this:
using MailKit;
using MailKit.Search;
using MailKit.Net.Imap;
...
using (var client = new ImapClient ()) {
// Note: depending on your server, you might need to connect
// on port 993 using SecureSocketOptions.SslOnConnect
client.Connect ("imap.server.com", 143, SecureSocketOptions.StartTls);
// Note: use your real username/password here...
client.Authenticate ("username", "password");
// open the Inbox folder...
client.Inbox.Open (FolderAccess.ReadOnly);
// search the folder for new messages (aka recently
// delivered messages that have not been read yet)
var uids = client.Inbox.Search (SearchQuery.New);
Console.WriteLine ("You have {0} new message(s).", uids.Count);
// ...but maybe you mean unread messages? if so, use this query
uids = client.Inbox.Search (SearchQuery.NotSeen);
Console.WriteLine ("You have {0} unread message(s).", uids.Count);
client.Disconnect (true);
}

Here is the sample of code with LumiSoft IMAP library:
using LumiSoft.Net.IMAP;
using LumiSoft.Net.IMAP.Client;
using LumiSoft.Net;
...
using (IMAP_Client client = new IMAP_Client())
{
client.Connect("imap.gmail.com", 993, true);
client.Login("your.username#gmail.com", "your_cool_password");
client.SelectFolder("INBOX");
IMAP_SequenceSet sequence = new IMAP_SequenceSet();
//sequence.Parse("*:1"); // from first to last
IMAP_Client_FetchHandler fetchHandler = new IMAP_Client_FetchHandler();
fetchHandler.NextMessage += new EventHandler(delegate(object s, EventArgs e)
{
Console.WriteLine("next message");
});
fetchHandler.Envelope += new EventHandler<EventArgs<IMAP_Envelope>>(delegate(object s, EventArgs<IMAP_Envelope> e){
IMAP_Envelope envelope = e.Value;
if (envelope.From != null && !String.IsNullOrWhiteSpace(envelope.Subject))
{
Console.WriteLine(envelope.Subject);
}
});
// the best way to find unread emails is to perform server search
int[] unseen_ids = client.Search(false, "UTF-8", "unseen");
Console.WriteLine("unseen count: " + unseen_ids.Count().ToString());
// now we need to initiate our sequence of messages to be fetched
sequence.Parse(string.Join(",", unseen_ids));
// fetch messages now
client.Fetch(false, sequence, new IMAP_Fetch_DataItem[] { new IMAP_Fetch_DataItem_Envelope() }, fetchHandler);
// uncomment this line to mark messages as read
// client.StoreMessageFlags(false, sequence, IMAP_Flags_SetType.Add, IMAP_MessageFlags.Seen);
}
Bit complicated, but works fine. Limisoft library is not perfect, so be sure you test it well.

Related

Sending Email to SpecifiedPickupDirectory with MailKit

I was using SmtpClient till now with ASP.NET MVC 5. For testing email send functionality on local system, I was using client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
Now, I want to do the same things in ASP.NET Core which does not have SmtpClient class implemented till now. All search for this ended up on MailKit. I have used their send mail code which is working fine with gmail.
I do not want to send testing emails each time and there may be a lot of scenarios in my project where I need to send email. How can I use the local email sending functionality with MailKit. Any links or little source code will help. Thanks
I'm not sure on the finer details of how SmtpDeliveryMethod.SpecifiedPickupDirectory works and what it does exactly, but I suspect it might just save the message in a directory where the local Exchange server periodically checks for mail to send out.
Assuming that's the case, you could do something like this:
public static void SaveToPickupDirectory (MimeMessage message, string pickupDirectory)
{
do {
// Generate a random file name to save the message to.
var path = Path.Combine (pickupDirectory, Guid.NewGuid ().ToString () + ".eml");
Stream stream;
try {
// Attempt to create the new file.
stream = File.Open (path, FileMode.CreateNew);
} catch (IOException) {
// If the file already exists, try again with a new Guid.
if (File.Exists (path))
continue;
// Otherwise, fail immediately since it probably means that there is
// no graceful way to recover from this error.
throw;
}
try {
using (stream) {
// IIS pickup directories expect the message to be "byte-stuffed"
// which means that lines beginning with "." need to be escaped
// by adding an extra "." to the beginning of the line.
//
// Use an SmtpDataFilter "byte-stuff" the message as it is written
// to the file stream. This is the same process that an SmtpClient
// would use when sending the message in a `DATA` command.
using (var filtered = new FilteredStream (stream)) {
filtered.Add (new SmtpDataFilter ());
// Make sure to write the message in DOS (<CR><LF>) format.
var options = FormatOptions.Default.Clone ();
options.NewLineFormat = NewLineFormat.Dos;
message.WriteTo (options, filtered);
filtered.Flush ();
return;
}
}
} catch {
// An exception here probably means that the disk is full.
//
// Delete the file that was created above so that incomplete files are not
// left behind for IIS to send accidentally.
File.Delete (path);
throw;
}
} while (true);
}
The above code snippet uses Guid.NewGuid () as a way of generating a temporary filename, but you can use whatever method you want (e.g. you could also opt to use message.MessageId + ".eml").
Based on Microsoft's referencesource, when SpecifiedPickupDirectory is used, they actually also use Guid.NewGuid ().ToString () + ".eml", so that's probably the way to go.

Email client app exceptions

I am developing an app with xamarin studio. My goal is to connect to pop3 and download emails to my app.
I am using the following code but I am facing these issues:
a) an exception on sslstream.AuthenticateAsClient("pop.gmail.com");. (The authentication or decryption has failed).
b)everywhere I have sw.Flush() I am taking exception: This operation is invalid until it is successfully authenticated.
TcpClient tcpclient = new TcpClient();
tcpclient.Connect("pop.gmail.com", 995);
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
sslstream.AuthenticateAsClient("pop.gmail.com");
StreamWriter sw = new StreamWriter(sslstream);
System.IO.StreamReader reader = new StreamReader(sslstream);
sw.WriteLine("USER myusername");
sw.Flush();
sw.WriteLine("PASS *****");
sw.Flush();
sw.WriteLine("RETR 1");
sw.Flush();
sw.WriteLine("Quit ");
sw.Flush();
string str = string.Empty;
string strTemp = string.Empty;
while((strTemp = reader.ReadLine()) !=null){
if(".".Equals(strTemp)){
break;
}
if(strTemp.IndexOf("-ERR") != -1){
break;
}
str +=strTemp;
}
reader.Close();
sw.Close();
tcpclient.Close();
EDIT
I used mailkit and it is a great solution. I can retrieve emails but i have a problem. When i have download a number of mails(not specific number. For deferent account was deferent number of mails)
I am taking the following error:
system.ArgumentOutOfRangeException on: var message = client.GetMessage(i, cancel.Token);
My code for the login:
partial void btnlogin (NSObject sender)
{
using (var client = new Pop3Client ()) {
var credentials = new NetworkCredential (Convert.ToString(txtusername.Text).Trim(), Convert.ToString(txtpassword.Text).Trim());
// Note: if the server requires SSL-on-connect, use the "pops" protocol instead
var uri = new Uri (Convert.ToString("pops://pop.gmail.com"));
using (var cancel = new CancellationTokenSource ()) {
client.Connect (uri, cancel.Token);
client.Authenticate (credentials, cancel.Token);
int count = client.GetMessageCount (cancel.Token);
var list= new List<string>();
for (int i = 0; i < count; i++) {
var message = client.GetMessage (i, cancel.Token);
Console.WriteLine ("From: {0}", message.From);
list.Add(Convert.ToString(message.From));
}
client.Disconnect (true, cancel.Token);
}
}
}
I came here to suggest using MailKit instead of writing your own library for this. MailKit is also specifically meant to work with Xamarin (since I work at Xamarin). MailSystem.NET is pretty badly broken (I've ranted about it elsewhere on StackOverflow), so I would definitely not recommend using that.
That said, you may need to look at using this version of the SslStream .ctor as opposed to the one you are using. The problem may be that the default .ctor isn't validating the SSL certificate because it isn't "trusted".
I would use an existing C# library to do this.
At one point in the past, I used MailSystem.NET and was able to port their library to MonoTouch. I am not sure of its license works for you, but you will have a much better time using it than rolling your own.
I also think that writing your own library for this would be a waste of anyone's time. I haven't tried Mail Kit yet (will definitely have to), but I have recently used Rebex Mail when I needed to backup my emails from my email server via POP3. Fortunatelly, it was a one time task only, so I did not have to pay as I only used their 30-day free trial that did not have any limitation.
using Rebex.Mail;
using Rebex.Net;
Pop3 client = new Pop3();
client.Connect("pop.gmail.com", SslMode.Implicit);
client.Login("gmailuser", "password");
var messageInfos = client.GetMessageList(Pop3ListFields.FullHeaders);
foreach (Pop3MessageInfo message in messageInfos)
client.GetMessage(message.SequenceNumber, string.Format(#"C:\gmail-pop3-backup\{0}-{1}.eml", message.Subject, message.UniqueId));
client.Disconnect();

How to Empty Gmail Trash with C#

I tried to access my Gmail mailbox with InterImap Library. It shows my messages there, but unable to delete messages. I also found a method "EmptyFolder()" but doesn't work.
All that worked for me is MoveMessageToFolder() but it's not that I need.
Please help me empty my Trash with C# using the same or any other library. I need the code sample that does that.
Here's the code what I managed to write.
var config = new InterIMAP.IMAPConfig("imap.gmail.com", "<my gmail username>", "<my gmail password", true, true, "");
var client = new InterIMAP.Synchronous.IMAPClient(config, new InterIMAP.IMAPLogger(config, new object[] { }), 1);
var trash = client.Folders["[Gmail]"].SubFolders["Trash"];
trash.EmptyFolder();
client.Logoff();
Thanks in Advance.
I dislike deleting the trash folder in Gmail manually. It's full of spam everyday.
So I copied c# code to do the job for me. I downloaded and used mail.dll from Limilabs, the evaluation version. Create a Gmail password for apps.
Here is the code:
using System;
using Limilabs.Client.IMAP;
using System.Collections.Generic;
namespace delete_gmail_trash
{
class Program
{
static void Main(string[] args)
{
using (Imap imap = new Imap())
{
imap.ConnectSSL("imap.gmail.com");
imap.UseBestLogin("username#gmail.com", "password for Gmail apps");
// Recognize Trash folder
List<FolderInfo> folders = imap.GetFolders();
CommonFolders common = new CommonFolders(folders);
FolderInfo trash = common.Trash;
// Find all emails we want to delete
imap.Select(trash);
List<long> uidList = imap.Search(Flag.All);
foreach (long uid in uidList)
{
imap.DeleteMessageByUID(uid);
Console.WriteLine("{0} deleted", uid);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
imap.Close();
}
}
}
}
If you delete a message from your Inbox or one of your custom folders, it will still appear in [Gmail]/All Mail.
Here’s why: in most cases, deleting a message simply removes that folder’s label from the message, including the label identifying the message as being in your Inbox.
[Gmail]/All Mail shows all of your messages, whether or not they have labels attached to them.
If you want to permanently delete a message from all folders:
Move it to the [Gmail]/Trash folder.
Delete it from the [Gmail]/Trash folder.
You can find more details here:
http://www.limilabs.com/blog/delete-email-permanently-in-gmail

Notify C# Client, when SMTP Server receive a new Email

I want to get all emails in my ASP.NET application that have a certain CC-recipient. To use this for future emails I didn't want to polling all the time to get them. But I can't find a way, how I can use push to get the emails instantly. Are their any frameworks in C# to help me for this?
I want to connect with my application to a mail server and register a method 'X'. Always when a new message arrived to the mail server, my application have to be notified and my application should execute the method 'X'.
I hope that this is possible with code like this:
void Application_Start()
{
...
ConnectWithTheSmtpServer();
RegisterMethodForNotification(DoSomethink);
...
}
void DoSomethink(Mail newMail)
{
// Do Somethink with the mail
}
EDIT:
I did it with the MailSystem.Net. It works very fine and is very easy to implement.
Sample Code:
void Application_Start()
{
var worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(StartIdleProcess);
if (worker.IsBusy)
worker.CancelAsync();
worker.RunWorkerAsync();
}
private void StartIdleProcess(object sender, DoWorkEventArgs e)
{
if (_imap != null && _imap.IsConnected)
{
_imap.StopIdle();
_imap.Disconnect();
}
_imap = new Imap4Client();
_imap.ConnectSsl(server-name, 993);
_imap.Login(username, passwort);
var inbox = _imap.SelectMailbox("INBOX");
_imap.NewMessageReceived += new NewMessageReceivedEventHandler(NewMessageReceived);
inbox.Subscribe();
_imap.StartIdle();
}
public static void NewMessageReceived(object source, NewMessageReceivedEventArgs e)
{
// Do something with the source...
}
You are approaching this from the wrong angle.
SMTP does not support receiving mail (never mind PUSH mail). POP3 is what you can use for retrieving mail, but it does not have support for PUSH either (so you would have to pull for mail).
The IMAP4 IDLE extension is what most refer to as PUSH mail - so you will need to find a library for C# that supports IMAP4 IDLE. I found some information that will get you going in the right direction (no reason to duplicate it here):
Using C# .Net Libraries to Check for IMAP Messages
Accessing IMAP in C#
Keep in mind when choosing a solution that it needs to support IDLE.
I really like the look of MailSystem.Net as it fulfills your requirements.
Remember that your mail server also needs to have IMAP4 and IMAP4 IDLE enabled. Some mail servers don't support it, so you might be clean out of luck (and will have to use POP3 pulling).
You could send a copy of your emails(i.e. using /etc/aliases file in PostFix) to a MAIL SERVER YOU CAN HANDLE. Once there, you can implement a MAIL PROCESSOR that do whatever you want anytime a mail that MEET CERTAIN CONDITIONS arrives.
Hope that helps,
You can try this:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using EAGetMail; //add EAGetMail namespace
namespace receiveemail
{
class Program
{
static void Main(string[] args)
{
// Create a folder named "inbox" under current directory
// to save the email retrie enter code here ved.
string curpath = Directory.GetCurrentDirectory();
string mailbox = String.Format("{0}\\inbox", curpath);
// If the folder is not existed, create it.
if (!Directory.Exists(mailbox))
{
Directory.CreateDirectory(mailbox);
}
// Gmail IMAP4 server is "imap.gmail.com"
MailServer oServer = new MailServer("imap.gmail.com",
"gmailid#gmail.com", "yourpassword", ServerProtocol.Imap4 );
MailClient oClient = new MailClient("TryIt");
// Set SSL connection,
oServer.SSLConnection = true;
// Set 993 IMAP4 port
oServer.Port = 993;
try
{
oClient.Connect(oServer);
MailInfo[] infos = oClient.GetMailInfos();
for (int i = 0; i < infos.Length; i++)
{
MailInfo info = infos[i];
Console.WriteLine("Index: {0}; Size: {1}; UIDL: {2}",
info.Index, info.Size, info.UIDL);
// Download email from GMail IMAP4 server
Mail oMail = oClient.GetMail(info);
Console.WriteLine("From: {0}", oMail.From.ToString());
Console.WriteLine("Subject: {0}\r\n", oMail.Subject);
// Generate an email file name based on date time.
System.DateTime d = System.DateTime.Now;
System.Globalization.CultureInfo cur = new
System.Globalization.CultureInfo("en-US");
string sdate = d.ToString("yyyyMMddHHmmss", cur);
string fileName = String.Format("{0}\\{1}{2}{3}.eml",
mailbox, sdate, d.Millisecond.ToString("d3"), i);
// Save email to local disk
oMail.SaveAs(fileName, true);
// Mark email as deleted in GMail account.
oClient.Delete(info);
}
// Quit and purge emails marked as deleted from Gmail IMAP4 server.
oClient.Quit();
}
catch (Exception ep)
{
Console.WriteLine(ep.Message);
}
}
}
}

Save mail we had read and load only new email in C#

I write a "email client" program to check and read mail.
I had download source-code of many author (in codeproject)but they program was loading very long and when i restart program must download it again.
I have idea to save mail we have downloaded and only download only new mail.
How can i save mail? I can use XML or SQL?
I using POP3 and IMAP.
Check out Limisoft library.
Here is the sample of code:
using LumiSoft.Net.IMAP;
using LumiSoft.Net.IMAP.Client;
using LumiSoft.Net;
...
using (IMAP_Client client = new IMAP_Client())
{
client.Connect("imap.gmail.com", 993, true);
client.Login("your.username#gmail.com", "your_cool_password");
client.SelectFolder("INBOX");
IMAP_SequenceSet sequence = new IMAP_SequenceSet();
//sequence.Parse("*:1"); // from first to last
IMAP_Client_FetchHandler fetchHandler = new IMAP_Client_FetchHandler();
fetchHandler.NextMessage += new EventHandler(delegate(object s, EventArgs e)
{
Console.WriteLine("next message");
});
fetchHandler.Envelope += new EventHandler<EventArgs<IMAP_Envelope>>(delegate(object s, EventArgs<IMAP_Envelope> e){
IMAP_Envelope envelope = e.Value;
if (envelope.From != null && !String.IsNullOrWhiteSpace(envelope.Subject))
{
Console.WriteLine(envelope.Subject);
}
});
// the best way to find unread emails is to perform server search
int[] unseen_ids = client.Search(false, "UTF-8", "unseen");
Console.WriteLine("unseen count: " + unseen_ids.Count().ToString());
// now we need to initiate our sequence of messages to be fetched
sequence.Parse(string.Join(",", unseen_ids));
// fetch messages now
client.Fetch(false, sequence, new IMAP_Fetch_DataItem[] { new IMAP_Fetch_DataItem_Envelope() }, fetchHandler);
// uncomment this line to mark messages as read
// client.StoreMessageFlags(false, sequence, IMAP_Flags_SetType.Add, IMAP_MessageFlags.Seen);
}
Bit complicated, but works fine. Limisoft library is not perfect, so be sure you test it well.
Messages on the server have a UID (at least for IMAP.) By definition the UID will only increase. Meaning if you have a UID of 321, the next UID has to be 322 or higher. So you could store the "Last UID" in your DB, and then get the highest UID from the server. If it's higher than your last one, load the new ones.

Categories

Resources