1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
# frozen_string_literal: true
require 'mail/check_delivery_params'
module Mail
# == 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 => true }
# 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 => true }
# end
#
# === 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), or a string containing
# the name of an OpenSSL verify mode (none, peer, client_once,
# fail_if_no_peer_cert).
#
# === 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!
class SMTP
include Mail::CheckDeliveryParams
def initialize(values)
self.settings = { :address => "localhost",
:port => 25,
:domain => 'localhost.localdomain',
:user_name => nil,
:password => nil,
:authentication => nil,
:enable_starttls_auto => true,
:openssl_verify_mode => nil,
:ssl => nil,
:tls => nil
}.merge!(values)
end
attr_accessor :settings
# Send the message via SMTP.
# The from and to attributes are optional. If not set, they are retrieve from the Message.
def deliver!(mail)
smtp_from, smtp_to, message = check_delivery_params(mail)
smtp = Net::SMTP.new(settings[:address], settings[:port])
if settings[:tls] || settings[:ssl]
if smtp.respond_to?(:enable_tls)
smtp.enable_tls(ssl_context)
end
elsif settings[:enable_starttls_auto]
if smtp.respond_to?(:enable_starttls_auto)
smtp.enable_starttls_auto(ssl_context)
end
end
response = nil
smtp.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp_obj|
response = smtp_obj.sendmail(message, smtp_from, smtp_to)
end
if settings[:return_response]
response
else
self
end
end
private
# Allow SSL context to be configured via settings, for Ruby >= 1.9
# Just returns openssl verify mode for Ruby 1.8.x
def ssl_context
openssl_verify_mode = settings[:openssl_verify_mode]
if openssl_verify_mode.kind_of?(String)
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{openssl_verify_mode.upcase}".constantize
end
context = Net::SMTP.default_ssl_context
context.verify_mode = 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
end
end
|