Ruby on Rails + Action Mailerで非同期メール送信機能の実装


##はじめに
* Gmailを使用してメールの送信
* Active Jobで非同期メール送信
* キューイングバックエンドはDelayed Jobを使用
* 最後にCapistranoでデプロイ

※Active JobはRails 4.2からの導入なので注意

<br>
## Action Mailerの設定
Gmailで送信するための設定を行う

```config/environments/development.rb
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.smtp_settings = {
    :address => 'smtp.gmail.com',
    :port => '587',
    :domain => 'smtp.gmail.com',
    :authentication => 'plain',
    :user_name => ENV['MAILADDRESS'],
    :password => ENV['MAILPASS'],
    :enable_starttls_auto => true,
  }
```

ポイント
* メール送信失敗時にエラーを出力
`config.action_mailer.raise_delivery_errors=true`
* Gmail側の設定で安全性の低いアプリがアカウントにアクセスするのを許可する必要がある
* https://support.google.com/accounts/answer/6010255

<br>
## メール送信ロジックの作成

メーラーをジェネレーターで作成 (仮にcontact_mailerを生成)

```
rails g mailer ContactMailer
```

メール送信メソッドを編集

```app/mailers/contact_mailer.rb
class ContactMailer < ApplicationMailer
  # 指定したGmailアドレスを指定
  default from: ENV['MAILADDRESS']

  def sendmail_notice(hoge)
    @hoge = hoge

    # mailの送信先を指定
    mail to: "hogehoge@gmail.com"
  end
end
```

メール本文を編集

```views/contact_mailer/sendmail_notice.text.slim
= "Name: " + @hoge + "\n\r"
```

コンソールでメール送信テスト

```
$ bin/rails c
Loading development environment (Rails 4.2.1)

Frame number: 0/5
[1] pry(main)> hoge = 'hogehoge'
=> "hogehoge"
[2] pry(main)> ContactMailer.sendmail_notice(hoge).deliver_now

```

これでメールの受信が確認できればOK
<br>
##キューイングバックエンドの用意 (Delayed Job)
Active Jobを使用するためのキューイングバックエンドを用意
Active Jobは他にも色々なキューイングバックエンドに接続できるできるので任意で取り替えることが可能

利用可能な最新のアダプタのリストについては、APIドキュメントを参照
http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html


必要なGemのインストール

```Gemfile
  gem 'delayed_job_active_record'
  gem "daemons"

```

Delayed Jobのキュー保存用のテーブルを作成

```
bin/rails generate delayed_job:active_record
bin/rake db:migrate
```

Jobの起動

```
bin/delayed_job start
```

Jobのプロセスを確認

```
$ ps aux | grep delayed_job
16646   0.0  1.4  3221660 118192   ??  S     6:33PM   0:41.04 delayed_job
24485   0.0  0.0  2451204    696 s001  S+   11:24PM   0:00.00 grep -E --color=auto delayed_job
```
## Active Jobの設定

Adapterの設定に先ほどインストールしたDelayed Jobを設定

```config/application.rb
module ProjectName
  class Application < Rails::Application
    config.active_job.queue_adapter = :delayed_job # アダプターの設定を追記
  end
end
```

Active Jobを使用してメール送信テスト
※ deliver_nowの部分をdeliver_laterにするだけでOK

```
$ bin/rails c
Loading development environment (Rails 4.2.1)

Frame number: 0/5
[1] pry(main)> hoge = 'hogehoge'
=> "hogehoge"
[2] pry(main)> ContactMailer.sendmail_notice(hoge).deliver_later

# キューに登録されていることを確認
Enqueued ActionMailer::DeliveryJob (Job ID: fa4d782c-69c0-4d04-b866-7470aa3fd205) to DelayedJob(mailers) with arguments: "ContactMailer", "sendmail_notice", "deliver_now", "hogehoge"
   (6.6ms)  BEGIN
  SQL (27.8ms)  INSERT INTO `delayed_jobs` (`queue`, `handler`, `run_at`, `created_at`, `updated_at`) VALUES ('mailers', '--- !ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper\njob_data:\n  job_class: ActionMailer::DeliveryJob\n  job_id: fa4d782c-69c0-4d04-b866-7470aa3fd205\n  queue_name: mailers\n  arguments:\n  - ContactMailer\n  - sendmail_notice\n  - deliver_now\n  - hogehoge\n', '2015-07-27 14:33:16', '2015-07-27 14:33:16', '2015-07-27 14:33:16')
   (1.0ms)  COMMIT
=> #<ActionMailer::DeliveryJob:0x007fcd98e6aba0 @arguments=["ContactMailer", "sendmail_notice", "deliver_now", "hogehoge"], @job_id="fa4d782c-69c0-4d04-b866-7470aa3fd205", @queue_name="mailers">
```

これでメール非同期送信の設定が完了

## Capistranoでデプロイ

デプロイ用のGemが用意されているのでそちらを使用
Gemfile

```
gem 'capistrano3-delayed-job', '~> 1.0'
```

Capfile

```
require 'capistrano/delayed-job'
```


デプロイ時にログでdelayed_jobが起動されていることを確認

```
INFO [6fce095e] Running ~/.rbenv/bin/rbenv exec bundle exec bin/delayed_job -n 1 restart as hogehoge@ip
DEBUG [6fce095e] Command: cd /var/www/hoge/releases/20150727141308 && ( PATH=/home/hoge/.rbenv/shims:/usr/local/rbenv/bin:$PATH RBENV_ROOT=~/.rbenv RBENV_VERSION=2.2.1 RAILS_ENV=production ~/.rbenv/bin/rbenv exec bundle exec bin/delayed_job -n 1 restart )
DEBUG [6fce095e] 	delayed_job: trying to stop process with pid 31573...
DEBUG [6fce095e]
DEBUG [6fce095e] 	delayed_job: process with pid 31573 successfully stopped.
DEBUG [6fce095e] 	delayed_job: process with pid 504 started.
```

## 参考
Action Mailer の基礎
http://railsguides.jp/action_mailer_basics.html

ActiveJob::QueueAdapters 
http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html

RailsのAction Mailerでメール送信
http://ruby-rails.hatenadiary.com/entry/20140828/1409236436

Rails4.2のActive Jobを使って非同期に処理を実行したりメールを送信してみる
http://genestream.hatenablog.com/entry/2015/01/15/095122

RailsでAcitiveJobとDelayedJobを使ってバックグランド処理を行う
http://ruby-rails.hatenadiary.com/entry/20150304/1425396671

<br>

<br><br><br><br><br>