Ubuntu下用Rails的ActionMail发送Email

好久好久没有写过Blog了,五一放假其间赶紧补上。
在Ubuntu7.04上,可以用postfix作为邮件发送服务器,如果只想通过本机发送邮件,则可以考虑不使用smtp验证
安装postfix:
ruby 代码
  1. sudo apt-get install postfix  
配置postfix:
ruby 代码
  1. sudo dpkg-reconfigure postfix 
ruby 代码
  1. internet Site  
  2. NONE  
  3. server1.example.com  
  4. server1.example.com,localhost.example.com,localhost  
  5. No  
  6. 127.0.0.0/8  
  7. Yes  
  8. 0  
  9. +  
  10. all  
如果希望局域网内其他电脑能够通过本机发送邮件,则将127.0.0.0/8这一栏改为
127.0.0.0/8, 192.168.1.0/24
这样在192.168.1.x网段的电脑都可以使用本机邮件发送服务了,此时可以开一个postfix日志窗口查看邮件是否能够正常发送
ruby 代码
  1. tail -f /var/log/mail.log  
测试邮件发送服务:
ruby 代码
 
  1. telnet localhost 25    
  2. Trying 127.0.0.1...    
  3. Connected to localhost.    
  4. Escape character is '^]'.    
  5. 220 nicole ESMTP Postfix (Ubuntu)    
  6.     
  7. ehlo localhost    
  8. mail from: lgn21st@gmail.com    
  9. rcpt to: lgn21st@163.com    
  10. Subjet: My Test    
  11. HelloWorld,    
  12. .    
  13. quit   

Rails通过ActionMail组件来为rails程序提供邮件发送功能,ActionMail是对Ruby的Net::SMTP模块的高级封装
首先需要配置rails的环境设置:
ruby 代码
  1. vim config/environment.rb 
在environment.rb尾部添加如下代码:
ruby 代码
 
  1. ActionMailer::Base.smtp_settings = {  
  2.   :address         =>  "localhost",  
  3.   :port            =>  25,  
  4.   :domain          =>  "example.com"  
  5. }  

生成一个邮件发送服务的Model,这里取名为notifier:
ruby 代码
  1. ruby script/generate mailer notifier

编辑app/model/notifier.rb,添加一个notifier_mail的方法:
ruby 代码
 
  1. class Notifier < ActionMailer::Base  
  2.   def notifier_mail  
  3.     recipients "[email protected]"  
  4.     from       "[email protected]"  
  5.     subject    "test"  
  6.     body       :mail => "your message" 
  7.   end  
  8. end  

创建邮件内容模板app/views/notifier/notifier_mail.rhtml,内容可以按自己的需要定制

测试rails的邮件发送功能,打开rails的console
ruby 代码
  1. ruby script/console 
  2. Notifier.deliver_notifier_mail 
console如果不返回错误,并能看到正确的TMail::Mail对象,就可到在日志中(railsapp/log/development.log)查看到发送出去邮件体是否符合预期,查看邮件服务器日志中邮件队列是否正常处理(/var/log/mail.log),查看电子邮箱中是否收到测试邮件了。

这里可能会遇到一个问题,通过自己搭的邮件服务器发送出去的邮件总是被网上邮件服务器当做spam过滤掉
希望能通过Gmail提供的SMTP服务发送邮件,但需要ActionMail支持ssl/tls方式访问SMTP服务器,ActionMail并不直接支持ssl/tls,在网上找到一个方法,可以实现此功能,需要编译并安装ruby的openssl模块,然后在rails应用程序中对Net::SMTP作扩展。
首先需要在系统中安装Openssl开发包(编译ruby的openssl模块需要)
ruby 代码
  1. sudo apt-get install libssl-dev  

编译并安装ruby的openssl模块:
ruby 代码
  1. cd ruby-CurrentVersion/ext/openssl  
  2. ruby extconf.rb  
  3. make  
  4. sudo make install  

扩展rails,在rails应用程序的lib目录下新建一个smtp_tls.rb的文件:
ruby 代码
 
  1. require "openssl"  
  2. require "net/smtp"  
  3.   
  4. Net::SMTP.class_eval do  
  5.   private  
  6.   def do_start(helodomain, user, secret, authtype)  
  7.     raise IOError, 'SMTP session already started' if @started  
  8.     check_auth_args user, secret, authtype if user or secret  
  9.   
  10.     sock = timeout(@open_timeout) { TCPSocket.open(@address@port) }  
  11.     @socket = Net::InternetMessageIO.new(sock)  
  12.     @socket.read_timeout = 60 #@read_timeout  
  13.   
  14.     check_response(critical { recv_response() })  
  15.     do_helo(helodomain)  
  16.   
  17.     if starttls  
  18.       raise 'openssl library not installed' unless defined?(OpenSSL)  
  19.       ssl = OpenSSL::SSL::SSLSocket.new(sock)  
  20.       ssl.sync_close = true  
  21.       ssl.connect  
  22.       @socket = Net::InternetMessageIO.new(ssl)  
  23.       @socket.read_timeout = 60 #@read_timeout  
  24.       do_helo(helodomain)  
  25.     end  
  26.   
  27.     authenticate user, secret, authtype if user  
  28.     @started = true  
  29.   ensure  
  30.     unless @started  
  31.       # authentication failed, cancel connection.  
  32.       @socket.close if not @started and @socket and not @socket.closed?  
  33.       @socket = nil  
  34.     end  
  35.   end  
  36.   
  37.   def do_helo(helodomain)  
  38.     begin  
  39.       if @esmtp  
  40.         ehlo helodomain  
  41.       else  
  42.         helo helodomain  
  43.       end  
  44.     rescue Net::ProtocolError  
  45.       if @esmtp  
  46.         @esmtp = false  
  47.         @error_occured = false  
  48.         retry  
  49.       end  
  50.       raise  
  51.     end  
  52.   end  
  53.   
  54.   def starttls  
  55.     getok('STARTTLS') rescue return false  
  56.     return true  
  57.   end  
  58.   
  59.   def quit  
  60.     begin  
  61.       getok('QUIT')  
  62.     rescue EOFError  
  63.     end  
  64.   end  
  65. end  

修改rails应用程序的环境配置,在之前提到的environment.rb文件尾部修改:
ruby 代码
 
  1. require "smtp_tls"  
  2. ActionMailer::Base.smtp_settings = {  
  3.   :address => "smtp.gmail.com",  
  4.   :port => 587,  
  5.   :authentication => :plain,  
  6.   :user_name => "your name",  
  7.   :password => "your password"  
  8. }  

至此,原rails应用程序不需要修改发送邮件部分的代码,只需要简单置入一个扩展文件,并作相应的配置,即获得用ssl/tls方式访问Gmail的SMTP服务器。简单测试一下,此方法发出的邮件不大会被spam掉,但事无绝对,此方法仅仅是一个参考,好处是不需要为自己的rails应用程序架设邮件服务器,缺点是无法跟踪查看邮件服务器以及邮件队列的日志信息,但Gmail一旦发送邮件失败,会自动给你的账号发送一封发送失败提示邮件。

你可能感兴趣的:(应用服务器,socket,ubuntu,Ruby,Rails)