RailsのActionMailerでGmailのsmtpサーバーを使ってメール送信する。

えー、10章と11章は問題なかったので飛ばしますw
そして12章からはテストに入って行ってますが、何か作っていかないとモチベーションが保てないので次はメールの送信やってみます。

メール送信できれば実際に使えるシステムを作れそうだ。
本番環境に移す方法がまだよくわかってないけど。

まずは開発環境だと実際にメールを送れなくてもエラーが出ないので、
/config/environments/development.rbの下の行をtrueにする。

config.action_mailer.raise_delivery_errors = true

そしてすばらしいコードがあったので使わせてもらいました。
http://www.prestonlee.com/archives/63

以下のコードを書いてlib/smtp_tls.rbに保存します。

require "openssl"
require "net/smtp"

Net::SMTP.class_eval do
  private
  def do_start(helodomain, user, secret, authtype)
    raise IOError, 'SMTP session already started' if @started
    check_auth_args user, secret, authtype if user or secret

    sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
    @socket = Net::InternetMessageIO.new(sock)
    @socket.read_timeout = 60 #@read_timeout

    check_response(critical { recv_response() })
    do_helo(helodomain)

    if starttls
      raise 'openssl library not installed' unless defined?(OpenSSL)
      ssl = OpenSSL::SSL::SSLSocket.new(sock)
      ssl.sync_close = true
      ssl.connect
      @socket = Net::InternetMessageIO.new(ssl)
      @socket.read_timeout = 60 #@read_timeout
      do_helo(helodomain)
    end

    authenticate user, secret, authtype if user
    @started = true
  ensure
    unless @started
      # authentication failed, cancel connection.
      @socket.close if not @started and @socket and not @socket.closed?
      @socket = nil
    end
  end

  def do_helo(helodomain)
    begin
      if @esmtp
        ehlo helodomain
      else
        helo helodomain
      end
    rescue Net::ProtocolError
      if @esmtp
        @esmtp = false
        @error_occured = false
        retry
      end
      raise
    end
  end

  def starttls
    getok('STARTTLS') rescue return false
  return true
  end

  def quit
    begin
      getok('QUIT')
    rescue EOFError
    end
  end
end

そしてconfig/environment.rbの設定は


require "smtp_tls"

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:authentication => :plain,
:user_name => "username@gmail.com",
:password => 'password'}

あとは普通にメール送信したらできました。
注意は、開発環境でもconfig/environment.rbの更新は再起動しないといけないみたいです。


ーーー追記ーーー

しばらくしてから同じようにメール送信しようとしたら

wrong number of arguments (3 for 2)

/lib/smtp_tls.rb:8:in `check_auth_args'

というエラーが出て送信できなかった。
   
\lib\smtp_tls.rb の8行目で、

check_auth_args user, secret, authtype if user or secret を
check_auth_args user, secret if user or secret
のように、check_auth_args 呼出時のパラメタ authtype を削除したらメール送信できました。

前にこれで送信できた時はrubyのバージョンが1.8.6で今は1.8.7なのでその違いなのかもしれません。