使用Ruby收發郵件

來源:互聯網
上載者:User
 

1。通過SMTP發送Email

每星期Holden Glova, Pat Eyler, 和 Phil Thomson都會向Ruby Garden 網站(http://www.rubygarden.org)提交一個Ruby Weekly News (RWN)文章。一個Ruby指令碼通過email接收這篇文章,將它從原來的xml格式轉換為HTML和純文字格式,然後將HTML格式的發表到網站,然後將純文字格式的文章發到郵件清單。如果這中間出現什麼問題(比如xml文檔結構不對等),這個指令碼將向寄件者發送一封包含錯誤資訊的email。

這個指令碼用Net::SMTP (Simple Mail Transfer Protocol) 庫發送email。清單 1 是這個指令碼中用來發送email的方法,這個方法接收3個參數:email地址,標題,和信件內容。因為這個程式要在各種控制環境下使用,所以一些類似寄件者,轉寄email的主機等屬性都定義為全域常量,而不是參數。

清單 1: 通過SMTP發送郵件

 1   FROM_ADDRESS = "dave@pragprog.com" 2   SMTP_HOST = "localhost" 3 4   def reply(to, subject, msg) 5     mail = "To: #{to}/r/n" + 6            "From: #{FROM_ADDRESS}/r/n" + 7            "Subject: #{subject}/r/n" + 8            "/r/n" + 9            msg1011     Net::SMTP.start(SMTP_HOST) do |smtp|12       smtp.send_mail(mail, FROM_ADDRESS,13         [ to, 'rurl_archive@zip.local.pragprog.com' ])14     end15   end

一個email訊息由兩部分組成:信封(envelope)和內容(content)。信封告訴SMTP代理(sendmail或者postfix)如何投遞訊息。內容包括能被人們閱讀的訊息本身和一些標題(header)(比如訊息subject),而一些內容中的header可能和envelope中的重複(比如"To"地址),這些重複的header用來顯示時候使用,而envelope中的則是用來投遞使用。(這也是為什麼你會收到"To"地址不是你的垃圾郵件)

你可以看到reply方法已經分離了envelop和content,第5行到第9行產生了content,它包括3個header:To,From,Subject,然後在一個空行後面加上了訊息內容。注意郵件主體內容之前的header之後必須有一個斷行符號換行,即"/r"和"/n"的組合。

方法Net::SMTP.start來和MTA( mail transfer agent)建立串連,這個方法的一個參數是運行MTA的機器名稱,並且使用了預設連接埠(25),這個方法返回一個對象用來和MTA互動,並且把這個對象作為參數傳給了block(11行到13行)。使用block,能保證block結束後串連能夠被關閉。

在我們的例子裡,這個互動過程很簡單,第12行的程式只是發送了剛才傳劍的郵件內容。

send_mail方法的第二個參數是使用的From地址,這是一個全域變數。第三個參數是一個包含接收者地址的數組。我們這裡把這條訊息發送到了兩個地方,一個參數指定的to,還有一個歸檔所有訊息的本地郵箱。

 


2。用POP接收和閱讀郵件

使用Ruby從POP伺服器內送郵件是非常簡單的事情。假設我們要對人們對各種語言的喜愛程度,參加調查的人可以通過發送標題為i like xxxxx的郵件給特定的地址,xxxxx是發信者喜歡的語言的名字。清單3的Ruby指令碼用來從POP伺服器接收結果並進行計算,把每種語言的喜愛者的數目存在一個普通檔案,每種語言一個檔案。

 

清單3: Fetching email with POP

 1   require 'net/pop' 2 3   Net::POP3.delete_all('pop3.server.address', 110, 4                        'YourAccount', 'YourPassword' ) do |email| 5     hdr = email.header 6     if hdr =~ /Subject:/s+I like/s+(/w+)/ 7       language = $1.upcase 8     else 9       language = "INVALID"10     end1112     count = (File.read(language) rescue "0")13     File.open(language, "w") {|f| f.puts old_count.succ}14   end

POP伺服器存放著使用者的訊息,當你讀完一條訊息的時候,你可以選擇刪除這封信,或者還把它放在伺服器上存放,在我們的例子裡,我們讀完之後將刪除它。幸運的是,Ruby提供了一個很方便的迭代器delete_all,它將一條條的取出郵件,處理完之後刪掉這些信件。delete_all需要的參數有POP伺服器的地址和連接埠(標準連接埠為110),還有使用者名稱和密碼。

這個方法開始之後將用指定的參數串連伺服器,一封一封的取得該使用者的郵件,然後每次將這封信(作為一個Net::POPMail對象)傳給給定的block來處理,當block處理完這封信之後,將刪除這封信。

在這個塊內,第5行將這封信的所有header都取出來放到一個字串當中。然後在第6行中用一個Regex在標題(Subject)中尋找類似的包括的I like xxxx 行,找出xxxx代表的語言,然後在12和13行中對找到的投票者選擇的語言的計數進行更新。

 

第12行有一個很有意思的結構。每次我們得到一個給某種語言的投票,我們都用一個檔案來儲存這個語言得到的投票數。我們可以讀取這個值,增加它,然後寫回到檔案。但是第一次有人給某個語言投票時,這個檔案還不存在,當我們讀取這個檔案時會得到一個異常,很幸運Ruby提供了一個異常機制(關鍵字rescue),但出現異常的時候可能是因為檔案不存在,所以捕獲這個異常,返回一個預設值0,即這個語言的得票數為0。

另一個小技巧是第13行的old_count.succ,我們用這個來增加一個字串。在Ruby中這是允許的,如果一個字串包含的是一個整數,那麼這個succ方法返回的是這個包含這個整數的下一個值的字串。即aString.succ=aString.to_i.succ.to_s 。

譯者註:old_count.succ可能應該是count.succ

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.