質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

7982閲覧

Ruby net/smtp TLSを使えない

kazuyakazuya

総合スコア193

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2019/08/08 09:33

編集2019/08/14 09:45

RubyのNet/SMTPでメールを送りたいです。
smtp4devでダミーのSMTPサーバー(localhost)を使うので実際にメールが外に流れることはありません。
やりたいことは
SMTP AUTH認証 と TLS の2つが整っているSMTPサーバーにアクセスしてメールを送るプログラムを作成
するということです。

一応、SMTP AUTH認証だけが実装されているパータンのものは成功しました。

ruby

1require 'net/smtp' 2a = Net::SMTP.new("localhost",50002) 3a.start('localhost'){|smtp| 4 smtp.authenticate("sample_user_name","sample_password") 5 smtp.send_message(<<-EndOfMail, 'from@example.com', 'to@example.net') 6 From: Your Name <from@example.com> 7 To: Dest Address <to@example.net> 8 Subject: test mail 9 Date: Sat, 23 Jun 2019 18:20:50 +0900 10 Message-Id: <unique.message.id.string@yourhost.example.com> 11 12 This is a test mail. 13 EndOfMail 14} 15

smtp4devの仕様なのか
startの引数に指定するSMTP AUTHの情報はなんでも通過できます。(なにも指定しなければ無論エラーになる。)
とりあえずこれでメールを送ることはできました。

つぎはTLS機能もsmtp4devに設定して(TLSじゃないと受け付けない・・・はず)

プログラムコードには

ruby

1starttlsメソッド

を追加
ver2.4リファレンス

ruby

1require 'net/smtp' 2a = Net::SMTP.new("localhost",50002) 3a.start('localhost'){|smtp| 4 smtp.starttls 5 smtp.authenticate("sample_user_name","sample_password") 6 smtp.send_message(<<-EndOfMail, 'from@example.com', 'to@example.net') 7 From: Your Name <from@example.com> 8 To: Dest Address <to@example.net> 9 Subject: test mail 10 Date: Sat, 23 Jun 2019 18:20:50 +0900 11 Message-Id: <unique.message.id.string@yourhost.example.com> 12 13 This is a test mail. 14 EndOfMail 15} 16

実行結果

cmd

1:\Users\matsu\Desktop\ruby_lesson>ruby sample.rb 2<internal:prelude>:78:in `__read_nonblock': An established connection was aborted by the software in your host machine. (Errno::ECONNABORTED) 3 from <internal:prelude>:78:in `read_nonblock' 4 from C:/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:172:in `rbuf_fill' 5 from C:/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:154:in `readuntil' 6 from C:/Ruby24-x64/lib/ruby/2.4.0/net/protocol.rb:164:in `readline' 7 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:950:in `recv_response' 8 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:944:in `get_response' 9 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:734:in `block in auth_plain' 10 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:960:in `critical' 11 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:733:in `auth_plain' 12 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:728:in `authenticate' 13 from sample.rb:5:in `block in <main>' 14 from C:/Ruby24-x64/lib/ruby/2.4.0/net/smtp.rb:519:in `start' 15 from sample.rb:3:in `<main>'

cmd

1確立された接続は、ホストマシンのソフトウェアによって中止されました。

みたいなことが書かれてありますが
コード自体には問題はないのでしょうか?

ファイアウォールが原因なのかと思い一回すべて無効にしてから
実行してみたのですが結果は全く変わらなかったので
ファイアウォールは関係ないと思います。

何が原因なのかがわかりません。
リファレンスを見た限り違うと思いますが
Rubyのバージョン自体の問題なのでしょうか?

分からないので参考になるリンクまたは説明をお願いします。


解決方法

smtp4devではできませんでしたがsendgridを経由したらいけました。
smtp4dev自体に問題があったようです。

ruby

