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

深入ActionMailer,使用Sendmail发邮件

    博客分类:
  • Ruby
阅读更多
来自: http://www.beyondrails.com/blogs/11
ActionMailer现在的实现只支持smtp和Sendmail两种方式发送邮件,配置分别如下:
# 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的源码:
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图片验证等麻烦问题。
分享到:
评论
1 楼 Ozone 2008-07-09  
学习了! 刚好项目中用到!!

相关推荐

Global site tag (gtag.js) - Google Analytics