Rails email with unsubscribe link

I am working on a Rails 4.2 application that has recurring weekly events for which people are logged. They will receive an email reminder before each event (so weekly). I want the email to have a one-click subscription link. This seems like a general task, but I have not found a good current solution. Some directions I've seen are to use MessageVerifier, which was new to Rails 4.1, and does not require saving a token string for comparison with the database. What are the steps for this. I have a user model and an event model. Emails are sent to registered users who have registered for a recurring event.

+7
email ruby-on-rails
source share
2 answers

Here is a solution I developed to link to unsubscribe from regular emails sent to subscribers. It uses MessageVerifier.

1. Create a cryptographic hash of user.id

In my event controller, I have a send_notice action that sends an email. I will create a variable for the unsubscribe link and pass it to the mailer.

# app/controller/events_controller.rb def send_notice ... @unsubscribe = Rails.application.message_verifier(:unsubscribe).generate(@user.id) EventMailer.send_notice(@event, @user, @unsubscribe).deliver_later end 

This takes a user id and generates a signed and encoded @unsubscribe string variable. The message verifier turns the user ID into an illegible character string, mixing it with your secret_key_base (found in the config / secrets.yml file) and the name you pass to this message (in this case I call it: unsubscribe, but it can be any name) like what they call a salt, and run it through the SHA1 algorithm. Make sure your secret_key_base is safe. Use environment variables to store value in production. In the last line, we pass the @unsubscribe variable to the mailer along with the @event and @user variables.

2. Add the @unsubscribe hash variable to the mailbox

 # app/mailers/event_mailer.rb def send_notice(event, user, unsubscribe) @event = event @user = user @unsubscribe = unsubscribe mail(to: user.email, subject: "Event Info") end 

3. Put the unsubscribe link in the email

 # app/views/events_mailer/send_notice.html.erb ... <%= link_to "Unsubscribe", settings_unsubscribe_url(id: @unsubscribe) %>. 

Note the argument added (id: @unsubscribe). This will add a coded user ID to the end of the URL starting with? in the so-called query parameter.

4. Add routes

Add a route where the user goes to the unsubscribe page. Then another route when they send an unsubscribe.

 # config/routes.rb get 'settings/unsubscribe' patch 'settings/update' 

5. Add a subscription field to the user model

I decided to add a boolean field (true / false) to subscribe to the user model, but you can configure it in different ways. rails g migration AddSubscriptionToUsers subscription:boolean .

6. Controller - decodes user_id from URL

I decided to add a settings controller with canceled subscription and update action. Generate rails g controller Settings unsubscribe . When the user clicks on the unsubscribe link in the email, he will go to the URL and add the encoded user ID to the URL after the question mark as a request parameter. Here's an example of what the link will look like: http: // localhost: 3000 / settings / unsubscribe? Id = BAhpEg% 3D% 3D - be9f8b9e64e13317bb0901d8725ce746b156b152 . The unsubscribe action will use MessageVerifier for unauthorized access and decoding the identity parameter to get the actual user ID and use it to find the user and assign it the @user variable.

 # app/controllers/settings_controller.rb def unsubscribe user = Rails.application.message_verifier(:unsubscribe).verify(params[:id]) @user = User.find(user) end def update @user = User.find(params[:id]) if @user.update(user_params) flash[:notice] = 'Subscription Cancelled' redirect_to root_url else flash[:alert] = 'There was a problem' render :unsubscribe end end private def user_params params.require(:user).permit(:subscription) end 

7. Views

Add the unsubscribe page that includes the unsubscribe form.

 # app/views/settings/unsubscribe.html.erb <h4>Unsubscribe from Mysite Emails</h4> <p>By unsubscribing, you will no longer receive email...</p> <%= form_for(@user, url: settings_update_path(id: @user.id)) do |f| %> <%= f.hidden_field(:subscription, value: false) %> <%= f.submit 'Unsubscribe' %> <%= link_to 'Cancel', root_url %> <% end %> 

There are several ways to fix this. Here I use form_for helper redirected to path_update_path with id argument added: @ user.id. This will add the user id to the url when submitting the form as a request parameter. The Update action will read it to find the user and update the Subscription field to false.

+28
source share

A really good option would be to use the Michael Hartl Rails tutorial application. In chapter 12, he implements a system in which users can follow other users' microposts (mainly tweets, Twitter style). You just need to configure model validations (user and event models) and implement the relationship model and controller. The relationship model and controller handle the entire following mechanism. In fact, the controller only has actions to create and delete, and the create action will create relationships and destroy them in order to delete them. To deal with the unsubscribe scenario, you can simply use the rails to remove the delete path in the ActionMailer template. The link above gives you step-by-step instructions, but if you get lost, feel free to ask me questions.

+2
source share

All Articles