blastengineを使ってRubyでメールを送信する

[blastengine](https://blastengine.jp/)はシンプルに使える開発者向けメールサービスを提供しています。何かと面倒なメール配信をシンプルに、かつ確実に送信先に届くようになります。

今回はblastengineを使ってRubyでメール送信を行うまでの流れを解説します。

## ユーザ登録する

blastengineにユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

![getting-started-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/f9e553b4-6322-4219-db91-a28f2a88e280.jpeg)


## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

## API経由で配信する

まずはAPIを使ってHTMLメールを配信する流れを紹介します。

### APIキーを取得する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2845ae27-6504-acce-eddd-5bef49b1de56.jpeg)


そして設定の中で、APIキーを取得します。

![getting-started-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/9cb1e6eb-79f9-000d-fc82-11aef3532066.png)


### ライブラリのインストール

今回はHTTPアクセス用に[http.rb](https://github.com/httprb/http)を利用します。HTTPartyやRestClientも有名ですが、それらと比べると軽量なライブラリとなっています。

```
$ gem install http
```

### ライブラリの読み込み

ではここからコードを書いていきます。まず必要なライブラリを読み込みます。

```rb
# 必要なライブラリの読み込み
require 'http'
require 'digest/sha2'
require 'base64'
```

### 必要な変数を取得

今回はターミナル（コマンドプロンプト）から実行します。その際にユーザIDとAPIキーを渡す仕組みにしますので、スクリプト側で入力値を受け取ります。また、両方とも必須なので、入力がなかったらエラーとします。

```rb
# ユーザIDとAPIキーを取得
user_id = ENV['BE_USERID'];
api_key = ENV['BE_APIKEY'];
if !user_id
	puts 'ユーザIDは必須です';
	exit;
end
if !api_key
	puts 'APIキーは必須です';
	exit;
end
```

### トークンを生成する

APIリクエストするためのトークンを生成します。手順としては次のとおりです。

1. ユーザIDとAPIキーを連結する
2. SHA256のハッシュを生成する
3. ハッシュを全て小文字にする
4. 3の文字列をBASE64エンコードする

実際のコードで言うと、次のようになります。 `token` がトークンです。

```rb
# トークンの作成
str = "#{user_id}#{api_key}";
token = Base64.urlsafe_encode64 Digest::SHA256.hexdigest(str).downcase
```

### APIリクエストする

では実際にメールを送信します。APIのエンドポイントは `https://app.engn.jp/api/v1/deliveries/transaction` になります。生成したトークンは `Authorization` ヘッダーに適用します。fromのemailやtoなど、メールアドレスは利用されるものに書き換えてください。

```rb
# APIエンドポイント
url = 'https://app.engn.jp/api/v1/deliveries/transaction'

# 送信するデータを作成
data = {
	from: {
		email: 'sample@example.jp',
		name: '送信者サンプル'
	},
	to: 'to@example.com',
	subject: 'テスト件名',
	encode: 'ISO-2022-JP',
	text_part: 'テスト配信',
	html_part: '<!DOCTYPE html><html><header></header><body>sample html</body></html>'
}

# ヘッダー
header = {
	'Content-Type': 'application/json',
	'Authorization': "Bearer #{token}"
}

# HTTPクライアントの作成
http = HTTP
  .headers(header)
  .accept(:json)
# API実行
res = http.post(url, json: data)
```

### 結果

レスポンスを出力します。配信ID（delivery_id）は照会、変更および削除操作に必要です。

```rb
puts res.body
# { delivery_id: 9 }
```

### 実行する

では実際にターミナル、またはコマンドプロンプトから実行してみます。 `YOUR_USER_ID` と `YOUR_API_KEY` はそれぞれ皆さんのものに置き換えてください。

```
$ BE_USERID=YOUR_USER_ID BE_APIKEY=YOUR_API_KEY ruby api.rb
{ delivery_id: 9 }
```

### 全体のコード

今回のサンプルコードは次のようになります。実装時の参考にしてください。

```rb
# 必要なライブラリの読み込み
require 'http'
require 'digest/sha2'
require 'base64'

# ユーザIDとAPIキーを取得
user_id = ENV['BE_USERID'];
api_key = ENV['BE_APIKEY'];
if !user_id
	puts 'ユーザIDは必須です';
	exit;
end
if !api_key
	puts 'APIキーは必須です';
	exit;
end

# トークンの作成
str = "#{user_id}#{api_key}";
token = Base64.urlsafe_encode64 Digest::SHA256.hexdigest(str).downcase

# APIエンドポイント
url = 'https://app.engn.jp/api/v1/deliveries/transaction'

# 送信するデータを作成
data = {
	from: {
		email: 'sample@example.jp',
		name: '送信者サンプル'
	},
	to: 'to@example.com',
	subject: 'テスト件名',
	encode: 'ISO-2022-JP',
	text_part: 'テスト配信',
	html_part: '<!DOCTYPE html><html><header></header><body>sample html</body></html>'
}

# ヘッダー
header = {
	'Content-Type': 'application/json',
	'Authorization': "Bearer #{token}"
}

# HTTPクライアントの作成
http = HTTP
  .headers(header)
  .accept(:json)
# API実行
res = http.post(url, json: data)
# レスポンス
puts res.body
```

## SMTPリレーでの配信

次にSMTPリレーを使った方式です。

### IPアドレスの登録

SMTPリレーを利用する場合、まず接続元サーバのIPアドレスを管理画面で登録する必要があります。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/9d86ed74-9790-2769-a0f5-2687d4d0954b.jpeg)


IPアドレスの設定ダイアログで、接続元サーバのIPアドレスを入力してください。

![getting-started-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ffa55126-de9c-f98a-3f35-6c15a9796b87.jpeg)


### ライブラリのインストール

今回はRubyで最も標準的と思われる mail を利用します。

```
gem install mail
```

### ライブラリの読み込み

ではここからコードを記述していきます。まず必要なライブラリを読み込みます。

```rb
require 'mail'
```

### SMTPサーバの指定

次にSMTPサーバを指定します。blastengineのSMTPサーバアドレスは `smtp.engn.jp` 固定になります。ポート番号は25/587/2525より選択してください。

```rb
Mail.defaults do
  delivery_method :smtp, address: 'smtp.engn.jp', port: 587
end
```

### メール配信する

後はメールオブジェクトを作り、deliverメソッドで送信を実行します。

```rb
mail = Mail.new do
  from   'from@example.jp'
  to       'to@example.com'
  subject  'HTMLメール'
	text_part do
		content_type 'text/plain; charset=UTF-8'
  	body     'これはHTMLメールです'
	end
	html_part do
		content_type 'text/html; charset=UTF-8'
		body '<html><body><h1>これはHTMLメールです</h1></body></html>'
	end
end

# 送信
mail.deliver
```

### 全体のコード

全体のコードは次のようになります。実装時の参考にしてください。

```rb
require 'mail'

Mail.defaults do
  delivery_method :smtp, address: 'smtp.engn.jp', port: 587
end

mail = Mail.new do
  from   'from@example.jp'
  to       'to@example.com'
  subject  'HTMLメール'
	text_part do
		content_type 'text/plain; charset=UTF-8'
  	body     'これはHTMLメールです'
	end
	html_part do
		content_type 'text/html; charset=UTF-8'
		body '<html><body><h1>これはHTMLメールです</h1></body></html>'
	end
end

# 送信
mail.deliver
```

### 送信後のメールオブジェクト

メールを送信した後のmailを出力すると、次のような内容が確認できます。これはメールのソースと一致するものになります。

```
Date: Tue, 14 Dec 2021 14:19:02 +0900
From: from@example.com
To: to@example.com
Message-ID: <61b829468797d_17ab73fe287032010618fd@localpc.local.mail>
Subject: =?UTF-8?Q?HTML=E3=83=A1=E3=83=BC=E3=83=AB?=
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_61b8294662856_17ab73fe2870320106171e";
 charset=UTF-8
Content-Transfer-Encoding: 7bit


----==_mimepart_61b8294662856_17ab73fe2870320106171e
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: base64

44GT44KM44GvSFRNTOODoeODvOODq+OBp+OBmQ==

----==_mimepart_61b8294662856_17ab73fe2870320106171e
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: base64

PGh0bWw+PGJvZHk+PGgxPuOBk+OCjOOBr0hUTUzjg6Hjg7zjg6vjgafjgZk8
L2gxPjwvYm9keT48L2h0bWw+

----==_mimepart_61b8294662856_17ab73fe2870320106171e--
```

## まとめ

クラウドサービスではSMTPポートが塞がれている場合があるので、そうした時にはAPI経由を利用してください。SMTPリレーを使えば、より信頼性高く、安定した配信が実現できるでしょう。

APIとSMTPリレー、それぞれの要件に合わせて最適な方を選択してください。

[エンジニア向けメール配信システム「ブラストエンジン」](https://blastengine.jp/)