Rails and Emails

Having just installed our Rails server on Heroku, we were looking for a way to send out emails to confirm email addresses. The line of least resistance seemed to be Gmail; everyone loves Gmail and there were quite a few articles on the subject. So we set it up and it worked… for a while.

It seems that Google have increased the security of the mail system and the option to use less secure apps no longer allows our Rails server to send emails. Instead Gmail warns that an unknown device in Virginia (i.e. a Heroku server) is trying to send email using the account and has been blocked. Even saying that the device belongs to me (which it does… kind of) didn’t improve matters. A different approach was required.

Rails had been configured to use SMTP to send email via Gmail so it made sense to adopt another email service that supported the same approach. Mailgun is offered by Heroku and seemed to fit the bill.

As soon as it’s installed using Heroku, a bunch of Mailgun environment variables are setup and a “Sandbox” email domain is created to get you up and running. The Gmail configuration  was replaced by this:

config.action_mailer.smtp_settings = {
 :address => ENV['MAILGUN_SMTP_SERVER'],
 :user_name => ENV['MAILGUN_SMTP_LOGIN'],
 :domain => 'yourdomain.heroku,com',
 :authentication => :plain

To get this to work you have to specify authorised recipients (i.e. email addresses) via the Mailgun console (which is accessed via the Heroku Overview page). Up to five authorised recipients are allowed which is enough to demonstrate that everything is setup okay but nothing more. To get it working fully, you have to have your own domain.

Mailgun suggest that you set up a subdomain for sending emails but you can use Mailgun to forward incoming emails to mailboxes of your choice (Mailgun does not offer IMAP or POP3 access) as well as to send outgoing emails so it may be easier for you to use the top-level domain. It certainly looks that way to me.

Once you have entered your email domain in the Mailgun console you can see the settings it needs to be entered on your DNS server. Once the DNS settings have propagated, you  take the username and password that Mailgun has created for your new email domain and update the environment variables MAILGUN_SMTP_LOGIN and MAILGUN_SMTP_PASSWORD. Then everything should work.

Having done this, I’m not sure why I contemplated using Gmail in the first place. You live and learn.

Rails, Devise and APIs

As a newcomer to Rails and having done a fair amount of background reading, it seemed to make sense that I use Devise to secure access to the API that I was creating. However, in the end I gave up, I could not get the authentication to work reliably and I could not stop Devise from sending HTML out in response to a JSON request. I know that better men than I would have fixed the problem but, as I dug into the issues, I got the feeling that I was going to spend more time removing functionality than I would spend writing what I needed from scratch.

Devise does a lot but, to my mind, a lightweight API doesn’t need much. However, there isn’t much out there to tell you what you need to do. While I was digging around, I came across APIs on Rails which gave me the confidence to remove Devise and start again. I started to work through the examples in the book and had problems with a few of them but there is a Github repository where the issues are discussed and solutions posted. It was not the simplest of processes but it was much more transparent than using Devise.

When it came to Chapter 5, entitled “Authenticating Users” I opted to use Json Web Tokens (JWTs) because they can carry information in much the same manner as a cookie which would, I believed, simplify the implementation server-side. Support for JWTs was added to the project via a Ruby Gem which proved to be well documented and easy to use.

In simple terms the approach is this:

  1. When a client starts a session on the server, they provide their credentials and, in return, are provided a JWT which contains information to identify the client.
  2. The client includes the JWT in the authorization header of every HTTP request sent to the server.
  3. The server opens the JWT, checks the content and allows the request to proceed if everything checks out. If it doesn’t check out, an unauthorised (401) error is returned immediately.

Much simpler than struggling with Devise! Once I got my head around it, it was easy enough to implement. If you are interested, you can take a look at the code on Github.

Rails and Devise are very powerful but so much happens under the hood that they are a minefield for new users who are trying to do something a little out of the ordinary.