Can two separate Windows services access the same POP mailbox simultaneously? - c#

We have got a single POP e-mail account. This e-mail account is filled with:
mails with subject XYZ
mails with subject ABC
We have two Windows services
Service 1 - Which picks up emails with Subject XYZ only (Reads an email, stores it in the database and then deletes it from the mailbox)
Service 2 - Which picks up emails with Subject ABC only (Reads an email, stores it in the database and then deletes it from the mailbox)
Can these two separate C# services (Service 1 & 2) (.Net framework 4.0) run simultaneously on this single POP enabled mailbox and work without any access conflicts over the mailbox?

Yes - there is generally no restrictions on how many clients can connect with the same account sequentially.
Notes
you should not be constantly be connecting - polling and disconnecting is the expected approach.
you may have issues deleting items due to way POP3 addresses items - may need to synchronize deletion in some way if server does allow 2 clients for the same user to be in TRANSACTION state at the same time (unlikely).
server may have some protection against frequent access from different IP in addition to exclusive single user access - you need to check with particular service provider if there are any restrictions (also likely for 2-3 well known clients you'd be fine).
See POP3 RFC 1939 for details.

Yes, multiple processes should be able to read from the same mailbox simultaneously.
The caveats are
That the server supports simultaneous access (it should)
That neither process is deleting messages.
Caveat #2 is important in that both processes have to read through the list of messages to find messages that are appropriate to them, but neither process will know which messages the other process has already read. If either process deletes a message, it opens up the possibility that one process will already know the message exists and attempt to read said message after the second process has deleted it. (A race condition.)
A better approach might be to have a single "Mail Reader" process read all messages, enter them into different queues (perhaps stored in a database) which are then handled by the other two "Do Work" processes. After the Mail Reader process has successfully placed the message into a queue, then it can safely delete the message from the mailbox.

Related

Not finding any new messages received after connection is made

The scenario is a Windows Service connects to an outlook.com or a gmail.com POP3 account using OpenPOP. It finds existing emails if there are any (i.e. client.getMessageCount() returns a value larger than zero).
The service keeps the connection open and rechecks for new messages.
The problem is that if i send email to that account after the service has connected then the getMessageCount() always returns zero until the service automatically re-cycles the pop connection.
I'm hoping someone has had the same issue.
I cannot resolve the issue by more frequent pop diconnect/reconnects as some providers (like outlook.com) have limits to time between connects.
The POP3 specification mentions that a mailbox is locked while a client has it open. Therefore no messages can appear.
Think of this scenario: Most servers assigns new messages a low message number. You have just fetched all the message numbers:
1 - Foo message
2 - Bar message
You now want to delete the Foo message, but the server updates the maildrop to look like:
1 - Baz message
2 - Foo message
3 - Bar message
You send the command DELE 1, and have now marked the Baz and not the Foo message to be deleted. The POP3 protocol was developed when internet was a sparse resource and you were not always connected. If you want to have live updates to a maildrop, you should use the much newer IMAP protocol instead.
If you keep using POP3, you will have to disconnect and connect again to have updates. Notice that most servers does not allow clients to continue to connect/disconnect in a fast manner, they will simply reject your authentication if you are connecting too often.
Also notice that Gmail have a strange POP3 implementation. See What non-standard behaviour features does Gmail exhibit, when it is programmatically used as a POP3 server?

Best way to test high-volume SMTP email sending code?

I've written a component in a Windows service (C#) which is responsible for sending sometimes large volumes of emails. These emails will go to recipients on many domains – really, any domain. (Yes, the recipients want the email. No, I'm not spamming. Yes, I'm in complaince with CAN-SPAM. Yes, I'm aware sending email from code sucks.) Many of the emails are transactional (generated in response to user actions); some are bulk (mail-merges basically).
I do not want to rely on an external SMTP server. (Among other considerations, the thought of having to check a mailbox for bounce messages and trying to parse them gives me bad feelings.)
My design is fairly simple. Both the transactional and bulk messages are generated and inserted into a DB table. This table contains the email envelope and content, plus an attempt count and retry-after date.
The service runs a few worker threads which grab 20 rows at a time and loop through each. Using the Simple DNS Plus library, I grab the MX record(s) of the recipient's domain and then use System.Net.Mail.SmtpClient to synchronously send the email. If the call to Send() succeeds, I can dequeue the email. If it temporarily fails, I can increment the attempt count and set an appropriate retry-after date. If it permanently fails, I can dequeue and handle the failure.
Obviously, sending thousands of test emails to hundreds of different actual domains is a Very Bad Idea. However, I definitely need to stress-test my multi-threaded send code. I'm also not quite sure what the best way is to simulate the various failure modes of SMTP. Plus, I want to make sure I get past the various spam control methods (graylisting to name the most relevant to the network layer of things).
Even my small-scale testing difficulties are exacerbated by my recent discovery of my ISP blocking connections to port 25 on any server other than my ISP's SMTP server. (In production, this thing will of course be on a proper server where port 25 isn't blocked. That does not help me test from my dev machine.)
So, the two things I'm most curious about:
How should I go about testing my code?
What are the various ways that SmtpClient.Send() can fail? Six exceptions are listed; SmtpException and SmtpFailedRecipientsException seem to be the most relevant.
Update: Marc B's answer points out that I'm basically creating my own SMTP server. He makes the valid point that I'm reinventing the wheel, so here's my rationale for not using an 'actual' one (Postfix, etc) instead:
Emails have different send priorities (though this is unrelated to the envelope's X-Priority). Bulk email is low priority; transactional is high. (And any email or group of emails can be further configured to have an arbitrary priority.) I need to be able to suspend the sending of lower-priority emails so higher-priority emails can be delivered first. (To accomplish this, the worker threads simply pick up the highest priority items from the queue each time they get another 20.)
If I've already submitted several thousand bulk items to an external SMTP server, I have no way of putting those on hold while the items I wish to submit now get sent. A cursory Google search shows Postfix doesn't really support priorities; Sendmail prioritizes on information in the envelope, which does not meet my needs.
I need to be able to display the progress of the send process of a blast (group of bulk emails) to my users. If I've simply handed all of my emails off to an external server, I have no idea how far along in actual delivery it is.
I'm hesitant to parse bounce messages because each MTA's bounce message is different. Sendmail's is different from Exchange's is different from [...]. Also, at what frequency do I check my bounce inbox? What if a bounce message itself isn't delivered?
I'm not too terribly concerned with a blast failing half-way through.
If we're talking catastrophic failure (app-terminating unhandled exception, power failure, whatever): Since the worker threads dequeue each email from the database when it is successfully delivered, I can know who has received the blast and who hasn't. Further, when the service resets after a failure, it simply picks up where it left off in the queue.
If we're talking local failure (a SmtpException, DNS failure, or so forth): I just log the failure, increment the email's attempt counter, and try again later. (Which is basically what the SMTP spec calls for.) After n attempts, I can permanently fail the message (dequeue it) and log the failure for examination later. This way, I can find weird edge cases that my code isn't handling – even if my code isn't 100% perfect the first time. (And let's be honest, it won't be.)
I'm hoping the roll-my-own route will ultimately allow me to get emails out faster than if I had to rely on an external SMTP server. I'd have to worry about rate-limiting if the server weren't under my control; even if it were, it's still a bottleneck. The multithreaded architecture I've gone with means I'm connecting to multiple remote servers in parallel, decreasing the total amount of time it takes to deliver n messages.
Assume you've got two servers available. One will be the sender, one will be the receiver. You can set up DNS (or even just hosts files) on both with a long series of fake domains. As far as the two servers are concerned, those domains are perfectly valid as the local DNS servers are authoritative for them, but are completely invalid as far as the rest of the net is concerned. Just make sure the resolver checks the hosts file before DNS.
Once that's done, you can have the sending server spam the receiving server to your heart's content, as have the receiver do various things to test your code's reactions. Greylisting, TCP delays, hard bounces, ICMP unreachables, ICMP hops exceeded, etc...
Of course, given you have to test all these conditions, you're basically creating your own SMTP server, so why not use an actual one to begin with? I'd guess the effort required to do some basic parseing of bounce messages will be far less than having to come up with code chunks to handle all the failure modes that postfix/sendmail/exim/etc... already handle perfectly well on their own.
And this is especially true when you consider your sending code has to be perfect from the get-go. If an email blast fails part-way through and only half the recipient list gets the message, you're in a far bigger hole than if a few hundred or a few thousand messages bounce. Or worse yet, fails in multiple different ways (some servers unreachable, some greylisting you for excessive traffic, etc...). Whereas bounces will happily sit in the incoming queue until you process them manually, or patch up your bounce parser to handle them.
After searching around, I ended up firing up Papercut on several extra machines I had laying around. I then populated my database with test addresses *#[test-machine-*.local].
While this did work well enough, I tested with 25 send threads and it looked like I was overwhelming the four computers running Papercut. Several hundred send attempts experienced TCP connection failures; those messages were properly requeued to be sent later (and ultimately did arrive). However, out of 25,000 test emails, about 500 simply disappeared – adding up the *.eml files in Papercut's folder on each test machine yielded only ~24,500.
Now I'm left wondering whether the missing emails are a due to a problem in my code, or if Papercut dropped messages which it reported in SMTP as 250 OK.

How to notify a person when this goes down?

I made a simple notifier command line application in C#. Basically I use the windows task scheduler and set it up to run this command line application at a certain time.
When this time is hit the command line application is ran all notifications are grabbed from a database(using linq to sql) formatted and sent by smtp to the right people.
Now how should I handle these scenarios
A database error occurs
Solution: Send a email to the admin to notify them that it failed and to check it out.
A smtp error occurs
Solution: ?????
So these are really the two things that could go wrong. There could be different combination's of this.
Database error might occur and and smtp might occur too, Or only one or the other might occur.
So how to get this information to an admin or someone so they can fix it. I highly doubt that an admin would go and check every single day to see if the notification thing worked or not.
So basically how to make it fail safe or at least make it so that if something goes wrong a admin can come fix and it and just run the notifier manually and get everything back in sync.
You have a couple options.
Write the error information to a log. Make it a procedure for some operator to check the log every so often.
Have it call some other service?
However, if the database is used by more than just your app, it's entirely possible that someone else will notice. Same thing with the email server. If it's down, then I bet a lot of people will be making phone calls. Note that your situation precludes lost network connectivity (like a dead switch or misconfigured router).
Incidentally if it detects SMTP is back up, then it should notify someone that it was down for a given time period. Same thing about the database server.
Finally, ALL error conditions should be written to your system log. It's pretty trivial to write to the windows event logs. If your system administrators are following commonly accepted protocols they should be monitoring those pretty often anyway.
Logging an Error to the EventLog could also be an option, providing that the Admin either checks the EventLog regularly or that you have monitoring systems that aggregate those errors.
You could use an SMS gateway or attach a cellphone to the server and have it send a text message to an admin when something has gone horribly wrong.
But you can take this even further:
What if you lose network connectivity
(a switch or cable gone bad for
example)?
What if the power goes down
(when is the last time you tested the
UPS)?
Depending on your needs (and the business cost of not sending out these notifications in short notice), you may need a full-fledged monitoring solution.
So the main problem is that you do not know how to notify the admin in case of an SMTP server failure. You have several options, assuming the admin's e-mail account is not residing on the same server.
First option: You could set up a cgi mail script on another server and contact that via http to send the e-mail.
Second option: Use an smtp client and set it up to contact the receiver's smtp server for sending the e-mail directly (instead of going through the local smtp server).
BTW: Some e-mail providers offer text message notifications for e-mails originating from a certain address. That's very handy if the server goes down while the admin is away from his desk.
For your DB errors, you could hardcode in a (set of) email address for DB errors to be sent to.
As for the SMTP errors, you can either do a "send email when smtp recovers", or you have to have an alternate method for alerting your admins. This could be a backup SMTP server, a SMS gateway (as someone else mentioned), or even something such as someones desktop in the network popping up an alert if it doesn't receive some type of "everything is ok" alert/message from the box running the script.

Meaningful interaction with IIS SMTP Server in .Net

Our business sends a newsletter to a vast number of subscribers every week. When the business was very young, before I joined, they used a "free" version of some mass mailer that took six hours to send 5K mails and fell foul of every reverse DNS check on the internet.
I upgraded this to a bespoke .Net widget that ran on the correct server and could send up to about 20k mails in half an hour with full DNS compliance. Unfortunately (or fortunately depending on your standpoint) our mail list has now outgrown this simple tool. In particular its lack of adequate throttling, it can make more mails than the server can comfortably send at once. I need to actually monitor how full the IIS SMTP server's available outgoing mail storage allocation is and throttle the load accordingly.
Unfortunately I can find no information on where a mail object goes when (or even if) it is turned into a mail. I can implement a filesystemwatcher if I have a place to watch, currently I don't. If no actual mail file is ever created I guess I will have to create one to implement the functionality but I need to know where to put it. It would also be more reassuring to allow the system to confirm sending somehow but I have no idea how to go about retrieving data from the system that says a mail has been sent.
Extensive Googling has proven vague on these points; so I was wondering if anyone here knew where I could get a guide to these problems, or could otherwise point me in the right direction.
Many thanks.
EDIT: In the end I gave up trying to measure throughput on the IIS SMTP server as a bad job. It just didn't seem to want to play. I'm now carrying out my logging in a separate location and just shunting it through to the SMTP server thereafter. I still don't know of anyone who really bothers trying to keep tabs on the doings of the IIS SMTP server and so this question as of this writing goes unanswered.
Oh well...
Okay so I've been working on this project for ages now and I thought I might share my findings with the world.
The IIS SMTP Server
All mails created using the IIS SMTP server are sent, in the first instance, to the Pickup Directory. If you are sending one mail then you will have to operate in Matrix time to actually ever see it there because it will probably just go, straight away.
On an individual mail's way out of the door it passes through the queue folder in IIS.
If you wanted to watch the Performance Counter to monitor this process you ould look at the "Remote Queue Length". (The reason for this is that the "Local Queue Length" monitors mails sent "Locally" within the network. "Remote" in this instance refers to "Outside into the world". The specific definition of "Local" escapes me as we send no local mail but I imagine it means queued to go to mailboxes contained within the specific installation of IIS on the server or any local grouping thereof.)
From an Exchange point of view it seems to be the equivalent of mails sent within the Exchange Domain and those sent out of that domain into the wider world.
Anyhow. The Remote Queue Length doesn't tell the whole story. You also have to look at the Remote Retry Queue, the number of Current Outbound Connections and, for belt and braces sake the actual number of files in the queue directory.
Here's why:
Remote Queue: All messages that have not
yet been sent, however many times
this has been tried. The number of
mails currently assigned to any open
connections are not counted as they
are in a state of "being tried".
Remote Retry Queue: All messages that
have not yet been sent that have, at
some point in the past, been assigned
to an open connection for delivery.
Obviously the delivery must have
failed or the message would have been
delivered. Any messages currently
assigned to an open connection for a
retry are not counted.
Current Outbound Connections: Shows when the
server is attempting to send queued
mails, more than one message can be
assigned to an outbound connection.
Messages thus assigned are not
counted in either the Remote Queue or
the Remote Retry queue. Physical
Files in the queue directory: This
shows the number of mails still in
the Queue directory. This will
decrease as mails are successfully
delivered.
Example: If you have 0 outbound connections and 50 mails in the Queue directory then the Remote Queue, Retry Queue and Physical files will all read at 50. When a retry flag is raised (this is a setting in IIS) the number of connections increases and the number of mails in the queues decreases. Until a mail is delivered the number of physical files remains the same. However as more than one mail can be sent on a current connection 1 connection may result in Remote Queue and Retry Queue lengths of 47 or lower. If, during the retry event, any mails are successfully delivered the number of physical files in the Queue directory will then decrease. When the connection closes the queue counters should all stabilise again.
Logging
It is possible with .Net's Mail library to Specify a Pickup directory separate from the IIS default. Here you can queue mails and get a bespoke service to occasionally move the mails into the IIS directory where the IIS service will take over and send out queued mails.
To do this you will be looking for the SmtpClient object's "DeliveryMethod" property which should be set to SmtpDeliveryMethod.SpecifiedPickupDirectory.
To actually set the SpecifiedPickupDirectory you should set the SmtpClient's PickupDirectoryLocation property.
When mails are delivered to this location they are stored as .eml files. The filename is a GUID. This means that multiple emails will be despatched in an essentially random order. You could, in theory, write code to address this situation if desired. The .eml file follows a standard format which can be read by opening the .eml in notepad. Parsing this will allow you to extract information for a log.
I hope this high level overview of the way the SMTP server in IIS works is of some assistance to someone in a similar position to the one I was in in March.
I would use the PerformanceCounter component to read the SMTP Service's Local Queue Length counter. That should keep you in control :-)
If your .net widget is bespoke, why not just throttle it's output to some (definable) throughput?
As an alternative you might be able to fiddle with some registry settings for the SMTP server.
http://blog.rednael.com/CommentView,guid,dc20366c-3629-490a-a8ee-7e8f496ef58b.aspx
Apparently there are also some WMI counters (SMTP Server\Remote Queue Length and SMTP Server\Remote Retry Queue Length) that will give you useful information.
http://www.tech-archive.net/Archive/Internet-Server/microsoft.public.inetserver.iis.smtp_nntp/2008-02/msg00011.html

Programmatically Verify an email message reached an exchange mail box

I have a job that runs which sends out emails to our users to which starts off a work flow process in our company. Periodically, a user will swear up and down that they didn't receive the email - though, when we go to the mail administrator to pull an exchange report, 10 times out of 10 it's in their deleted items. :P
I'd like to be able to programmatically verify that messages sent via .net C# (System.Net.Mail I think) reached the user's mail box.
It's exchange 2007 and all messages are internal.
You can't with System.Net.Mail. You'll have to dig through Exchange's APIs to determine if an email is present in someone's email account.
http://support.microsoft.com/kb/813349
Set an account for catching all bounce backs. In this way you will know which ones reached and which ones did not. This is the best way to ensure emails reached.
Alternatively you can add read reciepts via message headers(by setting the Disposition-Notification-To). but again, user can chose not to read it...
I see two ways to do what you want:
Send emails with "delivery confirmation" On (not "read receipt", this can be dismissed by the user as CoddeToGlory said). Then it's jut a matter of monitoring the mailbox that receives these confirmations via any way it's appropiate to you: Exchange Web Services, Outlook+COM or VBA, MAPI, ...
Use the powershell interface to Exchange and capture the output of Get-MessageTrackingLog looking for StoreDriver + Deliver events.

Categories

Resources