あやしいブログ記事っぽいタイトルにしてみました。まあでも2021年現在ではこれでいいかなという内容だとは思います。
昨日知り合いからの依頼で、何十とあるPDFファイルをCSVに従って自動でメール送信する手段が欲しいとのことで、ちょっとしたスクリプトを書いてみました。
下準備
- SMTPでメール送信したいので、Gmail側で「IMAPを有効にする」の設定が必要です
- 他のメール プラットフォームで Gmail のメールをチェックする – Gmail ヘルプ
https://support.google.com/mail/answer/7126229?authuser=1&visit_id=637585497201660494-366743322&hl=ja&rd=1
- 他のメール プラットフォームで Gmail のメールをチェックする – Gmail ヘルプ
- SMTPで送信する際に、(いくら今だけといえど)スクリプト内にパスワードをべた書きするのは嫌なので、「アプリパスワード」という目的を絞ったトークンを発行します。そのためには二段階認証の有効化が必要なので有効化します
- アカウントを 2 段階認証プロセスで保護する – パソコン – Google アカウント ヘルプ
https://support.google.com/accounts/answer/185839
- アカウントを 2 段階認証プロセスで保護する – パソコン – Google アカウント ヘルプ
- 無事に二段階認証が有効化できたら、アプリパスワードを発行します。有効化するアプリは「メール」を選び、名前は適当につけておきます
以上でGmail側の準備は完了です
実装
mail
というそのままの名前のgemがあるので、これを使います。RailsでおなじみのActionMailerも単体で使えるようですが、このgemはセットアップが簡単そうだったので採用しました。
mikel/mail: A Really Ruby Mail Library
https://github.com/mikel/mail
require "mail" Mail.defaults do delivery_method :smtp, { address: "smtp.gmail.com", # Gmailの指定通り port: 587, # Gmailの指定通り # domainはFromの記載が@以前だけに省略されている場合の補完用のドメインらしい(Wordspaceなら独自ドメインに変更) domain: "gmail.com", user_name: "##GmailやGoogleWordspaceのアドレス##", password: "##取得したアプリパスワード##", # Gmail側で可能ならTLSを有効化するよう指定されているため enable_starttls_auto: true } end m = Mail.new do from "表示名 <##GmailやGoogleWordspaceのアドレス##>" # 表示名 <送信元メールアドレス> to "##宛先##" subject "【件名】送信テスト" add_file "./file.pdf" # 添付ファイルへのパス text_part do # マルチバイト文字列を使っているためUTF-8を指定(未指定だと警告が出ます) content_type "text/plain; charset=UTF-8" body "【本文】送信テスト" end end m.deliver
ポイントは諸々コメントに書いた通りです。文字コードの指定方法にたどり着くまでが少し大変でした(添付ファイルのContent-Typeまで上書きされてしまって変なのが来たり)
メッセージの生成の方法はハッシュだったり文字列だったり色々とスタイルが選べるようです
Module: Mail — Documentation for mail (2.7.1)
https://www.rubydoc.info/gems/mail/Mail#new-class_method
一つ気になるのがUTF-8でメールを送って文字化けしたりしないのだろうかというところですが、GmailでGUIからふつうに送信しているメール自体がUTF-8になっているようなので、たぶん大丈夫だと思います。たぶん。。
ということで無事に送信できたメールはこちら
Content-Transfer-Encodingは特に指定していませんが、base64で送信されていました。(GmailでGUIからメールを送信する場合と同じです。)
ソースコードにパスワードを埋め込むあたり突っ込みたいような気もしつつ、単発で送るだけなら今回の方法でもお手軽さを考えればありだと思います
一通り作業が済んだらアプリパスワードはGoogleの管理画面から無効化しておきましょう。
パスワードを標準入力から受け取るとか.envに入れるとかもありだと思います