`
kfw5313
  • 浏览: 28943 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

深入ActionMailer,使用Sendmail发邮件

阅读更多
ActionMailer现在的实现只支持smtp和Sendmail两种方式发送邮件,配置分别如下:
Java代码 复制代码

   1. # ActionMailer::Base.delivery_method = :smtp 
   2. # ActionMailer::Base.smtp_settings = SMTP_SETTINGS 
   3. ActionMailer::Base.delivery_method = :sendmail 
   4. ActionMailer::Base.sendmail_settings = SENDMAIL_SETTINGS 
   5. SMTP_SETTINGS  = { 
   6.   :address => "smtp.gmail.com", 
   7.   :port => 587, 
   8.   :domain => "beyondrails.com", 
   9.   :authentication => :login, 
  10.   :user_name => "beyondrails@gmail.com", 
  11.   :password => "password" 
  12. } 
  13. SENDMAIL_SETTINGS = { 
  14.   :location       => '/usr/sbin/sendmail', 
  15.   :arguments      => '-i -t' 
  16. } 

# ActionMailer::Base.delivery_method = :smtp
# ActionMailer::Base.smtp_settings = SMTP_SETTINGS
ActionMailer::Base.delivery_method = :sendmail
ActionMailer::Base.sendmail_settings = SENDMAIL_SETTINGS
SMTP_SETTINGS  = {
  :address => "smtp.gmail.com",
  :port => 587,
  :domain => "beyondrails.com",
  :authentication => :login,
  :user_name => "beyondrails@gmail.com",
  :password => "password"
}
SENDMAIL_SETTINGS = {
  :location       => '/usr/sbin/sendmail',
  :arguments      => '-i -t'
}



为什么只支持这两种方式呢?让我们看下ActionMailer::Base的源码:
Java代码 复制代码

   1. module ActionMailer 
   2.   class Base 
   3.     class << self 
   4.       def method_missing(method_symbol, *parameters)#:nodoc: 
   5.         case method_symbol.id2name 
   6.           when /^create_([_a-z]\w*)/  then new($1, *parameters).mail 
   7.           when /^deliver_([_a-z]\w*)/ then new($1, *parameters).deliver! 
   8.           when "new" then nil 
   9.           else super 
  10.         end 
  11.       end 
  12.     end 
  13.     def deliver!(mail = @mail) 
  14.       raise "no mail object available for delivery!" unless mail 
  15.       logger.info "Sent mail:\n #{mail.encoded}" unless logger.nil? 
  16.       begin 
  17.         send("perform_delivery_#{delivery_method}", mail) if perform_deliveries 
  18.       rescue Exception => e  # Net::SMTP errors or sendmail pipe errors 
  19.         raise e if raise_delivery_errors 
  20.       end 
  21.       return mail 
  22.     end 
  23.     private 
  24.       def perform_delivery_smtp(mail) 
  25.         destinations = mail.destinations 
  26.         mail.ready_to_send 
  27.  
  28.         Net::SMTP.start(smtp_settings[:address], smtp_settings[:port], smtp_settings[:domain],  
  29.             smtp_settings[:user_name], smtp_settings[:password], smtp_settings[:authentication]) do |smtp| 
  30.           smtp.sendmail(mail.encoded, mail.from, destinations) 
  31.         end 
  32.       end 
  33.  
  34.       def perform_delivery_sendmail(mail) 
  35.         IO.popen("#{sendmail_settings[:location]} #{sendmail_settings[:arguments]}","w+") do |sm| 
  36.           sm.print(mail.encoded.gsub(/\r/, '')) 
  37.           sm.flush 
  38.         end 
  39.       end 
  40.     end 
  41.   end 
  42. end 

module ActionMailer
  class Base
    class << self
      def method_missing(method_symbol, *parameters)#:nodoc:
        case method_symbol.id2name
          when /^create_([_a-z]\w*)/  then new($1, *parameters).mail
          when /^deliver_([_a-z]\w*)/ then new($1, *parameters).deliver!
          when "new" then nil
          else super
        end
      end
    end
    def deliver!(mail = @mail)
      raise "no mail object available for delivery!" unless mail
      logger.info "Sent mail:\n #{mail.encoded}" unless logger.nil?
      begin
        send("perform_delivery_#{delivery_method}", mail) if perform_deliveries
      rescue Exception => e  # Net::SMTP errors or sendmail pipe errors
        raise e if raise_delivery_errors
      end
      return mail
    end
    private
      def perform_delivery_smtp(mail)
        destinations = mail.destinations
        mail.ready_to_send

        Net::SMTP.start(smtp_settings[:address], smtp_settings[:port], smtp_settings[:domain],
            smtp_settings[:user_name], smtp_settings[:password], smtp_settings[:authentication]) do |smtp|
          smtp.sendmail(mail.encoded, mail.from, destinations)
        end
      end

      def perform_delivery_sendmail(mail)
        IO.popen("#{sendmail_settings[:location]} #{sendmail_settings[:arguments]}","w+") do |sm|
          sm.print(mail.encoded.gsub(/\r/, ''))
          sm.flush
        end
      end
    end
  end
end


我们可以清楚的看到ActionMailer的调用顺序,首先是method_missing捕捉deliver_xxx方法,然后进入deliver!方法,然后根据deliver_method进入perform_deliver_xxx方法。

可以看到,sendmail方式的实现也非常简单,直接使用IO.popen方法来调用系统命令。
使用Sendmail这一Linux下高性能邮件服务器发送邮件,可以避免使用Gmail等邮件系统提供的smtp服务不稳定或需要Recaptcha图片验证等麻烦问题。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics