How to use the SendGrid API with Ruby

RapidAPI Team
The Era of APIs
Published in
8 min readNov 26, 2019

Email is a technology that has been part of everyday life for more than 50 years. It’s still one of the most important methods of communication, even in the era of smartphones and apps. It provides an extremely reliable and secure way of messaging, from notifications to password resets. In some countries, email (or some form thereof) is even used as a way of communication from public authorities, having rendered mail obsolete years ago.

With this in mind, most web applications rely on email one way or another. If you own a web store, for example, you’re more likely than not already sending emails to your customers with order confirmations. This is more or less expected from such a service, as it gives customers peace of mind and a “paper” trail of their orders. But sending email reliably is a whole other topic. Due to its increase in popularity, most big email providers are very aggressive when it comes to receiving email, and will easily classify email from unknown sources as SPAM. This is when reputable email sending services come into play.

Connect to the SendGrid API

What is SendGrid?

Instead of spending time and money on setting up your own email server, your time is best spent integrating into a known and reputable email provider. SendGrid has been around for about 10 years, making them one of the kings in the industry of email communications. See, building an email server is a tricky business, where you have to build a reputation and maintain it, to avoid getting flagged by the email giants like Gmail. They have invested the research and time needed to build a powerful service, so you don’t have to.

Of course, SendGrid has also spent a considerable amount of time building its APIs, to allow developers like you to easily integrate your apps into their robust infrastructure. They officially provide their API via RapidAPI, which makes integration and billing a whole lot easier.

What we will build

You have a customer who needs you to build an API for them. The usage is as follows: they have an app where users can see real estate listings. While swiping through the listings, they can select the ones they like and when they do, they enter their email to receive the listing’s details. The details are stored in the API you will build, in the form of a PDF file. Your API needs to be able to receive a request with the email and the listing ID, and then send the user an email with the realtor’s contact information and the corresponding PDF file as an attachment.

Requirements

Setup our project

You will need:

  • Ruby
  • Padrino
  • A RapidAPI Account

The simplest way to install Ruby is to go to the official installation instructions. Here you’ll find directions to install Ruby depending on your platform. There’s also a comparison of Ruby web frameworks here, where you can get an overview of which framework might be best suited for your project. For this project, we’ll use Padrino.

To get your RapidAPI account, just head on to rapidapi.com to sign up. Even though SendGrid’s API has a free usage tier, you’ll need a credit card. Don’t worry though, as you’ll only be charged if you go over the free usage of the plan (which is 100 emails per day, and should be enough for this tutorial).

Connect to the SendGrid API

Setup SendGrid in RapidAPI

Go SendGrid’s profile in RapidAPI. Here you’ll see a list of endpoints supported by SendGrid. Before you can use any of them, you need to subscribe to one of their plans. Like we mentioned before, they offer a free plan, which includes more than enough emails per day to be able to play around and test our code. Go ahead and subscribe to that plan:

After that, click on “Endpoints” at the top of the page. At the bottom, you will see two important strings: X-RapidAPI-Host and X-RapidAPI-Key. You'll need both for the next section.

A quick example

Let’s start with a quick snippet on how to send an email using Ruby. First, you’ll have to install a library called excon, which is a powerful yet simple networking library. This is needed as we'll be making HTTP requests to SendGrid to send emails. Run this in your terminal:

gem install excon

After that, hop on to the interactive ruby shell, so we can play around with the API. Run irb in your terminal, then require some dependencies:

require 'excon' require 'json'

We’ll need the JSON gem to convert Ruby structures into JSON, which is what SendGrid expects. Now, if you take a look at the sample payload for the “Send” endpoint, you’ll notice it’s quite simple:

{
"personalizations": [
{
"to": [
{
"email": "john@example.com"
}
],
"subject": "Hello, World!"
}
],
"from": {
"email": "from_address@example.com"
},
"content": [
{
"type": "text/plain",
"value": "Hello, World!"
}
]
}

Most of this you’ll recognize. There’s a “to”, a “from” and “content”. This is the most basic payload you can send to SendGrid to send an email. You can take a look at their documentation to see what other parameters you can send to customize each email. For example, you can add attachments to emails. To keep this example short, let’s just customize the options a bit to our liking. Type this in your IRB session:

