views:

44

answers:

2

I have a simple rails app where user can send a mass email to 10+ people. In this email I'd like to always have a link at the bottom which the end user can click to unsubscribe himself from the notifications. I don't have much idea how I should tackle this.

can there be just a generic link in the email which users click then enter their email address to unsubscribe themselves? But problem with this is that some other user could unsubscribe someone else.

I would like to generate a specific unique link for each email so that when user clicks it, it automatically removes that user from the list rather than user having to do some extra work.

Where should I start in order to implement this?

A: 

Your unsubscribe links could look like this: http://host/application/[email protected]&token=598bbdf39bc8f27b07fe85b6a7dd8decef641605

Generate the token using the email address and a magic token. Ideally, you'd use HMAC with SHA256, but even just sha1 should be 'good enough':

$ echo "secret token [email protected]" | sha1sum
598bbdf39bc8f27b07fe85b6a7dd8decef641605  -

The secret token portion would be fixed in your application, and the [email protected] needs to match the email address.

Of course, if the secret token ever gets revealed, you're back to anyone unsubscribing everyone. You could also store per-user magic tokens in your database to validate the tokens in URLs, that wouldn't be much more difficult than this, and definitely much safer.

sarnold
I like this idea. but few questions. How do I generate that token from inside rails? and that token will be associated with each person who gets the email right? (a new column in DB). So when user clicks to unsubscribe, my rails code reads the token....does lookup on table and unsubscribes if it finds a person with that token
Patrick
@Patrick, [Jesse's](http://stackoverflow.com/users/363881/jesse-wolgamott) answer includes `SecureRandom`, which sounds like a great source for magic tokens. You could either store the token in your User model or create a new table with just user id and unsubscribe tokens, and populate it as you send emails.
sarnold
+1  A: 

If you have a model for EmailTemplate and a model for Subscriber, then your code might look something like:

@email_template = EmailTemplate.find(3)
@email_template.subscribers.each do |subscriber|
  Notifier.deliver_template(:email_template=>@email_template, :subscriber=>subscriber)
end

so, you could change to

email_delivery = EmailDelivery.create(:email_template=>@email_template, :subscriber=>subscriber)
Notifier.deliver_template(email_delivery)

And then the email_delivery's before_create generates a token. A random password generator per email_delivery should be good. SecureRandom does a good job at random tokens: p SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"

Include that email_delivery token in your email, and then do a lookup based solely on that.

Jesse Wolgamott
I have not made the controllers/models yet but I will try your approach as well.
Patrick