Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

メールフォームからメールを送る近代的な方法 | YAPC::Kansai 2017 OSAKA

4,735 views

Published on

メール送信温故知新、今昔物語。

Published in: Software
  • Be the first to comment

メールフォームからメールを送る近代的な方法 | YAPC::Kansai 2017 OSAKA

  1. 1. メールフォーム から メールを送る 近代的な方法 @azumakuniyuki YAPC::Kansai 2017 Osaka 2017/03/4(土) MOTEXさん
  2. 2. メールフォーム から メールを送る 近代的な方法 @azumakuniyuki YAPC::Kansai 2017 Osaka 2017/03/4(土) MOTEXさん メール送信 温故知新
  3. 3. 自己紹介 @azumakuniyuki (東邦之) 株式会社Cubicroot (京都市) 3 - インフラエンジニア(ラック実装から構築・保守) - *BSD, Linux, 古くはSolaris, SunOS - ネットワークの設計・サーバの構築と保守 - インフラのコード化支援(Ansible,Serverspec) - 数年前からプログラマー - 主にPerl, Rubyも - サイトの開発(バックエンド) - メール関連の開発 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  4. 4. ニャーン 4YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  5. 5. 子 曰 温 故 而 知 新 可 以 為 師 矣 論 語 ・ 爲 政 第 二 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  6. 6. 子 曰 温 故 而 知 新 可 以 為 師 矣 論 語 ・ 爲 政 第 二 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  7. 7. 7 /usr/sbin/sendmail YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  8. 8. /usr/sbin/sendmail 8 - 信頼と実績・歴史と伝統のSendmailそのもの - -rwxr-sr-x root smmsp sendmail* - setgidされたやつ - おなじみのコマンドは全部/usr/sbin/sendmailが実体 - /usr/bin/newaliases - /usr/bin/mailq 必ずある(V8Sendmail) YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  9. 9. 9 - /etc/alternatives/mta - Postfixと同居しているパターン多い - /usr/sbin/alternatives(8)で切り替えられる - /usr/sbin/sendmail.sendmail - /usr/sbin/sendmail.postfix 必ずある(何かと同居) /usr/sbin/sendmail YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  10. 10. 10 - Sendmailを駆逐したい勢力 - Sendmailが捨てられて何かに置き換わっている - /var/qmail/bin/sendmail - /usr/bin/exim - macOS $ strings /usr/sbin/sendmail | grep postfix 必ずある(入れ替わってる?) /usr/sbin/sendmail YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  11. 11. 11 - どれも本家の/usr/sbin/sendmailとある程度の互換性がある - my $sendmail = '/usr/sbin/sendmail -t'; - php.ini/sendmail_path= - ; (default: "sendmail -t -i"). - CGI::FormBuilder - qw(/usr/lib/sendmail /usr/sbin/sendmail /usr/bin/send... - LWP::Protocol::mailto - qw(/usr/sbin/sendmail /usr/lib/sendmail /usr/ucblib/s... 存在する前提になってる /usr/sbin/sendmail YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  12. 12. 12 $ hostname | mail -s 'Nyaan' neko@nyaan.jp $ ls -laF `which mail` lrwxrwxrwx ... /usr/bin/mail -> mailx* $ strings /usr/bin/mailx | grep sendmail /usr/sbin/sendmail 存在する前提になってる /usr/sbin/sendmail YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  13. 13. 13 無いといろいろマズい、たぶん /usr/sbin/sendmail YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  14. 14. 14 127.0.0.1:25 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  15. 15. 15 25 = SMTP YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  16. 16. 16 $ netstat -na | grep LISTEN | grep -E ':(25|587)' tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp6 0 0 ::1:25 :::* LISTEN # /usr/sbin/lsof -i:25 COMMAND PID USER ... sendmail 2401 root ... localhost:smtp (LISTEN) MTAでなくても動いてる 127.0.0.1:25 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  17. 17. 17 # mailq -Ac /var/spool/clientmqueue (1 request) ... v22IJrNi0022 ... Fri Mar 3 02:22 root (Deferred: Connection refused by [127.0.0.1]) neko@nyaan.jp # crontabの結果がメールで来ないとか、いろいろ困る。 動いてないとキューに溜まる 127.0.0.1:25 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  18. 18. 18 動いている前提になっている localhost:25 - Mail::Sendmail - 'smtp' => [ qw( localhost ) ], - Email::Sender - ::Transport::SMTP - has host => (..., default => sub { 'localhost' }); - Email::Send::SMTP - my $host = delete($args{Host}) || 'localhost'; YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  19. 19. 19 To: neko@nyaan.jp ニャーン 里親になる! なまえ メール でんわ @ 送信 /usr/bin/mail* smtp.nyaan.jp:25 Sendmail, Postfix, ... ~/dead.letter Mail Queue 127.0.0.1:25 /usr/sbin/sendmail* YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  20. 20. 20 192.0.2.222:25 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  21. 21. 21 別のSMTPサーバを経由する 192.0.2.222:25 - 多くのWebサーバから外へ出るメールのゲートウェイとして - ゲートウェイ? - ウィルスチェックをするとか - 特定のFrom:なメールだけ通過させる - 野良メールはゲートウェイで捨てる - 優先度(Precedence:)別に処理するとか - 登録完了系はすぐに送信 - お知らせ系はキューに貯めて毎時0分に送信 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  22. 22. 22 今は外へメールが送りにくい 192.0.2.222:25 - OP25B: Outbound Port 25 Blocking - 一般家庭の回線から外部のSMTPへ接続できない - ISPがブロックしている - 固定IPアドレスの回線なら外向きのSMTP接続も大丈夫 - SPF: Sender Policy Framework - DNSのTXTレコードで設定されている - 「**@nyaan.jpは192.0.2.222からしか送信しませんよ」 - ↑TXTに書いていないとこからのメールは「迷惑メール」行き? YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  23. 23. 23 To: neko@nyaan.jp ニャーン 里親になる! なまえ メール でんわ @ 送信 /usr/bin/mail* smtp.nyaan.jp:25 Sendmail, Postfix, ... ~/dead.letter Mail Queue 127.0.0.1:25 /usr/sbin/sendmail* 192.0.2.222:25 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  24. 24. 24 smtp.gmail.com:587 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  25. 25. 25 587 = Submission YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  26. 26. 26 SMTP認証を経てメール投函 smtp.gmail.com:587 - 587 = Submission - <input type = 'submit' value = '送信'> - 素数 - 587番ポートは認証が必須(で設定されているのが殆ど) - OP25Bな環境では(ほぼ)唯一のメール送信方法 - ほとんどのメールサーバはSubmissionに対応している - Gmail, Office365, Yahoo!, SendGrid, Amazon SES - 会社のメールサーバとか(Sendmail, Postfix, ...) YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  27. 27. 27 Email::Sender smtp.gmail.com:587 use Email::Sender; my $SMTP = Email::Sender::Transport::SMTP->new( 'host' => 'smtp.gmail.com', 'port' => 587, 'sasl_username' => '*********@gmail.com', 'sasl_password' => '*************' ); YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  28. 28. 28 Net::SMTP or Net::SMTPS smtp.gmail.com:587 use Net::SMTP; # TLSで通信するならNet::SMTPS; use Authen::SASL; my $smtp = Net::SMTP->new('smtp.gmail.com', 'Port'=>587); my $auth = Authen::SASL->new('callback' => { 'user' => '*******@gmail.com', 'pass' => '********' }; $smtp->auth($auth); YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  29. 29. 29 Sendmail (/etc/mail) smtp.gmail.com:587 # grep authinfo sendmail.cf Kauthinfo hash /etc/mail/authinfo # vi authinfo Authinfo:smtp.gmail.com "U:**@gmail.com" "P:**" "M:plain" # makemap hash authinfo < authinfo # chmod 0600 ./authinfo YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  30. 30. 30 Postfix (/etc/mail/postfix) smtp.gmail.com:587 # grep smtp_sasl main.cf smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/authinfo # vi authinfo [smtp.gmail.com]:587 ***@gmail.com:**** # /usr/sbin/postmap authinfo # chmod 0600 ./authinfo* YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  31. 31. 31 To: neko@nyaan.jp ニャーン 里親になる! なまえ メール でんわ @ 送信 /usr/bin/mail* smtp.nyaan.jp:25 smtp.GMail.com:587 Sendmail, Postfix, ... ~/dead.letter Mail Queue 127.0.0.1:25 /usr/sbin/sendmail* 192.0.2.222:25 #! /usr/bin/env perl use Net::SMTP; use Email::MIME; YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  32. 32. 32 「温故」編まとめ SMTP or Submission a. /usr/sbin/sendmailが要る - コマンドラインでも送れるし b. 127.0.0.1(localhost)の25番ポートでMTAが動いている - Net::SMTPとか使っても送れる c. 25番ポートにSMTP接続できる別サーバが要る - WebサーバでMTAが動いていない時のため d. 587番ポートで認証できるアカウントとサーバが要る - OP25Bでブロックされている時 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  33. 33. 子 曰 温 故 而 知 新 可 以 為 師 矣 論 語 ・ 爲 政 第 二 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  34. 34. 34 443 = HTTPS YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  35. 35. 35 メール配信サービスのAPI HTTP API - 有名且つ大きいところ - Amazon SES https://aws.amazon.com/jp/ses - SendGrid https://sendgrid.kke.co.jp/ - 信頼と実績・歴史と伝統のSMTPインターフェイスもある - Submission(認証して)で送る - SMTPアレルギーが無いなら楽かも、たぶん。 - HTTP(HTTPS)で送信する方が速い - 大量に送るならHTTP-APIを使う方が良い YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  36. 36. 36 AmazonSESのモジュール HTTP API - Amazon::SES - 依存: [JSON::XS, Moo, LWP::UserAgent, ...] - Net::AWS::SES - 依存: [HTTP::Headers, LWP::UserAgent, MIME::*] YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  37. 37. 37 SendGridのモジュール HTTP API - Mojo::SendGrid (Mojolicious) - 2016年3月に登場した(新しい!) - Mail::SendGrid - 2011年からある - 依存: [HTTP::Tiny, IO::Socket::SSL, JSON, Moo, ...] - WebService::SendGrid - 依存: [JSON::XS, Moose, DateTime::Formt::HTTP, ...] YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  38. 38. 38 僕? HTTP API use Furl; my $http = Furl->new(...); my $mail = { 'to' => 'neko@nyaan.jp', 'from' => 'kijitora@example.jp', 'subject' => 'Nyaan', 'text' => Encode::encode('UTF-8', 'にゃーん'), ... }; $http->post('https://sendgrid.net/api/mail.send.json',, $mail); YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  39. 39. 39 依存が少ないのを選んでる HTTP API - 依存が沢山あるモジュールは好みでは無い - Perlのコアモジュールなら少しぐらいOK - 開発時間 < コードが動いている時間 - 依存は少ない方がええやんね - 極少人数開発が多いし - 依存先モジュールの変更点を追いかけるのは大変やし... YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  40. 40. 40 To: neko@nyaan.jp ニャーン 里親になる! なまえ メール でんわ @ 送信 /usr/bin/mail* smtp.nyaan.jp:25 smtp.GMail.com:587 Sendmail, Postfix, ... ~/dead.letter Mail Queue 127.0.0.1:25 /usr/sbin/sendmail* 192.0.2.222:25 email.us-east-1...:443 sendgrid.com:443 #! /usr/bin/env perl use Furl; use Email::MIME; #! /usr/bin/env perl use Net::SMTP; use Email::MIME; YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  41. 41. 41 SMTP or HTTP YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  42. 42. 42 どっちが良いの? YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  43. 43. 43 SMTPの良いところ SMTP or HTTP - MTAが操作できるなら非常に柔軟なことができる - 手持ちのSMTP(Submission)アカウントで送信OK - Gmail, Yahoo!でなくても自前で建てたサーバ経由でもOK - そもそも昔からある汎用的な技術で枯れている! - 選択肢が多い - Sendmail, Postfix, qmail, Exim4, OpenSMTPD, Exchange, - qpsmtpd - コマンドラインから手軽に送信(mailx, telnet) YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  44. 44. 44 HTTPの良いところ SMTP or HTTP - MTA(SendmailやPostfixとか)が動いてなくてもOK - そもそもSMTPに関わらなくても良い - Webサイトに組み込みやすい - メールキューの監視・管理をしなくても良い - 外に出やすい(80, 443だけ外出OKとかOP25Bは無関係とか) - テンプレート機能とかメール送信以外が充実 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  45. 45. 45 SMTPのイマイチなところ SMTP or HTTP - MTA(Sendmail, Postfix, ...)が必要になることが多い - Sendmailは難解と言われる - PostfixもSMTPの知識が無いと難しい - キューの管理(たくさん滞留すると大変) - 国内の携帯電話宛とか特に - DNSのことも気にせなアカン - 外出しにくい(OP25BとかSPFとか) - ロストテクノロジー YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  46. 46. 46 HTTPのイマイチなところ SMTP or HTTP - 証明書とか面倒くさい - ちょっとテストしたいだけやのに - キューの制御ができない - 一旦エンドポイントに渡した後は何もできない - Suppressionリストが共有(Amazon SES) - 同じリージョン内でバウンスしたアドレスには送れない - 国内の携帯電話宛では厄介 - バウンス情報が少なすぎる(SendGrid) YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  47. 47. 47 適材適所 二者択一では無い YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  48. 48. 48 To: neko@nyaan.jp ニャーン 里親になる! なまえ メール でんわ @ 送信 /usr/bin/mail* smtp.nyaan.jp:25 smtp.GMail.com:587 Sendmail, Postfix, ... ~/dead.letter Mail Queue 127.0.0.1:25 /usr/sbin/sendmail* 192.0.2.222:25 email.us-east-1...:443 sendgrid.com:443 #! /usr/bin/env perl use Furl; use Email::MIME; #! /usr/bin/env perl use Net::SMTP; use Email::MIME; 127.0.0.1:2794 メールのヘッダと本文をJSON で書いてHTTP POST Haineko YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  49. 49. 49 メールを送った後 YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  50. 50. 50 バウンス処理しましょ Email Bounces - メールアドレスは水物・ナマモノ - Perlなら良いモジュールがある! YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  51. 51. 51 メールを送った後 Sisimai http://libsisimai.org/ YAPC::Kansai 2017 Osaka | 2017/03/04(土) MOTEXさん メールフォームからメールを送る近代的な方法 @azumakuniyuki
  52. 52.

×