Fixing smtp_tls.rb for Ruby 1.8.7

I’ve been on-and-off developing a couple of Ruby On Rails applications and since most of them are in the “just for fun” stage I was using my Google Apps account for e-mail delivery. However, I kept on getting argument count error in smtp_tls.rb (a library required for proper e-mail delivery via smtp.gmail.com server) - both on my development and staging machine. I know, I know, I should get a dedicated box and become a real man, but for now my Dreamhost account should be enough (hey, it’s for blogging and fun, not production!).

But back to the problem - I kept on fixing smtp_tls.rb until this morning a lightbulb popped over my head. Yes, check_auth_args in Net::SMTP takes different arguments in Ruby 1.8.7 (which I’m using for development) and in Ruby 1.8.6 (staging).

In order to make things right just do some Ruby version checking (see lines 9 - 13):

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

    if RUBY_VERSION == "1.8.7"
      check_auth_args user, secret
    else
      check_auth_args user, secret, authtype if user or secret
    end

    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