メールフォーム

最近,メールフォーム用の 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 の挙動がイマイチ分からなかったので,適当に調査してみた結果のメモ.

  1. CGI#params は { 文字列 => 配列 } のハッシュ
  2. CGI#params のデフォルト値は空の配列.したがって,(cgi.params["hoge"] == nil) は常に false
  3. value が存在しないような key-value pair (hoge=&... のような場合)の場合,空の文字列を要素に持つ配列が返される

以上から,ある key に対して(空の文字列ではない)value が存在するかどうかは cgi.params["hoge"].to_s.empty? 辺りで判定できそうです.

このエントリをつぶやく このWebページのtweets