class: middle, center # Mailers [http://pjb3.me/bewd-mailers](http://pjb3.me/bewd-mailers) .footnote[ created with [remark](http://github.com/gnab/remark) ] --- # Action Mailer Action Mailer is the part of Rails that allows you to send emails. Mailers go in `app/mailers`. They are similar to controllers and uses views in `app/views`. For more info: [http://guides.rubyonrails.org/action_mailer_basics.html](http://guides.rubyonrails.org/action_mailer_basics.html) --- # Generating A Mailer We are going to use mailers to implement a basic welcome email feature for our site. .terminal $ rails g mailer UserMailer welcome You can execute this mailer in the rails console like this: .terminal $ rails c Loading development environment (Rails 4.1.0) >> UserMailer.welcome.deliver You will see the email message printed out in the console, but this isn't a very good way to preview email. Let's install mailcatcher to make this better. --- # Mail Catcher Mail Catcher is a server that runs on your machine that receives email and then allows you to preview those messages. This is useful for development and testing because it doesn't matter who these emails are from or to, they all end up in mail catcher. Mail Catcher is packaged as a gem, so to install it, you simply install the gem: .terminal $ gem install mailcatcher Then, you have to start up mail catcher: .terminal $ mailcatcher Starting MailCatcher ==> smtp://127.0.0.1:1025 ==> http://127.0.0.1:1080 *** MailCatcher runs as a daemon by default. Go to the web interface to quit. If you restart your computer, it will stop running, so you may have to do this again. It's ok if you try to start it again, you will just get this message: .terminal $ mailcatcher Starting MailCatcher ~~> ERROR: Something's using port 1025. Are you already running MailCatcher? Before we can use this, we need to configure Rails to use it. --- # Configuring Action Mailer The documentation at [http://mailcatcher.me](http://mailcatcher.me) actually has instructions on how to do this, but all you need to do is add these two lines before the end of the configure block in `config/environments/development.rb`: ```ruby config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 } ``` Now start a new rails console and send the `welcome` message again: .terminal $ rails c Loading development environment (Rails 4.1.0) >> UserMailer.welcome.deliver Rendered user_mailer/welcome.text.erb (1.8ms) Open http://localhost:1080 in another tab --- # Mail Catcher You should see something like this: ![Mail Catcher](img/mailcatcher.png) --- # Rails 4.1 Mailer Previews Rails 4.1 has a new feature that allows you to preview emails without having to use Mailcatcher. Go to this URL: [http://localhost:3000/rails/mailers](http://localhost:3000/rails/mailers) You will be able to click though the links to see your welcome email. --- # Adding Links To Emails When you generate links in emails, they need to be a full URL including the domain name of your site, not just a relative link. In order to do that, Rails needs to know what domain name to use. In `config/environments/development.rb`, use this setting: ```ruby config.action_mailer.default_url_options = { host: "localhost", port: 3000 } ``` In `config/environments/production.rb`, it will look something like this: ```ruby config.action_mailer.default_url_options = { host: "serene-thicket-5859.herokuapp.com" } ``` Now in the email ERB templates, use the same code, but be sure to use the `_url` version of the route methods instead of `_path`, like this: ```rhtml <%= link_to "Log In", admin_login_url %> ``` --- # Using Parameters In Email Right now our mailer has a hard-coded to address, an incorrect from address and no dynamic content, so let's fix all that. First, modify the mailer to use a from address that matches you app, like this: ```ruby default from: "support@serene-thicket-5859.herokuapp.com" ``` In a real app, you should switch this to your real domain name. Next, change the `welcome` mailer method to look like this: ```ruby def welcome(user) @name = user.email.split('@').first mail to: user.email end ``` The method now takes an argument, which will be an active record user object. We use that object to first set an instance variable that we will later use in the view. Then we change the `to` to be the email address of the user. Change the view to use that instance variable: ```rhtml
Welcome, <%= @name %>
``` If you try to preview this mailer now, you will get an error, because we need to modify the preview, so let's do that next. --- # Mailer Previews When we generated the mailer, a file `test/mailers/previews/user_mailer_preview.rb` was generated to allow us to preview the mailer. When the mailer accepts no arguments, it works fine, but if you need to pass arguments to the mailer, as we do with the user record, then modify the preview code to do that. Modify the `welcome` method to look like this: ```ruby def welcome UserMailer.welcome(User.last) end ``` Now if you preview that mailer, it should work. --- # Deployment In production, we will need a provider to handle mail delivery. A good one to use is Mailgun. Add it to your app like this: .terminal $ heroku addons:add mailgun Adding mailgun on serene-thicket-5859... done, v12 (free) Then update `config/environments/production.rb` with the following configuration: ```ruby config.action_mailer.smtp_settings = { port: ENV['MAILGUN_SMTP_PORT'], address: ENV['MAILGUN_SMTP_SERVER'], user_name: ENV['MAILGUN_SMTP_LOGIN'], password: ENV['MAILGUN_SMTP_PASSWORD'], domain: 'serene-thicket-5859.herokuapp.com', authentication: :plain, } config.action_mailer.delivery_method = :smtp ``` Commit the changes and push them to Heroku as normal with `git push heroku master`. Once you have, to test that it working, run `heroku run rails c` to get a rails console at Heroku, then run this code to send an email to yourself: ```ruby UserMailer.welcome(User.first).deliver ``` This assumes that the first user in your database at Heroku has an email address that matches yours. If it does not, either change it or create a user that does have your email address and use that. --- # In-Class Assignments 1. Create User Mailer, get it working locally first and then deploy it to Heroku 2. Create a sign up form that allows anyone who visits your site to create a customer. 3. When someone signs up and creates a customer, make it so there is a timestamp column called `verified_at` that is initially null. When a customer is created, send them a welcome email with a link in it to verify that they own that email address. When they click the link, have it set the value for `verified_at` to the current time, unless it is already set. Hint: Use the [new Rails 4.1 Application Message Verifier](http://api.rubyonrails.org/classes/Rails/Application.html#method-i-message_verifier) to secure the link by using `generate` to put the customer id in the URL that they click on and then using `verify` to get the value back out in the action that the URL goes to