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