If you need to implement newsletter sending, rapidmail Show archive.org snapshot is a solid option.
Support is very fast, friendly and helpful, and the initial setup is simple. Since rapidmail works via SMTP, you can simply ask the Ops team to configure SMTP credentials for your application.
You also do not need to use rapidmail’s built-in newsletter feature. Instead, you can send emails as transactional mails, which allows you to keep the entire newsletter logic inside your application.
One thing to keep an eye on is the sending quota. Rapidmail notifies you when 70% of the quota is used, so you have enough time to scale the plan if needed.
Implementing Gmail's one-click unsubscribe
Modern mail clients (e.g. Gmail) support a native unsubscribe button if your email contains the appropriate headers.
You only need to set the following headers in your mailer:
List-UnsubscribeList-Unsubscribe-Post
Example (simplified):
def press_release(press_release, frontend_user, locale: I18n.default_locale, from: DEFAULT_NEWSLETTER_SENDER_ADDRESS)
@subject = press_release.title.localize(locale)
@token = frontend_user.unsubscription_token
headers['List-Unsubscribe'] = "<#{unsubscribe_all_unsubscribe_url(token: @token)}>"
headers['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click'
mail from:,
to: frontend_user.email,
subject: @subject
end
Generating an unsubscribe token
Each user needs a token that allows them to unsubscribe securely.
Rails' signed_id works well for this:
class FrontendUser < ApplicationRecord
# ...
def unsubscription_token
return unless persisted?
signed_id(purpose: :unsubscription)
end
# ...
end
Processing the unsubscribe request
The unsubscribe endpoint receives the token and updates the user's newsletter preference.
# Optional form model with ActiveType
class FrontendUser::Unsubscription < ActiveType::Record[FrontendUser]
# ...
end
# routes.rb
resource :unsubscribe, only: [:show, :update], controller: :unsubscribe do
member do
post :unsubscribe_all
end
end
# app/controllers/frontend/unsubscribe_controller.rb
def unsubscribe_all
load_unsubscription
if @unsubscription.update(receives_newsletter: false)
head :ok
else
head :unprocessable_entity
end
end
private
def load_unsubscription
@unsubscribe_token = params[:token]
@unsubscription = FrontendUser::Unsubscription.find_signed(@unsubscribe_token, purpose: :unsubscription)
unless @unsubscription
respond_to do |format|
format.html do
redirect_to root_path, alert: I18n.t('frontend.unsubscribe.invalid_link')
end
format.all do
head :not_found
end
end
end
end
The endpoint should accept the POST request triggered by the List-Unsubscribe-Post header and return 200 OK if the unsubscribe succeeds.