views:

187

answers:

7

I have a constantly-running Java program that needs to send an email whenever it encounters a problem. However it is possible that the mail server it uses could be down at the time it tries to send the email.

What is the best way to ensure that the email will be delivered when the mail server comes back up?

+2  A: 

Put the email object into a stack or list when it fails to send, when the email server comes back up, pop each email out until it is empty.

Guy
+7  A: 

Queue up the requests. Have a separate thread which merely waits for something to enter the queue, then tries to email it. If it fails, it waits a few hours and tries again. Once it sends a message, it goes back to the queue to get the next message.

S.Lott
I agree with this. If you have the chance to get a little more sophisticated, you can make your queue class(es) smart enough to know when a message is a repeat. Then, when your mail server comes back up you won't get 5,000 emails telling you that the network is down. :)
Scott Saunders
If you want guaranteed delivery you'll need to back it with a data store of some kind (database, file, etc) in case the application goes down and the queue is not clear.
Chris Hall
Or use a JMS queue manager that guarantees delivery. There are lots of these available commercially.
S.Lott
+2  A: 

You may want to save the email in a file, perhaps an xml file, so that should the application crash you won't lose this information.

This file is loaded when the application starts, and it keeps everything in memory, so that while there are pending emails then it keeps checking every 5 minutes or so, then, as it sends each email it will resave the xml file, so that should it crash after sending 3 emails out of 10 it won't resend those three when it starts up.

But, how you handle that is really going to depend on the specification for how to handle error conditions.

James Black
If you want to handle crashes, then you shouldn't be writing to the same file, because a crash while writing may cause large portions of data to be lost. Using multiple files is probably safer.
Hosam Aly
True, depending on the level of paranoia you could use two files, and just write to one, then replace the original, to limit the chance of problems. It all depends on how much you depend on reliability.
James Black
Why not maintain a directory of pending messages. That way you limit the possibility of corruption and you're not reading/writing one (potentially huge) file
Brian Agnew
@Brian Agnew - You can do that, but that will depend on how often systems go down. To have a separate directory means that you expect the system will go down often, and that the mail server is unavailable. Someone would need to do an analysis to determine what they should do for the chance of problems that they have.
James Black
+2  A: 

If you go from "forward everything to this SMTP server which is always there" to a situation where you need to handle all kinds of conditions normally handled by a full SMTP-server like retry later, retransmit if connection closed, use MX-hosts in their stated order and similar, you may want to consider simply having a SMTP-server inside your client (but one that does not accept incoming connections) since this moves all the dirty logic away from your applications.

I believe that the James email server - http://james.apache.org/ - is easily embeddable, but I have not actually tried.

Thorbjørn Ravn Andersen
A: 

The suggestion of using James is a good one but I've had some issues in the past of James being a bit flaky and needing to be restarted.

You could use something like Quartz to have a scheduler check for messages that need to be sent. If the message can't be sent (eg. smtp server isn't available), then that message is rescheduled to be sent at a later time. You could either have a task per message or have a persistent task that checks for messages and available mail server then sends the messages. The persistent task would give you email batching.

Carl
A: 

If you are in a Unix/Linux world, then consider the alternative of sending your alerts using syslog, and dealing with the generation of emails on that side. For example, nsyslogd has a module called ommail for generating emails natively.

IIRC, there are adapters for log4j and the like that can bridge between the Java and syslog worlds with a minimum of (zero ?) coding.

Stephen C
A: 

Apache James - http://james.apache.org/ will let you run your own mailserver as a proxy, not only that but is written in 100% java, so you can figure out what its doing, and as an extra bonus James uses databases to queue the mail, so you can even inject mail directly into the queues by inserting into a database, then leave whole business of sending the mail up to James.

danny