この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
こんにちは、KBMJの中平@railsエンジニアです。
今回は、docomoやauなどのメールドレスでドットの連続とか@の前にドットをつけたRFC違反メールアドレスだと、ruby on rails のActionMailer(Tmail)でメール送受信が失敗していたので、その対策方法を書きます。RFC違反メールアドレスだとActionMailer(Tmail)でどのような問題が起こるのか
ruby…rails.@kbmj.com などのメールアドレスだとActionMailer(Tmail)を使ってメールの送受信をした時に、メールアドレスの
from、toがnilになってしまいメールアドレスが送受信できません。
(スパムが心配なのでドメインは弊社のものにしています。)
確認してみる
ruby script/console
>> TMail::Version
=> “0.10.7”
>> mail = TMail::Mail.new
=> #<TMail::Mail port=#<TMail::StringPort:id=0x27c5f68> bodyport=nil>
>> mail.from = ‘ruby…rails.@kbmj.com’
=> nil
とnilになってしまい、メールアドレスがきちんと取得できません。
■対策方法
こちらのサイトを参考にさせていただきました。
最新のTMailだと対策されているみたいですが、リリース済みのプロジェクトでしたので、parse.yからparse.rbを作り直します。
1.parse.yファイルを取得します。
Tmailを単体で取得し、その中にparse.yがありますのでそれを使います。
http://rubyforge.org/frs/?group_id=4512
ここからダウンロード、使用しているTMailと同じバージョンのものを使います。リビジョン 3329で対応しているみたいですので、
変更内容
svn log -r 3329 http://i.loveruby.net/svn/public/tmail/trunk/svn diff -r 3328:3329 http://i.loveruby.net/svn/public/tmail/trunk/lib/tmail/parser.y
で変更点を同じようにダウンロードしたpaser.yに編集します。
2.parse.yからparse.rbを作成しなおします。
raccを使いparse.yからparse.rbを作成いたします。
raccがない場合は取得して使ってください。
windows環境だとサンプルのように
racc -ocalc.rb calc-ja.y
としても、実行されないので
c:\ruby\bin\racc -ocalc.rb calc-ja.yという感じで実行する必要があります。
praser.rbを作成する。
c:\ruby\bin\racc parser.y -E -o tmail_parser.rb
参考にさせていただいたサイトですと、直接既存のparser.rbを置き換えていますが、
私は直接置き換えずtmail_parser.rbとファイル名をつけ、
project\libの中にtmail_parser.rbを入れておき
起動時に
TMail.instance_eval{remove_const ‘Parser’}
require ‘tmail_parser’
として、parser.rbを新しいtmail_parserを使うようにしております。
これで、RFC違反メールアドレス対策が出来ました。
確認してみる。
ruby script/console
>> mail = TMail::Mail.new
=> #<TMail::Mail port=#<TMail::StringPort:id=0x27c5f68> bodyport=nil>
>> mail.from = ‘ruby…rails.@kbmj.com’
=> “ruby…rails.@kbmj.com”
問題ないことが確認できました。
第2の問題
実際にメール送受信を試したところ、送信は出来ているのですが受信に失敗していました。
ログを調べてみると・・・・
postfixがRFC違反メールアドレスだと、
ruby…rails.@kbmj.comを”ruby…rails.”@kbmj.com という感じで変更していました。
そのため、再びparseが上手くいかずメールアドレスがnilになっていました。
ログを見るとヘッダー情報にはメールアドレスがそのままきていましたので、
require ‘action_mailer’
module TMail
class Mail
# 指定された名前の最初のヘッダを取得する
def first_header(key)
if port.to_s =~ /^#{key}:\s*(.*)/i
$1
else
nil
end
end
end
end
このようなmoduleを作成し、
メールの受信処理に
def receive(email)
email.first_header(‘return-path’).sub(/^</, ”).sub(/>$/, ”).sub(/^\”/,”).sub(/\”@/,’@’)
end
とすることで、無事メールアドレスが取得できました。
古いバージョンActionMailer(Tmail)でRFC違反メールアドレスの対応する場合は参考にしていただければと思います。