SendGrid+Ruby+JIS(ISO-2022-JP)でメールを送信する

クラウドメールサービス[SendGrid](https://sendgrid.kke.co.jp)を使ってRubyからメールを送ってみます。
SendGridを使ってメールを送る方法はいくつかあります。詳しくは[公式ブログ](https://sendgrid.kke.co.jp/blog/?p=1300)を参照してください。

- SMTP
- Web API
- マーケティングメール機能

今回はSMTPとX-SMTPAPIを組み合わせて宛先毎に内容の異なるメールを送ってみます。

# SMTP
SMTPはWeb APIに比べて細かいメール送信パラメータを指定できるのがメリットですが、それが面倒な場合、デメリットにもなります。でも、UTF-8以外のエンコードを指定してメールを送りたい、といった場合はSMTPが必須になります。今回は歴史的な経緯上よく使われるJIS(ISO-2022-JP)でメールを送ります。

# X-SMTPAPI
名前がSMTPっぽくて紛らわしいですが、[X-SMTPAPI](https://sendgrid.kke.co.jp/blog/?p=1300)はSendGrid独自の拡張ヘッダです。これを利用するとメール送信時にSendGridの様々な機能を使うことができます。今回は、To、Substitution、Sectionを利用してメールの件名や本文内の特定のキー文字列を宛先毎に異なる値に置換してメールを送ってみます。

# とりあえず送ってみる
以下の手順で[サンプルコード](https://github.com/SendGridJP/sendgrid-smtp-ruby-example)をクローン、.envファイル編集、実行してください。
Rubyは2.1.0で動作確認しています。

```text
git clone https://github.com/SendGridJP/sendgrid-smtp-ruby-example.git
cd sendgrid-smtp-ruby-example
cp .env.example .env
# .envファイルを編集してください
bundle install
ruby -f sendgrid-smtp-jis.rb
```

### .envファイルの編集
```text
SENDGRID_USERNAME=SendGridユーザ名
SENDGRID_PASSWORD=SendGridパスワード
TOS=you@youremail.com,friend1@friendemail.com,friend2@friendemail.com
FROM=you@youremail.com
```
SENDGRID_USERNAME:SendGridのユーザ名を指定してください。
SENDGRID_PASSWORD:SendGridのパスワードを指定してください。
TOS:宛先をカンマ区切りで指定してください。
FROM:送信元アドレスを指定してください。

指定したアドレスにメールは届きましたか？

# コード

```rb
# -*- encoding: utf-8 -*-
require 'mail'
require 'dotenv'
require 'smtpapi'
require 'nkf'
require 'mail-iso-2022-jp'

Dotenv.load
sendgrid_username = ENV["SENDGRID_USERNAME"]
sendgrid_password = ENV["SENDGRID_PASSWORD"]
from = ENV["FROM"]
tos = ENV["TOS"].split(',')

# smtpapi
smtpapi = Smtpapi::Header.new
smtpapi.set_tos(tos)
smtpapi.add_substitution("fullname", ["田中 太郎", "佐藤 次郎", "鈴木 三郎"])
smtpapi.add_substitution("familyname", ["田中", "佐藤", "鈴木"])
smtpapi.add_substitution("place", ["office", "home", "office"])
smtpapi.add_section('office', '中野')
smtpapi.add_section('home', '目黒')
smtpapi.add_category('category1')

mail = Mail.new(:charset => "ISO-2022-JP") do
  from from
  to tos
  subject "[sendgrid-smtp-ruby-example] フクロウのお名前はfullnameさん"
  add_file "./gif.gif"
end
mail["x-smtpapi"] = smtpapi.to_json

text_plain = Mail::Part.new do
  body (NKF.nkf('-j', "familyname さんは何をしていますか？\r\n 彼はplaceにいます。"))
  content_type "text/plain; charset=ISO-2022-JP"
end
text_html = Mail::Part.new do
  body (NKF.nkf('-j', "<strong> familyname さんは何をしていますか？</strong><br />彼はplaceにいます。"))
  content_type "text/html; charset=ISO-2022-JP"
end
mail.part :content_type => "multipart/alternative" do |p|
  p.html_part = text_plain
  p.text_part = text_html
end

mail.delivery_method(:smtp,
  address: "smtp.sendgrid.net",
  port: 587,
  domain: "gmail.com",
  authentication: :login,
  user_name: sendgrid_username,
  password: sendgrid_password
)
mail.deliver
```

mailと[mail-iso-2022-jp](https://github.com/kuroda/mail-iso-2022-jp)を使ってISO-2022-JPを使ったマルチパートメールを送っています。
[smtpapi](https://github.com/SendGridJP/smtpapi-ruby)のset_tosを使って.envファイルから読み込んだ宛先アドレスの配列を設定しています。
add_substitutionを使ってメールの件名と本文内のキー文字列（fullname, familynameなど）と宛先毎の置換後の文字列を設定しています。
add_sectionはadd_substitutionで指定した値内のキー（office, homeなど）をさらに置換する文字列を指定しています。これらを組み合わせてかなり複雑な置換が行えると思います。

```rb
mail["x-smtpapi"] = smtpapi.to_json
```
として拡張ヘッダの値としてJSON文字列を指定して利用します。