最近,メールフォーム用の CGI を求められる事が多いので簡単な関数を書いておく事にしました.メールを送る方法については,sendmail を叩くのが一番楽なようです.
SENDMAIL_PATH = "/usr/sbin/sendmail" def sendmail(from, to, subject, message) require 'kconv' require 'base64' encoded = Base64.encode64(subject.tojis).chomp! subject = "=?ISO-2022-JP?B?#{encoded}?=" # message の文字コードが不明の場合 # message = message.toutf8 if (Kconv.guess(message) != 6) IO.popen("#{SENDMAIL_PATH} -t", "r+") { |io| io.print("From: #{from}\n") io.print("To: #{to}\n") io.print("Subject: #{subject}\n") io.print("MIME-Version: 1.0\n") io.print("Content-Type: text/plain; charset=\"UTF-8\"\n") io.print("Content-Transfer-Encoding: 7bit\n") io.print("\n") io.print("#{message}\n") } end
今回は,件名は取り合えず ISO-2022-JP でエンコードしています.件名も UTF-8 でエンコードできるようで,その場合は subject = "=?UTF-8?B?#{encoded}?=" のような形になるようです.
sendmail を叩く代わりに直接 SMTP 通信を行う場合は,以下のような感じでしょうか.
def sendmail(from, to, subject, message) require 'net/smtp' ... Net::SMTP.start('localhost', 25) { |smtp| smtp.open_message_stream(from, [ to ]) { |io| io.print("Subject: #{subject}\n") io.print("MIME-Version: 1.0\n") io.print("Content-Type: text/plain; charset=\"UTF-8\"\n") io.print("Content-Transfer-Encoding: 7bit\n") io.print("\n") io.print("#{message}\n") } } end
尚,今回は,sendmail("from@example.com", "to@example.com", "hoge", "...") のように単一の宛先を指定するような使い方を想定しているので,複数の宛先を指定する場合は少し修正する必要があります.
CGI#params の挙動
メールフォーム自体とは少しずれますが,CGI#params の挙動がイマイチ分からなかったので,適当に調査してみた結果のメモ.
- CGI#params は { 文字列 => 配列 } のハッシュ
- CGI#params のデフォルト値は空の配列.したがって,(cgi.params["hoge"] == nil) は常に false
- value が存在しないような key-value pair (hoge=&... のような場合)の場合,空の文字列を要素に持つ配列が返される.
以上から,ある key に対して(空の文字列ではない)value が存在するかどうかは cgi.params["hoge"].to_s.empty? 辺りで判定できそうです.