payload = {}
receiver = { email: 'my@email.org', name: 'John SendGrid Doe' }
subject = 'Hello from RapidAPI!'
from = { email: 'tutorial@rapidapi.com', name: 'RapidAPI Tutorial' }
payload[:personalizations] = []
payload[:personalizations] << { subject: subject, to: [ receiver ] }
payload[:from] = frompayload[:content] = []
payload[:content] << { type: 'text/plain', value: 'Hello from RapidAPI! This is just a test from the console' }

Remember to substitute the recipient’s email with either your own or some temporary email for testing purposes. This is just creating a similar structure as the JSON we showed before. We’re sending an email to John Doe, adding a subject and a body. Now, let’s send it:

headers = {}
headers['X-RapidAPI-Host'] = 'YOUR HOST'
headers['X-RapidAPI-Key'] = 'YOUR API KEY'
headers['Content-Type'] = 'application/json'
Excon.post('https://rapidprod-sendgrid-v1.p.rapidapi.com/mail/send', headers: headers, body: payload.to_json)

Notice we’re setting the headers to the values we asked you to take note of previously, plus a header specifying that the content we send is JSON. Without this last header, you’ll just get an error back. You should now see an email in your inbox!

Build the API

Now that we have a grasp on how the API works, let’s build what our client asked. We’ll build this with Padrino. First, create a directory for our project:

mkdir sendgrid-api

And add a Gemfile:

# Gemfile
source "https://rubygems.org"
gem "sinatra"
gem "excon"

Run bundle install in your console to install the dependencies. Let's also create a folder for our attachments:

mkdir attachments

Fill this folder with some dummy PDF files. You can use this one. We created three different files so we have some to play with:

Create the endpoint

Let’s now create our main file. Name it app.rb and add this to it:

# app.rb
require 'sinatra'
require 'excon'
require 'json'
require 'base64'
Get the full snippet at https://rapidapi.com/blog/sendgrid-api-ruby/

First, we import all the necessary gems. We’ll need sinatra and excon, but we'll also need json and base64. The last one is required to be able to convert our attachments to Base 64 encoding, as is required by SendGrid. We then set up our endpoint as a POST endpoint, call it request_listing, and get the parameters from the request.

Next, we read the attachment from the attachments folder, and if we can’t find it we’ll just stop with a status of 404. The next big thing is to build the payload. This is pretty straightforward and there’s nothing too different from what we already saw in the previous steps. What’s new is the next highlighted section. To add an attachment, we need to encode it to Base 64 encoding. In few words, this means converting the binary contents of the PDF attachment to a string, so SendGrid can easily send it over. We’ll also set a file name and specify the type of file.

# Lines 40-46 payload[:attachments] = [ { # Encode the file content: Base64.strict_encode64(attachment), # Set a filename for the attachment filename: "#{listing_id}.pdf", # Specify the content of the file type: 'application/pdf' } ]

Lastly, we’ll send the payload to SendGrid like we did previously.

Giving our API a test

Go to your terminal and run bundle exec ruby app.rb. This will start your server, and you should see something like this in your terminal:

[2019-11-24 23:16:49] INFO WEBrick 1.3.1 [2019-11-24 23:16:49] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin18] == Sinatra (v2.0.7) has taken the stage on 4567 for development with backup from WEBrick [2019-11-24 23:16:49] INFO WEBrick::HTTPServer#start: pid=64410 port=4567

This means your server is now running on port 4567. To test it, we’ll just use cURL. In another terminal, let’s try this:

curl -d '[email protected]&listing_id=unknown_property' http://localhost:4567/request_listing

Notice unknown_property as our listing ID. We're trying to test that our server actually says a listing can't be found when the ID is wrong. You should see Listing not found in your terminal. Now, let's try a listing that does exist:

curl -d '[email protected]&listing_id=property_1' http://localhost:4567/request_listing

Your terminal should now say nothing, but your inbox should have a new email with an attachment: one of the dummy PDFs.

Conclusions

Congratulations! You’ve just managed to programmatically send email with attachments using SendGrid. Their APIs give you a lot more control over your email needs than what we showed here. You should definitely take a look at Suppression Groups if you’re planning on sending non-transactional emails. This feature lets you create a sort of category (which you specify using the asm.group_id parameter when sending email) so that users can unsubscribe. This is particularly important because you want to avoid getting marked as SPAM by your users, which affects your email reputation.

Related Reading

Originally published at https://rapidapi.com on November 26, 2019.

--

--