Ruby
net/http from the standard library, and where the key lives.
There is no emails.sh gem to install. net/http is in the standard library and the API is one POST, so this file is the entire integration.
Send
# lib/emails.rb
require 'net/http'
require 'json'
require 'uri'
# The key comes from https://emails.sh/dashboard/api-keys. Keep it in
# ENV['EMAILSSH_API_KEY'], loaded from .env or from Rails credentials.
module Emailssh
ENDPOINT = URI('https://emails.sh/v1/emails').freeze
class Refused < StandardError
attr_reader :code
def initialize(code, message)
@code = code
super("#{code}: #{message}")
end
end
def self.send_email(to:, subject:, html:, from: 'Acme <hello@acme.com>')
request = Net::HTTP::Post.new(ENDPOINT)
request['Authorization'] = "Bearer #{ENV.fetch('EMAILSSH_API_KEY')}"
request['Content-Type'] = 'application/json'
request.body = JSON.generate(from: from, to: [to], subject: subject, html: html)
response = Net::HTTP.start(ENDPOINT.host, ENDPOINT.port, use_ssl: true, read_timeout: 10) do |http|
http.request(request)
end
body = JSON.parse(response.body)
unless response.is_a?(Net::HTTPSuccess)
refusal = body['error']
raise Refused.new(refusal['code'], "#{refusal['message']} #{refusal['next']}")
end
body['id']
end
endrequire_relative 'lib/emails'
begin
id = Emailssh.send_email(
to: 'ada@example.com',
subject: 'Your receipt from Acme',
html: '<p>Thanks for your order.</p>'
)
puts "queued #{id}"
rescue Emailssh::Refused => e
# e.message carries the sentence saying what to do next.
warn e.message
endWith Faraday
gem install faradayrequire 'faraday'
require 'json'
conn = Faraday.new(url: 'https://emails.sh') do |f|
f.request :json
f.response :json
f.options.timeout = 10
end
response = conn.post('/v1/emails') do |req|
req.headers['Authorization'] = "Bearer #{ENV.fetch('EMAILSSH_API_KEY')}"
req.body = {
from: 'Acme <hello@acme.com>',
to: ['ada@example.com'],
subject: 'Your receipt from Acme',
html: '<p>Thanks for your order.</p>'
}
end
if response.success?
puts "queued #{response.body['id']}"
else
refusal = response.body['error']
warn "#{refusal['code']}: #{refusal['message']} #{refusal['next']}"
end