views:

64

answers:

1

Hi everyone,

I'm looking for some opinions here, I'm building a web application which has the fairly standard functionality of:

  1. Register for an account by filling out a form and submitting it.
  2. Receive an email with a confirmation code link
  3. Click the link to confirm the new account and log in

When you send emails from your web application, it's often (usually) the case that there will be some change to the persistence layer. For example:

  1. A new user registers for an account on your site - the new user is created in the database and an email is sent to them with a confirmation link
  2. A user assigns a bug or issue to someone else - the issue is updated and email notifications are sent.

How you send these emails can be critical to the success of your application. How you send them depends on how important it is that the intended recipient receives the email.

We'll look at the following four strategies in relation to the case where the mail server is down, using example 1.

TRANSACTIONAL & SYNCHRONOUS The sending of the email fails and the user is shown an error message saying that their account could not be created. The application will appear to be slow and unresponsive as the application waits for the connection timeout. The account is not created in the database because the transaction is rolled back.

TRANSACTIONAL & ASYNCHRONOUS The transactional definition here refers to sending the email to a JMS queue or saving it in a database table for another background process to pick up and send.

The user account is created in the database, the email is sent to a JMS queue for processing later. The transaction is successful and committed. The user is shown a message saying that their account was created and to check their email for a confirmation link. It's possible in this case that the email is never sent due to some other error, however the user is told that the email has been sent to them. There may be some delay in getting the email sent to the user if application support has to be called in to diagnose the email problem.

NON-TRANSACTIONAL & SYNCHRONOUS The user is created in the database, but the application gets a timeout error when it tries to send the email with the confirmation link. The user is shown an error message saying that there was an error. The application is slow and unresponsive as it waits for the connection timeout

When the mail server comes back to life and the user tries to register again, they are told their account already exists but has not been confirmed and are given the option of having the email re-sent to them.

NON-TRANSACTIONAL & ASYNCHRONOUS The only difference between this and transactional & asynchronous is that if there is an error sending the email to the JMS queue or saving it in the database, the user account is still created but the email is never sent until the user attempts to register again.

What I'd like to know is what have other people done here? Can you recommend any other solutions other than the 4 I've mentioned above? What's a reasonable way of approaching this problem? I don't want to over-engineer a system that's dealing with the (hopefully) rare situation where my mail server goes down!

The simplest thing to do is to code it synchronously, but are there any other pitfalls to this approach? I guess I'm wondering if there's a best practice, I couldn't find much out there by googling.

+4  A: 

My 2 cents:

  1. Once you have a user sign up, never roll back the registration if sending the E-Mail fails. For simple business reasons: They may not come back or re-register if it doesn't work out at the first try. Rather tolerate an incomplete registration and nag the user to confirm their E-Mail address as soon as possible.

  2. In most cases when sending an E-Mail goes wrong, your app will not get immediate feedback anyway - non-existent E-Mail addresses on valid servers will send back a "undeliverable" message with some delay; if the mail gets eaten by a spam filter, you'll get no feedback at all; in other scenarios, it may take several minutes (greylisting) to several days (mail server temporarily down) for an E-Mail to get delivered. A synchronous approach waiting for the delivery of the mail is therefore doomed IMO. Even an immediate failure (because the user entered a obviously fake address) should never result in the registration getting rolled back.

What I would do is, make account creation as easy as possible, allow the user access to the account before it is confirmed, and then nag the hell out of them to confirm their E-Mail (if necessary, limit access to certain areas until confirmation). I would prevent the creation of a second account with the same E-Mail, though, to prevent clutter.

Make sure you allow changing the E-Mail address even if the previous address hasn't been confirmed yet, and enable the user to re-request the confirmation message to a different address.

Pekka
This answer needs to be carved into stone somewhere in Silicon Valley, and religiously adhered to by all sites that require registration.
MusiGenesis
Some great points, thanks!
Annie
So Pekka - you didn't comment on whether the email should be sent sychronously or asynchronously, any opinions here?
Annie
@Denise asynchronously definitely, I'd say. You can check for the most usual "immediate" errors straight away (invalid address, server non-existent). If those two things are all right, dispatch the E-Mail, proceed with the registration and nag the user until they click the confirm link in the mail.
Pekka
@Denise please confirm that I'm understanding you correctly: By "synchronous" you mean work through the sending process during registration, and proceed with registration only when the process has been finished, as opposed to "asynchronously" putting the message into a queue and proceeding straight away, correct?
Pekka
Yep, that's what I mean by synchronous and asynchronous :) As an aside, do you have any suggestions (from a technology point of view) on how to implement this asynchronously?
Annie
@Denise Usually, one would pass the message to another script that runs in the background. What platform are you on?
Pekka
Developing a Java web app using spring and JPA, I'm thinking of maybe putting the emails in a database table and have a background process poll the table for new emails and send them.
Annie
@Denise don't know much about Java so I can't say what's the best practice there... Maybe worth another question. Having a background process sounds entirely feasible though.
Pekka
Cool, thanks for your help :)
Annie