Getting the Action Mailer to Actually Mail (with Mailgun)
3.3.2017
I've been on a saga for the last couple of weeks (okay, maybe that's too short for a true saga) trying to get a rails app to send email.
"But Jonathan, that's so simple, you just use the Action Mailer!"
You're right, condescending person. The action mailer is not actually too difficult to set up. This post is great when it comes to explaining that. But that sends your email to exactly no one. And I've found that for a newer programmer such as myself, there has been an enormous amount of trial and error when it comes to actually getting a production app to send real live emails. So here's my guide for those struggling with this same issue.
In the course material for my school, it recommended testing out your mailer with the letter opener gem. And this works great. It's a good way to make sure that it's not the ActionMailer that's broken (though you should write a spec too!) when something goes wrong. So I'd get that working first. But again, your emails are not actually going to anyone.
What you need is an SMTP server. A go-between service for your app and the people you're mailing too. Since I push most of my apps to Heroku, Mailgun (which is a plugin for Heroku) is the option I'm going to go over. To get this hooked up, first include the following in your config/environments/production.rb file:
ActionMailer::Base.smtp_settings = {
:port => ENV['MAILGUN_SMTP_PORT'],
:address => ENV['MAILGUN_SMTP_SERVER'],
:user_name => ENV['MAILGUN_SMTP_LOGIN'],
:password => ENV['MAILGUN_SMTP_PASSWORD'],
:domain => 'yourapp.heroku.com',
:authentication => :plain,
}
ActionMailer::Base.delivery_method = :smtp
Push your app to Heroku, and then, from the Resources console on your Heroku app, add the Mailgun add-on. THIS WILL CONFIGURE YOUR ENVIRONMENT VARIABLES FOR YOU. Don't be like me and try to enter them through the command line, and mess one of them up. If you go to Settings > Config Vars on your Heroku console, you should see them there.
Okay, so now you should be hooked up to Mailgun (though I make no promises). However, if you try to send an email, nothing will happen. In fact, if you go to the logs, you'll see that the ActionMailer believes it sent the email! But it definitely won't arrive. The reason is that you are still in sandbox mode on Mailgun. In sandbox mode, you can only send emails to verified accounts, and only 5 of them. To test this out, go to the Mailgun console (through your Heroku app), go to domains and click on the only one that should be present, and then scroll down to see the big line that says "You haven't added any authorized recipients yet." Add one and test it out.
It's all well and good if this works, but how in the hell do you get out of sandbox mode? Do you pay Mailgun? Well, you could, and if your app gets a huge mailing list you might have to to pay for more emails, but that's not what gets you out of sandbox mode. What you need to do is hook up a custom domain name from which the emails can be sent from.
Head to one of the main domain purchasing sites and get one. I used NameCheap, really for no particular reason, but that's who I know and have now. Many domains are only 88 cents a year, but they aren't exactly prime real estate. Once you've bought one, you need to change your domain's DNS settings to connect your custom domain to your app.
First, go into the Mailgun console for your Heroku app and add your custom domain. On your domain's page in Mailgun, copy your IP address, then scroll down and open up the Domain Verification and DNS Records section. Copy the corresponding VALUES for the following records: TXT TXT (the second one) CNAME
Then, on Namecheap, do this: Sign in to your account. On your account home page, click the "Manage" button by your domain. Click "Advanced DNS." Then, fill in the following records with the following information:
Type - Host - Value A Record - @ - IP Address copied above CNAME Record - email - mailgun.org TXT Record - @ - TXT value copied above TXT Record - krs._domainkey - TXT (second one) value copied above
If this works, you should be able to go back to your Mailgun console, check your DNS settings, and see that you're connected. At this point, you'll also want to change the config settings for your Heroku app (I prefer to do this through the online Heroku console) to reflect the new domain - this part is NOT automatic. It will still try to connect to your old domain otherwise.
AND THEN YOU CAN SEND EMAILS FROM YOUR APP.
Perhaps there's an easier way to do all this, but this is the process worked for me. It's very finicky, so you may have to veer off from my instructions at some point along the way, but I hope they can at least be a useful starting point. And I hope I didn't forget anything! I suppose I'll find out the next time I try to implement a RLM (Real Life Mailer).
Other Posts
The Best Projects Can Be Done in a Weekend
Everyone Has Something To Offer
Book Thoughts: Capital and Ideology
Naive Diffie-Hellman Implementation in Ruby
When Does the Magic Comment Work, and When Does it Not?
Benchmarking Arrays Full of Nils
Go, and When It's Okay to Learn New Things
Grouping Records by Month with Ruby
Add Timestamps to Existing Tables in Rails
The Busy and (Somewhat) Fit Developer
TuxedoCSS and the Rails Asset Pipeline
Gem You Should Know About: auto_html