1require 'net/smtp' 2a = Net::SMTP.new("smtp.sendgrid.net", 587) 3a.enable_starttls 4a.start('matsukazu0409@gmail.com'){|smtp| 5 smtp.authenticate("sendgridユーザー","パスワード") 6 smtp.send_message(<<-EndOfMail, 'matsukazu0409@gmail.com', 'matsu-kazu4@ezweb.ne.jp') 7 From: Your Name <from@example.com> 8 To: Dest Address <to@example.net> 9 Subject: test mail 10 Date: Sat, 23 Jun 2019 18:20:50 +0900 11 Message-Id: <unique.message.id.string@yourhost.example.com> 12 13 This is a test mail. 14 EndOfMail 15 16 17 } 18

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

asm

2019/08/08 13:41

smtp4dev側の問題のように思えますが 別のメール送信ソフトなどで検証は行いましたか?
kazuyakazuya

2019/08/08 15:28

ありがとうございます。 それはつまり、gmailなどのメールソフトで そのままの意味でlocalhostへ送信するということですか? この場合ポート番号50001を使っているので gmailもポートをいじる必要があると思うのですが 可能なのでしょうか? 調べても出てこないです・・・。
asm

2019/08/08 16:24

gmailだとポート開放が必要で若干めんどくさいですね Thunderbird Outlook Becky! 等での動作を確認してはどうでしょうか?
kazuyakazuya

2019/08/09 00:04

ありがとうございます 一回それで試してみます。
kazuyakazuya

2019/08/09 07:36

Thunderbirdで試行していますが タイムアウトになってしまいます。 送信するときに必ず宛先を指定しなければいけないのですが この宛先がなにであれエラーには関係ない・・・のでしょうか?
guest

回答2

0

ベストアンサー

Rubyコードの問題点

サーバーの設定次第ですがa.startの時点でEHLOが平文で送られてしまうので
starttlsを送信する前にエラーになる可能性があります。

start前にenable_starttls_autoもしくはenable_starttlsを使うとよいでしょう。

RFCを確認しましたが

ruby

1 smtp.send_message(<<-EndOfMail, 'from@example.com', 'to@example.net') 2 From: Your Name <from@example.com> 3 To: Dest Address <to@example.net> 4 Subject: test mail 5 Date: Sat, 23 Jun 2019 18:20:50 +0900 6 Message-Id: <unique.message.id.string@yourhost.example.com> 7 8 This is a test mail. 9 EndOfMail

では、フィールド名の前の空白が問題を引き起こす可能性があります。<<~を使い先頭の空白を消したほうがよいでしょう。

仕様の問題点

使いたいのがSTARTTLSなのかSMTP over SSL/TLSなのかが不明です。
net/smtpはSTARTTLSとSMTP over SSL/TLSの併用は不可能な仕様になっています。
それぞれを確認するとよいでしょう。

検証方法の問題点

smtp4devは私が検証した限り.cerファイルを渡さないとTLS機能が使えない
かつ、.cerファイルの形式が不明な上、動作報告が見当たりません。
いくつか試してみましたが、正常動作させる方法は不明です。

代替として、OrigamiSMTPを利用しstarttlsの検証ができました。

投稿2019/08/12 12:31

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuyakazuya

2019/08/13 15:51

ありがとうございます。
guest

0

a.start('localhost'){|smtp| の段階ですでに接続が始まっているので、その後で starttls をするのは手遅れのようです。
上記のマニュアルにも、 starttls のところには、

通常は Net::SMTP#start で STARTTLS が送られるため 利用する必要はないはずです。

と書いてありますよね。

TLSになってなさそうであれば、下記のように enable_starttls を追加するのでどうでしょうか。
ついでにアカウント・パスワードもstartメソッドにまとめています。

ruby

1require 'net/smtp' 2a = Net::SMTP.new("localhost", 50002) 3a.enable_starttls 4a.start('localhost', "sample_user_name", "sample_password"){|smtp| 5 smtp.send_message(<<-EndOfMail, 'from@example.com', 'to@example.net') 6# (以下省略)

投稿2019/08/12 06:10

takahashim

総合スコア1877

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuyakazuya

2019/08/13 15:52

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問