IoTなネットワークメソッドはHTTP,HTTPS,MQTTなどが一般に使われていますが、なにか忘れていませんか?そうHTTPなんかよりも古くからあるSMTPです。
ということで、mrubyでメールを送ってみました。
SMTPサーバはヤフーのアカウントでヤフーメールを使いました。最近のSMTPはSSLだったりするのでmruby-polarsslを使います。認証はSMTP_AUTHなのでmruby-base64も使いました。
余談ですがpolarsslは去年ARMに買収されてmbedドメインになっていますね。
ZRouterでクロスのmruby-polarssl/polarsslのビルドはひっかかるかなとおもったんですが、すんなりビルドできました。
def oneline(s)
line = ""
while ch = s.read(1)
line << ch
if ch == "\n"
break
end
end
puts line
line
end
myaddr = "foo@yahoo.co.jp"
toaddr = "bar@yahoo.co.jp"
pw = "himitu"
header = "From: " << myaddr << "\r\nSubject: test\r\n"
body = "MORI MORI Test"
socket = TCPSocket.new('smtp.mail.yahoo.co.jp', 465)
entropy = PolarSSL::Entropy.new
ctr_drbg = PolarSSL::CtrDrbg.new(entropy)
ssl = PolarSSL::SSL.new
ssl.set_endpoint(PolarSSL::SSL::SSL_IS_CLIENT)
ssl.set_authmode(PolarSSL::SSL::SSL_VERIFY_NONE)
ssl.set_rng(ctr_drbg)
ssl.set_socket(socket)
ssl.handshake
oneline(ssl)
ssl.write("EHLO smtp.mail.yahoo.co.jp\r\n")
while true
res = oneline(ssl)
if res[0,4] == "250 "
break
end
end
plain = Base64::encode(sprintf("%s¥0%s¥0%s", myaddr, myaddr, pw))
auth = "AUTH PLAIN " << plain << "\r\n"
ssl.write(auth)
oneline(ssl)
ssl.write("MAIL FROM:" << myaddr << "\r\n")
oneline(ssl)
ssl.write("RCPT TO:" << toaddr << "\r\n")
oneline(ssl)
ssl.write("DATA\r\n")
oneline(ssl)
mail = ""
mail << header << "\r\n" << body << "\r\n.\r\n"
ssl.write(mail)
oneline(ssl)
ssl.write("QUIT\r\n")
oneline(ssl)
ssl.close_notify
socket.close
ssl.close
plainを作っているところは最初<<で連結したら不思議な動作になってしまったのでsprintfにしました。¥0が含まれる文字列ってサポートされてるのかな。。。
FreeBSD/mipsなmrubyで実行するとこんな感じです。
# mruby smtp.rb
220 smtp531.mail.kks.yahoo.co.jp ESMTP
250-smtp531.mail.kks.yahoo.co.jp
250-AUTH LOGIN PLAIN XYMCOOKIE
250-PIPELINING
250 8BITMIME
235 ok, go ahead (#2.0.0)
250 ok
250 ok
354 go ahead
250 ok 1457748965 qp 87684
221 smtp531.mail.kks.yahoo.co.jp
この仕組みは何かの通知に使えると思いますが、パスワードの管理の問題があります。何にも使ってないアカウントであってもパスワードが漏洩すると偽装の可能性があります。