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

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);
}
}
}
}

Related

c# forward Email from Outlook inbox

I want to forward an existing Email from my Outlook inbox folder. On recent research I found some different solutions:
get the current mail item and copy it to a new message
move method to move in a different folder
forward method...
My goal is to find a simple way to forward an existing Email to another E-Mail adress.
My code enclosed does not have access to send!
private void buttonExplorer_Click(object sender, RibbonControlEventArgs e)
{
Microsoft.Office.Interop.Outlook.Selection mySelection = Globals.ThisAddIn.Application.ActiveExplorer().Selection;
Microsoft.Office.Interop.Outlook.MailItem mailItem = null;
foreach (Object obj in mySelection)
{
if (obj is Microsoft.Office.Interop.Outlook.MailItem)
{
mailItem = (Microsoft.Office.Interop.Outlook.MailItem)obj;
mailItem.Forward();
mailItem.Recipients.Add("test#web.com");
mailItem.Send();
}
}
}
Would be nice if there is a simple way to solve the forwarding event issue.
Forward() creates a new item, as stated here.
So you'll need to use that new item from then on:
var newItem = mailItem.Forward();
newItem.Recipients.Add("to.alt#web.de");
newItem.Send();
Try using Microsoft Exchange Web Service (EWS) to forward the email messages. EWS provides api for the commonly used events.
A sample code would like this,
// Connect to Exchange Web Services as user1 at contoso.com.
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("user1#contoso.com", "password ");
service.AutodiscoverUrl("user1#contoso.com");
// Create the e-mail message, set its properties, and send it to user2#contoso.com, saving a copy to the Sent Items folder.
EmailMessage message = new EmailMessage(service);
message.Subject = "Interesting";
message.Body = "The proposition has been considered.";
message.ToRecipients.Add("user2#contoso.com");
message.SendAndSaveCopy();
For more info, refer https://msdn.microsoft.com/en-us/library/office/dd633681(v=exchg.80).aspx

EWS managed API Pull notification to watch the new email is not working

I am creating a application which will work as a window service in the back ground. This application will parse the new emails in the inbox and save the attachments. I tried streaming notification but as the connection disconnects after 30 mints I thought to use pull notifications. Below is the code which I debug but I don't see any output on console. As soon as I run the application it closes the console window so don't know if it is working. I want watch the new email as soon as it enters in the inbox so need some guidance how to achieve that.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Exchange.WebServices.Data;
using System.Configuration;
using System.Timers;
namespace PullNotification
{
class Program
{
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
WebCredentials wbcred = new WebCredentials(ConfigurationSettings.AppSettings["user"], ConfigurationSettings.AppSettings["PWD"]);
PullSubscription SubscriptionInbox;
service.Credentials = wbcred;
service.AutodiscoverUrl(ConfigurationSettings.AppSettings["user-id"], RedirectionUrlValidationCallback);
SubscriptionInbox = service.SubscribeToPullNotifications(new FolderId[] { WellKnownFolderName.Inbox }, 5/* subcription will end if the server is not polled within 5 mints*/, null/*to start a new subcription*/, EventType.NewMail, EventType.Modified);
//Timer myTimer = new Timer();
//myTimer.Elapsed += new ElapsedEventHandler(GetPullNotifications);
//myTimer.Interval = 10000;
//myTimer.Start();
GetEventsResults events = SubscriptionInbox.GetEvents();
EmailMessage message;
foreach (ItemEvent itemEvent in events.ItemEvents)
{
switch (itemEvent.EventType)
{
case EventType.NewMail:
try
{
Item item = Item.Bind(service, itemEvent.ItemId);
if (item.Subject == "A123")
{
Console.WriteLine("check the code");
}
}
catch (Exception e)
{
Console.WriteLine("error=" + e.Message);
}
break;
case EventType.Deleted:
Item item1 = Item.Bind(service, itemEvent.ItemId);
Console.WriteLine("Mail with subject" + item1.Subject + "--is deleted");
break;
}
}
//Loop
}
internal static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
//The default for the validation callback is to reject the URL
bool result=false;
Uri redirectionUri=new Uri(redirectionUrl);
if(redirectionUri.Scheme=="https")
{
result=true;
}
return result;
}
}
}
Pull notifications require that you issue a pull request (via GetEvents) when you want updates the difference between the notification methods is described in https://msdn.microsoft.com/en-us/library/office/dn458791%28v=exchg.150%29.aspx .Your code has no loop and only issue one GetItem request which is why it behaves the way you describe which is normal.
I want watch the new email as soon as it enters in the inbox so need some guidance how to achieve that.
If you want the Server to notify you when an email has arrived then you need to either look at Push or Streaming notifications Pull notifications requires that you poll the server for updates.
I tried streaming notification but as the connection disconnects after 30 mints
That's normal you just need code to reconnect and manage the subscription see http://blogs.msdn.com/b/emeamsgdev/archive/2013/04/16/ews-streaming-notification-sample.aspx for a good sample.
Cheers
Glen

SmtpMail.Send() doesn't work

i have a problem with send mail in c#; it doesn't send any mail and also doesn't throw any exceptions with failure :
using System.Web.Util;
public static void SendEmail(string _FromEmail, string _ToEmail, string _Subject, string _EmailBody)
{
// setup email header .
SmtpMail.SmtpServer = "localhost";
MailMessage _MailMessage = new MailMessage();
_MailMessage.From = _FromEmail;
_MailMessage.To = _ToEmail;
_MailMessage.Subject = _Subject;
_MailMessage.Body = _EmailBody;
try
{
SmtpMail.Send(_MailMessage);
}
catch (Exception ex)
{
throw new ApplicationException("error has occured: " + ex.Message);
}
}
please help!
Check the folders in your IIS' Mailroot directory (probably located in C:\InetPub\Mailroot). Chances are your mails are dropped there, probably in the Badmail or the Queue directory.
see C:\InetPub\Mailroot\queue folder. if your emails got stuck in this folder then
1>> stop your SMTP
2>> move emails from queue folder to C:\inetpub\mailroot\Pickup folder and start your smtp server and wait for few seconds.
if your email got stuck in queue folder again then you need to enable smtp logging for more information. use this link to see how to enable smtp logging.
http://www.msexchange.org/tutorials/Logging_the_SMTP_Service.html

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.

Check for unread emails

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.

Categories

Resources