class Mail::SMTP

Sending Email with SMTP

Mail allows you to send emails using SMTP. This is done by wrapping Net::SMTP in an easy to use manner.

Sending via SMTP server on Localhost

Sending locally (to a postfix or sendmail server running on localhost) requires no special setup. Just to Mail.deliver &block or message.deliver! and it will be sent in this method.

Sending via MobileMe

Mail.defaults do
  delivery_method :smtp, { :address              => "smtp.me.com",
                           :port                 => 587,
                           :domain               => 'your.host.name',
                           :user_name            => '<username>',
                           :password             => '<password>',
                           :authentication       => 'plain',
                           :enable_starttls      => :auto  }
end

Sending via GMail

Mail.defaults do
  delivery_method :smtp, { :address              => "smtp.gmail.com",
                           :port                 => 587,
                           :domain               => 'your.host.name',
                           :user_name            => '<username>',
                           :password             => '<password>',
                           :authentication       => 'plain',
                           :enable_starttls      => :auto  }
end

Configuring TLS/SSL and STARTTLS

A few remarks:

Certificate verification

When using TLS, some mail servers provide certificates that are self-signed or whose names do not exactly match the hostname given in the address. OpenSSL will reject these by default. The best remedy is to use the correct hostname or update the certificate authorities trusted by your ruby. If that isn't possible, you can control this behavior with an :openssl_verify_mode setting. Its value may be either an OpenSSL verify mode constant (OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER), or a string containing the name of an OpenSSL verify mode (none, peer).

Others

Feel free to send me other examples that were tricky

Delivering the email

Once you have the settings right, sending the email is done by:

Mail.deliver do
  to 'mikel@test.lindsaar.net'
  from 'ada@test.lindsaar.net'
  subject 'testing sendmail'
  body 'testing sendmail'
end

Or by calling deliver on a Mail message

mail = Mail.new do
  to 'mikel@test.lindsaar.net'
  from 'ada@test.lindsaar.net'
  subject 'testing sendmail'
  body 'testing sendmail'
end

mail.deliver!

Constants

DEFAULTS

Attributes

settings[RW]

Public Class Methods

new(values) click to toggle source
# File lib/mail/network/delivery_methods/smtp.rb, line 103
def initialize(values)
  self.settings = DEFAULTS.merge(values)
end

Public Instance Methods

deliver!(mail) click to toggle source
# File lib/mail/network/delivery_methods/smtp.rb, line 107
def deliver!(mail)
  response = start_smtp_session do |smtp|
    Mail::SMTPConnection.new(:connection => smtp, :return_response => true).deliver!(mail)
  end

  settings[:return_response] ? response : self
end

Private Instance Methods

build_smtp_session() click to toggle source
# File lib/mail/network/delivery_methods/smtp.rb, line 157
def build_smtp_session
  if smtp_tls? && (settings[:enable_starttls] || settings[:enable_starttls_auto])
    raise ArgumentError, ":enable_starttls and :tls are mutually exclusive. Set :tls if you're on an SMTPS connection. Set :enable_starttls if you're on an SMTP connection and using STARTTLS for secure TLS upgrade."
  end

  Net::SMTP.new(settings[:address], settings[:port]).tap do |smtp|
    if smtp_tls?
      smtp.disable_starttls
      smtp.enable_tls(ssl_context)
    else
      smtp.disable_tls

      case smtp_starttls
      when :always
        smtp.enable_starttls(ssl_context)
      when :auto
        smtp.enable_starttls_auto(ssl_context)
      else
        smtp.disable_starttls
      end
    end

    smtp.open_timeout = settings[:open_timeout] if settings[:open_timeout]
    smtp.read_timeout = settings[:read_timeout] if settings[:read_timeout]
  end
end
setting_provided?(k) click to toggle source

`k` is said to be provided when `settings` has a non-nil value for `k`.

# File lib/mail/network/delivery_methods/smtp.rb, line 117
def setting_provided?(k)
  !settings[k].nil?
end
smtp_starttls() click to toggle source

Yields one of `:always`, `:auto` or `false` based on `enable_starttls` and `enable_starttls_auto` flags. Yields `false` when `smtp_tls?`. Else defaults to `:auto` when neither `enable_starttls*` flag is provided. Providing a truthy value for `enable_starttls` will ignore `enable_starttls_auto`.

# File lib/mail/network/delivery_methods/smtp.rb, line 125
def smtp_starttls
  return false if smtp_tls?

  if setting_provided?(:enable_starttls) && settings[:enable_starttls]
    # enable_starttls: provided and truthy
    case settings[:enable_starttls]
    when :auto then :auto
    when :always then :always
    else
      :always
    end
  else
    # enable_starttls: not provided or false
    if setting_provided?(:enable_starttls_auto)
      settings[:enable_starttls_auto] ? :auto : false
    else
      # enable_starttls_auto: not provided
      # enable_starttls: when provided then false
      # use :auto when neither enable_starttls* provided
      setting_provided?(:enable_starttls) ? false : :auto
    end
  end
end
smtp_tls?() click to toggle source
# File lib/mail/network/delivery_methods/smtp.rb, line 149
def smtp_tls?
  (setting_provided?(:tls) && settings[:tls]) || (setting_provided?(:ssl) && settings[:ssl])
end
ssl_context() click to toggle source

Allow SSL context to be configured via settings, for Ruby >= 1.9 Just returns openssl verify mode for Ruby 1.8.x

# File lib/mail/network/delivery_methods/smtp.rb, line 186
def ssl_context
  openssl_verify_mode = settings[:openssl_verify_mode]

  if openssl_verify_mode.kind_of?(String)
    openssl_verify_mode = OpenSSL::SSL.const_get("VERIFY_#{openssl_verify_mode.upcase}")
  end

  context = Net::SMTP.default_ssl_context
  context.verify_mode = openssl_verify_mode if openssl_verify_mode
  context.ca_path = settings[:ca_path] if settings[:ca_path]
  context.ca_file = settings[:ca_file] if settings[:ca_file]
  context
end
start_smtp_session(&block) click to toggle source
# File lib/mail/network/delivery_methods/smtp.rb, line 153
def start_smtp_session(&block)
  build_smtp_session.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication], &block)
end