Heroku Schedulerでruby-gmailを使ってGmailの送信を予約できるようにした
メールを送信しようと思ったら深夜で、でも深夜にメール送るのもなんか嫌で、結局下書き保存して後で送信することがよくあって困ります。
夜は早く寝ろというツッコミもありますが、深夜のメール以外にも何かとメールを遅らせて送信したい場面は少なくありません。
送信を予約できるような仕組みは無いのかと探したところ、いくつか見つかりました。
今あるツール
メーラー
ThunderbirdやOutlookには送信を予約できる機能があるそうです。しかし、普段からメーラーを使わずにブラウザからGmailを使っているので、わざわざインストールするのはめんどくさいです。それに予約した時間にPCの電源を入れてないと使えないと思うんですが、どうなんでしょうか。調べてません。
ブラウザ拡張機能
Right InboxやBoomerang for Gmailというブラウザの拡張機能を使うと、Gmailの予約送信ができるようになります。普段のGmailの画面にボタンが追加され、そこで時間を指定できます。予約した時間になると、サーバーがGmailにアクセスしてメールを送信する仕組みだと思われます。ただし月10通までしか無料で使えないという欠点があります。
じゃあ自分で作ればいいじゃん
- 無料、かつ件数制限無し
- PC立ち上げっぱなしじゃなくていい
こういうのが欲しかったのですが、探した限りありませんでした。じゃあ自分で作ればいいじゃん。
無料のPaaSとかでできないかなと探していると、良さそうなものとしてHeroku Schedulerが見つかりました。
Heroku Scheduler
Herokuのアドオンの1つで、cronみたいなことを行うことができます。ただし実行間隔は固定されていて、10分/1時間/1日間隔のいずれかです。
Herokuの料金体系は少し分かりにくいですが、どうやらプロセスの動いた時間の合計が月750時間以下であれば無料みたいです。
webのプロセス数を0にして、workerのプロセスを1つだけを動かすようにすれば、ずっと動かしていても無料の範囲内に収まります。
作ってみた
使い方
- 件名の先頭に[1h30m]とか書いてGmailの下書きに保存しておく
- (約)1時間30分後に自動で送信される
とっても簡単ですね。
仕様
- 10分ごとに起動
- Gmailにアクセスして下書きメールを見る
- 件名の先頭に時間指定があった場合、その時間だけメールの保存時刻から過ぎていたら送信する
10分よりも細かな時間は指定出来ませんが、10分は誤差とみなせる範囲なので問題ありません。
実装
最近なんとなくRubyを勉強したいなと思っていたので、Rubyで書きました。 入門書は読んでいなくて、分からなかったらググって調べるを繰り返してたので、シンタックスとかかなり怪しいです。
Gmailのアクセスにruby-gmailというgemを使うので、まずGemfileを用意。
Gemfile
source "https://rubygems.org" gem 'ruby-gmail'
bundlerでgemをインストール。
$ bundle install --path=vendor/bundle
スクリプトを書きます。
send-gmail-later.rb
# encoding utf-8 require 'gmail' USERNAME = ENV['GOOGLE_USERNAME'] PASSWORD = ENV['GOOGLE_PASSWORD'] PATTERN = /^\[(\d+d)?(\d+h)?(\d+m)?\] / Gmail.new(USERNAME, PASSWORD) do |gmail| now = DateTime.now gmail.mailbox('[Gmail]/Drafts').emails(:all).each do |draft| if draft.subject =~ PATTERN d = $1.to_i h = $2.to_i m = $3.to_i if d == 0 && h == 0 && m == 0 next end send_date = draft.date + d + Rational(h * 60 + m, 1440) if send_date <= now gmail.deliver do to draft.to subject draft.subject.sub(PATTERN, '') body draft.body.decoded.encode('utf-8', draft.charset) end draft.date = now draft.archive! end end end end
.bundleとvendorディレクトリは.gitignoreに追加しておきます。
$ cat << EOF > .gitignore .bundle/ vendor/ EOF
2013-06-20追記: .bundleディレクトリは.gitignoreに追加しないほうがいいです。
gitにコミット。
$ git init $ git add . $ git commit -m "Initial commit"
Heroku Toolbeltをインストールして、ログインなどの初期設定をします。
自分の環境はUbuntuなのでUbuntu用をインストールします。
$ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh $ heroku login
heroku appを作成します。
このときgitのワーキングディレクトリにいると、自動でremoteにherokuが追加されます。
$ heroku create
webのプロセスは使わないので、プロセス数を0にします。
$ heroku ps:scale web=0
Googleのユーザー名とパスワードはスクリプト中には書けないので、Herokuの環境変数に登録します。
$ heroku config:add GOOGLE_USERNAME={自分のユーザー名} $ heroku config:add GOOGLE_PASSWORD={自分のパスワード}
タイムゾーンを東京に設定して、時刻の比較をできるようにします。
$ heroku config:add TZ=Asia/Tokyo
デプロイ。
$ git push heroku master
Heroku Schedulerアドオンを追加。
このアドオン自体は無料ですが、クレジットカード情報を登録していないと追加できません。
$ heroku addons:add scheduler:standard
schedulerの設定画面を開きます。
$ heroku addons:open scheduler
Add Job...
をクリックして、taskを登録します。
$ bundle exec ruby send-gmail-later.rb
frequencyをEvery 10 minutes
に設定してSave
を押せば完了です。