ruby用來發送互連網郵件
其實只要你任性的可以,用telnet也是可以發郵件的哦。不過本貓沒那麼任性,還是用KISS原則來發郵件吧。本篇博文只介紹了如何發郵件,但沒涉及收郵件的事,以後如有機會會單獨開一篇博文介紹。
ruby通過smtp發郵件有2種操作手段,一是直接用Net::SMTP來發送,比較底層。如果還要發送附件,則需要額外gem:mailfactory,而mailfactory又依賴於包mime-types。即便如此如果郵件伺服器串連需要ssl,則還需要require檔案smtp-tls.rb,而這個rb檔案需要openssl包的支援啊!第二種方法是直接使用高層的gem包mail,包含添加附件的功能,不過該gem也依賴於mime-types包,這個包專門用來描述郵件檔案格式的,俗稱多用途互連網郵件擴充類型啊。下面依次介紹下每種方法。
方法一:使用Net::SMTP
正常的非加密串連的smtp連接埠號碼為25,如果是加密則可能為587或465,要看具體的郵件伺服器的說明。開始用的是QQ的郵件伺服器,但老是不穩定,遂換為hotmail的,但hotmail需要ssl串連。按上面所述需要openssl包。麻煩開始了:rubygems.org用gem死活連不上,後來將openssl.gem直接下載到本地,用gem install -l openssl.gem安裝,發現require還是出錯,需要native ext:openssl.so動態庫擴充,進入openssl的ext原始碼目錄用make編譯提示出錯:Ignore OpenSSL broken by Apple,提示我用其他的openssl庫路徑,我用毛啊!是不支援Mac OS X嗎?但是檢查了系統中是安裝過openssl的:
/private/etc/openssl
/private/etc/openssl/cert.pem
/usr/bin/openssl
/usr/lib/pkgconfig/openssl.pc
/usr/local/Cellar/openssl
動態庫也是存在的,但不是ruby 的c_ext!
apple@kissAir: ruby_src$locate libssl.dylib
/Applications/Xcode6-Beta4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libssl.dylib
/Applications/Xcode6-Beta4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/libssl.dylib
/opt/com.bitaxis/lib/libssl.dylib
/opt/local/lib/libssl.dylib
/usr/lib/libssl.dylib
/usr/local/Cellar/openssl/1.0.1e/lib/libssl.dylib
神馬情況?考慮到tk對ruby的問題(見我另一篇在mac OS X下ruby使用tk的博文),我懷疑該ruby版本本身不支援原生openssl,這個版本是我在ruby-lang下載的ruby-2.1.5原始碼編譯並且安裝的!遂用rvm下載了其ruby-2.1.5版本,一試竟然可以鳥!但隨後發現hotmail.com的加密串連還是連不上,又換回QQ郵箱,用非加密的smtp,25連接埠串連。這回基本可以穩定發送了,如果換位163的郵箱測試發現更加穩定,上未重構的代碼:
#!/usr/bin/ruby#encoding:utf-8require 'net/smtp'require './smtp-tls.rb'require 'mailfactory'#Senders and Recipientsfrom_name = 'localhost'from_mail = '12345678@qq.com'to_name = 'ks'to_mail = '88888888@qq.com'#Servers and Authentication#smtp_host = 'smtp.qq.com'smtp_host = 'smtp.163.com'smtp_port = 25 #465 587 25#smtp_domain = 'qq.com'smtp_domain = 'localhost.localdomain'smtp_user = "wangyi@163.com"smtp_pwd = "xxxxxxxx"#smtp_user = "12345678@qq.com"#smtp_pwd = 'xxxxxxxx'#The subject and the messaget = Time.nowsubj = '1331 thinkpad test hopy'msg_body = "send msg from ruby.\n"#The date/time should look something like: Thu, 03 Jan 2006 12:33:22 -0700msg_date = t.strftime("%a, %d %b %Y %H:%M:%S +0800")#Compose the message for the email
#如果使用mailfactory發送則實際用不著msg格式了msg = <<END_OF_MESSAGEDate: #{msg_date}From: #{from_name} <#{from_mail}>To: #{to_name} <#{to_mail}>Subject: #{subj}#{msg_body} END_OF_MESSAGEmail = MailFactory.newmail.to = to_mailmail.from = from_mailmail.subject = subjmail.text = msg_bodymail.attach(File.expand_path("./mail.rb")) #發送附件#smtp = Net::SMTP.new(smtp_host,587)#smtp.enable_starttls#Net::SMTP.start(smtp_host, smtp_port, smtp_domain, smtp_user, smtp_pwd, :plain) do |smtp|Net::SMTP.start(smtp_host,smtp_port,smtp_domain, smtp_user, smtp_pwd, :login) do |smtp| #smtp.send_message msg, smtp_user, to_mail #mail.to = to_mail #puts smtp.methods #smtp.enable_starttls smtp.send_message(mail.to_s,smtp_user,to_mail)end
方法二:使用ruby gem:mail(未完待續)
mail是一個比較進階的郵件庫,包含了發送附件的功能。不過下載下來本地安裝後開始報錯提示refuse port 25之類的錯誤。開始我以為是許可權不夠,用sudo執行後,發現在執行require 'mail'命令時又報錯!發現當初安裝時未以sudo許可權安裝,先gem uninstall mail.gem,然後重新安裝:sudo gem install mail.gem,此時在sudo和普通許可權下require 'mail'都正常鳥:
#!/usr/bin/rubyrequire 'mail'smtp = { :address => 'smtp.163.com', :port => 25, :domain => '163.com', \:user_name => 'wangyi@163.com', :password => 'xxxxxxxx',\:enable_starttls_auto => true, :openssl_verify_mode => 'none' }Mail.defaults { delivery_method :smtp, smtp }mail = Mail.new do from 'wangyi@163.com' to '12345678@qq.com' subject 'test mail' body 'body:hello send mail way 2 :)' add_file File.expand_path("./mail2.rb")endmail.deliver!
有一個小問題,就是開始smtp中user_name和from裡設定的發送郵件賬戶不一樣,導致老是發送失敗,這裡都改成wangyi@163.com就可以了。但在方法一中可以不一樣哦。還有2種方法中domain改成’localhost‘等其他值也能發送成功,好像沒啥關係。
最後要說的是,2種方法都是用的非加密的方式串連,即郵件伺服器允許非ssl方式串連,如果郵件伺服器只能加密串連上面代碼就不能用。至於這時該如何寫代碼,若知道的各位童鞋請不吝賜教哦。