SMTP勉強
とりあえず,RubyでSMTPのSSLを使う練習.四苦八苦で笑えるかもよ.
まずは,実行してみたソースコード.
# test_smtp.rb require 'smtp.rb' # cvsの最新のコードを落としてきたもの require 'tmail' # 外部のファイルから読み込みたいだけ # メールのテキスト mail = TMail::Mail.load('mail5.txt') # mail.date = Time.now # GMail Account & password account = 'account' pass = 'password' address = 'smtp.gmail.com' port = '465' # TLSなら587なのかな? helo = 'localhost.localdomain' smtp = Net::SMTP.new(address, port) smtp.enable_ssl(OpenSSL::SSL::SSLContext.new) # verify modeをVERIFY_PEERにしちゃダメっぽいので, # enable_sslの引数のssl_contextをこんな感じに. # smtp.rbのdefault_ssl_context(@ssl_context)は,verify_modeが # VERIFY_PEERになっていて,それだとエラーが起きた. smtp.start(helo, account, pass, :login) # hoge smtp.send_message(mail.to_s, mail.from.to_s, mail.to.to_s) # fuga smtp.finish # piyo
なんせSSLとTLSの違いがわからんので,とりあえずSSLでやって,下手鉄砲を撃ちまくってみた結果です.ちなみに,以降のエラー文の,test_smtp.rbにおいてエラーが発生した箇所は,実際の行数と異なりますので,ラベルを付けてみたり.
とりあえずSSLでやってみたときのエラーメッセージは?
$ ruby test_smtp.rb ./smtp.rb:703:in `authenticate': undefined method `funcall' for #<Net::SMTP smtp.gmail.com:465 started=false> (NoMethodError) from ./smtp.rb:546:in `do_start' from ./smtp.rb:507:in `start' from test_smtp.rb:23 # hoge
funcallが無いとか言われても,すげー困る.
smtp.rbのfuncallって何なの?
funcallは意味わかんないので,試しにコメントアウトしてみる
def authenticate(user, secret, authtype) check_auth_method authtype check_auth_args user, secret # funcall "auth_#{authtype || 'cram_md5'}", user, secret end
こんな感じにしてみて,実行
$ ruby test_smtp.rb ./smtp.rb:898:in `check_response': 530 5.5.1 Authentication Required *********** (Net::SMTPUnknownError) # なんか乱数のような文字列さ from ./smtp.rb:863:in `getok' from ./smtp.rb:793:in `mailfrom' from ./smtp.rb:633:in `send_message' from test_smtp.rb:24 # fuga
check_responseで,上のメソッドauthenticateに関係しそうなところでエラーが起こった.ソースコードを読んでいて考えたのは,たぶんだけど,funcallってのはauth_#{authtype || 'cram_md5'}って名前のメソッドにuserとsecretを渡して呼び出す,みたいな動きをすると思うんだ.だから,sendで良いと思うの.ボクは.結局,こうすると解決した.
def authenticate(user, secret, authtype) check_auth_method authtype check_auth_args user, secret self.send "auth_#{authtype || 'cram_md5'}", user, secret end
funcall→self.sendの結果は?
この状態でtest_smtp.rbを実行してみると,エラーメッセージこそ出るものの,ちゃんと最終行まで行ってる.てことは,Authenticateできたってことだよね.今回は自分のgmailのアドレスから自分のgmailのアドレスに送ったんだけれども,実際にGMailを開いてみると送信済みメッセージと受信メッセージに追加されていた.さて,お次のエラーはというと,
$ ruby test_smtp.rb /opt/local/lib/ruby/1.8/net/protocol.rb:133:in `sysread': end of file reached (EOFError) (略) from ./smtp.rb:587:in `do_finish' from ./smtp.rb:516:in `finish' from test_smtp.rb:26 # piyo
ということで,Net::SMTP#finishを考えないといけないようだ.
finish,それはコネクションのクローズ
これは,先例があるので簡単に解決できた.ありがたや.
id:zorio:20060416:1145206278
どうも、GMailはQUITを送ると応答を返さずにコネクションを切断するようだ。
どうするのが正しいのか分からんので、とりあえず保留。
これの解法は,id:zorio:20060417:1145281299に載っていたので,それをそのまま適応する.
def quit begin getok('QUIT') rescue EOFError end end
とすると,一番上に載せたスクリプトは,エラーを吐く事無く実行が終了し,ホッと胸を撫で下ろすボクがそこに居るのでした.
id:zorioさんみたいな人が居ないと,ボクはいつまでたっても迷える子羊だったのだろうか(たぶん最新バージョンのsmtp.rbの存在は知ることが無かったと思う).