A while ago, Marc Kohlbrugge asked me to implement an interesting feature into startup.jobs that I had not previously considered building in my apps. Because it provides a great benefit to the user, I have written this blog post for people who want to implement the List-Unsubscribe header with Rails.
First, I’ll explain about this feature, which you may have seen in emails you have received. On Apple Mail.app on iOS, you’ll often see this in the header of an email:
By clicking on the “Unsubscribe” button you get automatically unsubscribed from this email list. You might wonder how this works. When you look at the raw email you’ll see this:
Here you can see that the sender of this email included a List-Unsubscribe
header to the email. This way, email clients can provide you a way to opt-out of future emails. When you click the button in your client, the email client sends an email on your behalf to the specified email address.
In this blog post, I’ll explain how to implement this using ActionMailbox.
When a person unsubscribes, it’s important to know who that user is. The easiest and most secure way to do this is by adding a new field to the database, which I call the unsubscribe_token
. You could say: Why not use user.id
? However, that would allow users to unsubscribe other users by providing the other person’s id.
The migration to add the token:
class AddUnsubscribeTokenToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :unsubscribe_token, :string
add_index :users, :unsubscribe_token
end
end
Then also add it to the User model:
class User < ApplicationRecord
has_secure_token :unsubscribe_token
end
Write the route in the file called app/mailboxes/application_mailbox.rb
. This handles every incoming email that starts with unsubscribe-
. You can also choose something else, but be sure that you supply the right address in the header.
class ApplicationMailbox < ActionMailbox::Base
routing(/unsubscribe-/i => :unsubscribers)
end
Then create the Mailbox (you could compare this to a regular Rails controller). For another example, see the documentation.
class UnsubscribersMailbox < ApplicationMailbox
before_processing :set_user
def process
@user.update_column(:send_saved_search_emails, false)
end
def set_user
recipient = inbound_email.mail.to.first
unsubscribe_token = recipient.scan(/unsubscribe-(.+?)@/i)
inbound_email.bounced! if unsubscribe_token.blank? || (@user = User.find_by(unsubscribe_token: unsubscribe_token)).blank?
end
end
Then final step is to add the header to the email. In a mailer, you can add headers to the mail by listing them in the call to mail
.
class SavedSearchEmailMailer < ApplicationMailer
def new_posts(user, new_posts)
@user = user
mail to: @user.email,
subject: title,
"List-Unsubscribe": "<mailto:unsubscribe-#{@user.unsubscribe_token}@startup.jobs>"
end
end
This is best explained in the Rails documentation for ActionMailbox.
Like this post? Follow me at @jankeesvw on Twitter