Railsでドットが連続3つ(トリプルドット)以上あるメールアドレスでもActionMailer::Base.deliverを利用してメールを送信する
●何がやりたいのか
RailsでActionMailer::Base.deliverを利用してメールを送信する場合、以下のようなアドレスは通常送信できないが、送信したい。
TMail 携帯メールアドレス問題 - 基本へ帰ろう←の対応策の一つ。
●実験
・ドットが連続3つ
C:\rails_app>ruby script/console Loading development environment. >> mail = TMail::Mail.new => #<TMail::Mail port=#<TMail::StringPort:id=0x246883e> bodyport=nil> >> mail.to = "hoge...hoge@docomo.ne.jp" => "hoge...hoge@docomo.ne.jp" >> ActionMailer::Base.deliver(mail) => #<TMail::Mail port=#<TMail::StringPort:id=0x246883e> bodyport=#<TMail::StringPort:id=0x246501c>>
Railsのログには以下のように残される。
Sent mail: To: <>
・ドットが連続2つ
C:\rails_app>ruby script/console Loading development environment. >> mail = TMail::Mail.new => #<TMail::Mail port=#<TMail::StringPort:id=0x246883e> bodyport=nil> >> mail.to = "hoge...hoge@docomo.ne.jp" => "hoge...hoge@docomo.ne.jp" >> ActionMailer::Base.deliver(mail) => #<TMail::Mail port=#<TMail::StringPort:id=0x246883e> bodyport=#<TMail::StringPort:id=0x246501c>>
Railsのログには以下のように残される。
Sent mail: To: hoge..hoge@docomo.ne.jp
上記の結果から分かるように、ドットが3つ以上のメールアドレスはToが消えてしまう。
●ドットが連続3つでもActionMailer::Base.deliverを使ってメールを送信する
結論から言うとこうやりました。
・tmail_triple_dot_measures.rb
module ActionMailer class Base def deliver!(mail = @mail) if "#{mail.to}" =~ /\.\.\./ sendmail_lr = SendmailWithoutUsingActionmailer::Send.new(@from,@subject,@body) sendmail_lr.sendto(@recipients) return mail end raise "no mail object available for delivery!" unless mail logger.info "Sent mail:\n #{mail.encoded}" unless logger.nil? begin send("perform_delivery_#{delivery_method}", mail) if perform_deliveries rescue Exception => e # Net::SMTP errors or sendmail pipe errors raise e if raise_delivery_errors end return mail end end end
・sendmail_without_using_actionmailer.rb
module SendmailWithoutUsingActionmailer =begin Example: class Mobile::Users::AccountController < ApplicationController require 'sendmail_without_using_actionmailer' def sendmail_for_triple_dot subject = "テストタイトル" body = "テスト本文" from = "customer@#{SEND_DOMAIN}" to = "hoge@docomo.ne.jp" sendmail = SendmailWithoutUsingActionmailer::Send.new(from,subject,body) sendmail.sendto( to ) end end =end class Send require "nkf" SENDMAIL = "/usr/sbin/sendmail" def initialize( from, subject, body ) @from = from @subject = subject @body = body end def encode( str ) require "base64" "=?iso-2022-jp?B?" + Base64.encode64( NKF.nkf( "-j", str ) ).chomp + "?=" end def sendto( to, cc = nil, bcc = nil ) text = "From: #{@from}\n" text += "To: #{to}\n" text += "Cc: #{cc}\n" if cc text += "Bcc: #{bcc}\n" if bcc text += "Subject: #{encode( @subject ).gsub(/\n/,'\\n') if @subject}\n" text += "MIME-Version: 1.0\n" text += "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n" text += "Content-Transfer-Encoding: 7bit\n" text += "\n" text += NKF.nkf( "-j", @body ) + "\n" to = to.split( /,\s*/ ) to += cc.split( /,\s*/ ) if cc to += bcc.split( /,\s*/ ) if bcc [@from,*to].each do |t| raise "Mail address error -> #{t}" if t !~ /^[0-9A-Za-z_\-\._]+@[0-9A-Za-z_\-\._]+$/ end require "net/smtp" logger = Logger.new("#{RAILS_LOG_FILE}") begin Net::SMTP.start( 'localhost' ) do |smtp| smtp.send_mail text, @from, to end rescue #送信失敗ログを出す #logger.info "SENDMAIL_WITHOUT_USING_ACTIONMAILER SEND FALSE:To:\n #{to}\n" unless logger.nil? #logger.info "SENDMAIL_WITHOUT_USING_ACTIONMAILER SEND FALSE:Subject:\n #{@subject}\n" unless logger.nil? #logger.info "SENDMAIL_WITHOUT_USING_ACTIONMAILER SEND FALSE:Body:\n #{@body}\n" unless logger.nil? return false else #送信成功ログを出す #logger.info "SENDMAIL_WITHOUT_USING_ACTIONMAILER SEND TRUE:To:\n #{to}\n" unless logger.nil? #logger.info "SENDMAIL_WITHOUT_USING_ACTIONMAILER SEND TRUE:Subject:\n #{@subject}\n" unless logger.nil? #logger.info "SENDMAIL_WITHOUT_USING_ACTIONMAILER SEND TRUE:Body:\n #{@body}\n" unless logger.nil? return true end end end end
ActionMailer::Base.deliverは使いますが、ドットを連続3つ以上含んでいたら、SendmailWithoutUsingActionmailerモジュールを使って送信すると言うやり方をやってみました。Viewのメールテンプレートもそのまま使えますので良いです。
Railsへの設置の仕方は、上記2つのファイルをRailsアプリのlibフォルダ内に入れます。