rubyでGmailのfrom・subject・本文を読み込みたい(Net::IMAP編)
twitterへ流し込みたいので。
参考:
- Google サイト
- RubyでIMAPを使ってGMailにアクセスする | netswitch!
- Blogger
- IMAP4のコマンド一覧
- IMAP4のFETCHオプションの一覧
- class Net::IMAP (Ruby 1.9.3)
- module Kconv (Ruby 1.9.3)
初期設定
require 'net/imap' require 'kconv' imap = Net::IMAP.new('imap.gmail.com', 993, true) imap.login("foo@gmail.com, "********") imap.examine('INBOX')
Net::IMAP#select('INBOX')でも良いのだけど、読み取り専用のNet::IMAP#examine('INBOX')を使いました。
最新メールのUID確認
pry(main)> last_uid = imap.status('INBOX', ["MESSAGES"])["MESSAGES"] => 160229
最新メールのヘッダ読み取り
ただし上記のexamine以降に受信したメールは読み取れません。注意してください。
pry(main)> envelope = imap.fetch(last_uid, "ENVELOPE")[0].attr["ENVELOPE"] => #], sender= [# ], reply_to= [# ], to= [# ], cc=nil, bcc=nil, in_reply_to=nil, message_id="<201306182133.r5ILXrjg023268@bizml125.nikkeibp.co.jp>">
最新メールのヘッダの中身を取り出す
pry(main)> envelope.date => "Wed, 19 Jun 2013 06:33:53 +0900" pry(main)> envelope.subject.toutf8 => "[NEニュース NO.3773]シャープのセンサ、ジェスチャーと照度、近接の三つを検知" pry(main)> envelope.from envelope.from envelope.from= pry(main)> envelope.from[0].name.toutf8 => "日経エレクトロニクス" pry(main)> envelope.from[0].mailbox + "@" + envelope.from[0].host => "ne@nikkeibp.co.jp" pry(main)> envelope.to[0].mailbox + "@" + envelope.to[0].host => "ne@nikkeibp.co.jp" pry(main)> envelope.message_id => "<201306182133.r5ILXrjg023268@bizml125.nikkeibp.co.jp>"
文字数確認。
pry(main)> envelope.subject.toutf8.size => 43
foo@baa形式で取り出すメソッドmail_address_formatted
いちいち「envelope.from[0].mailbox + "@" + envelope.from[0].host」などと長いのを書くのが面倒だったので。
なお、Object#__send__メソッドは
Rubyist Magazine 出張版 正しいRubyコードの書き方講座―RubyistのRubyistによる、Rubyistとそうでない人のための
のp.222に載ってるのを昨夜読んで、使ってみたくなったので書いてみましたw
class Net::IMAP::Envelope def mail_address_formatted(value) return nil unless ["from", "sender", "reply_to", "to"].include?(value) self.__send__(value)[0].mailbox + "@" + self.__send__(value)[0].host end end
mail_address_formattedメソッドを使ってみる。
pry(main)> envelope.mail_address_formatted("from") => "ne@nikkeibp.co.jp" pry(main)> envelope.mail_address_formatted("reply_to") => "ne@nikkeibp.co.jp" pry(main)> envelope.mail_address_formatted("sender") => "ne@nikkeibp.co.jp" pry(main)> envelope.mail_address_formatted("to") => "ne@nikkeibp.co.jp"
文字数確認。
pry(main)> envelope.mail_address_formatted("from").size => 17
本文の冒頭1500バイトを"BODY[1]<0.1500>"で取得し、utf8に変換
pry(main)> imap.fetch(last_uid, "BODY[1]<0.1500>")[0].attr["BODY[1]<0>"].toutf8 => "****************************************************************************\r\n【NEニュース 2013年6月19日号】 No.3773\r\n 発信元◇日経BP社 日経エレクトロニクス編集\r\n http://techon.nikkeibp.co.jp/NE/?ref=ML\r\n****************************************************************************\r\n\r\n\r\n----------------------------------------------------------------------PR----\r\n 【動画で解説】自動車メーカー15社が採用するシーメンスの開発プラットフォーム\r\n\r\n http://h.nikkeibp.co.jp/h.jsp?no=060860 \r\n\r\nアンケートに答えて抽選で10名にAmazonギフト券5000円が当たるキャンペーン実施中\r\n----------------------------------------------------------------------------\r\n\r\n\r\nNEニュース/ ‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥\r\n◆目次◆\r\n‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥\r\n\r\n◆ニュース・ヘッドライン\r\nシャープ、ジェスチャーや照度/色合い、近接の検知が可能なセンサを発売へ\r\n「使い手がロボットを試し始めた」、“サービス・ロボット元年”の動向を聞く\r\nホンダ、HEV用電池のレアアースをモータに再利用\r\n\r\n◆NEブログ\r\n問題解決としての医療\r\n\r\n◆今日のコラム・解説\r\n【さらば端末ビジネス】第2回 消えるパソコン用ソフト\r\n\r\n◆日経エレクトロニクス/日経コミュニケーション主催セミナーのご案内\r\n「スマートWebコネク"
本文冒頭の装飾をgsubで落とす
pry(main)> imap.fetch(last_uid, "BODY[1]<0.1500>")[0].attr["BODY[1]<0>"].toutf8.gsub(/[ ‥…∴∵∞~−~――−─│└┴┼┘├┬┤┠┰┨┌┸╂┐━┃┗┻╋┛┣┳┫┝┯┥┏┷┿┓__/\+■□◆◇▲▼△▽★☆\*\=\+-]/, "").gsub(/ +/," ").gsub(/(\r\n)+/,"\n") => "\n【NEニュース2013年6月19日号】No.3773\n発信元日経BP社日経エレクトロニクス編集\nhttp://techon.nikkeibp.co.jp/NE/?refML\nPR\n 【動画で解説】自動車メーカー15社が採用するシーメンスの開発プラットフォーム\n http://h.nikkeibp.co.jp/h.jsp?no060860 \nアンケートに答えて抽選で10名にAmazonギフト券5000円が当たるキャンペーン実施中\nNEニュース \n目次\nニュース・ヘッドライン\nシャープ、ジェスチャーや照度/色合い、近接の検知が可能なセンサを発売へ\n「使い手がロボットを試し始めた」、“サービス・ロボット元年”の動向を聞く\nホンダ、HEV用電池のレアアースをモータに再利用\nNEブログ\n問題解決としての医療\n今日のコラム・解説\n【さらば端末ビジネス】第2回消えるパソコン用ソフト\n日経エレクトロニクス/日経コミュニケーション主催セミナーのご案内\n「スマートWebコネク"
本文テキストを"RFC822.TEXT"で取得し、utf8にし、装飾を落とし、冒頭500文字を取得
pry(main)> imap.fetch(last_uid, "RFC822.TEXT")[0].attr["RFC822.TEXT"].toutf8.gsub(/[ ‥…∴∵∞~−~――−─│└┴┼┘├┬┤┠┰┨┌┸╂┐━┃┗┻╋┛┣┳┫┝┯┥┏┷┿┓__/\+■□◆◇▲▼△▽★☆\*\=\+-]/, "").gsub(/ +/," ").gsub(/(\r\n)+/,"\n")[0..499] => "\n【NEニュース2013年6月19日号】No.3773\n発信元日経BP社日経エレクトロニクス編集\nhttp://techon.nikkeibp.co.jp/NE/?refML\nPR\n 【動画で解説】自動車メーカー15社が採用するシーメンスの開発プラットフォーム\n http://h.nikkeibp.co.jp/h.jsp?no060860 \nアンケートに答えて抽選で10名にAmazonギフト券5000円が当たるキャンペーン実施中\nNEニュース \n目次\nニュース・ヘッドライン\nシャープ、ジェスチャーや照度/色合い、近接の検知が可能なセンサを発売へ\n「使い手がロボットを試し始めた」、“サービス・ロボット元年”の動向を聞く\nホンダ、HEV用電池のレアアースをモータに再利用\nNEブログ\n問題解決としての医療\n今日のコラム・解説\n【さらば端末ビジネス】第2回消えるパソコン用ソフト\n日経エレクトロニクス/日経コミュニケーション主催セミナーのご案内\n「スマートWebコネクションズ2013」\nhttp://techon.nikkeibp.co.jp/seminar/130627.html\n日経エレクト"
Twitterでメールをお知らせするフォーマットにしてみる。
"subject《from》body"のフォーマット*1で文字数が140文字ぴったり。
URLの文字数はそのまま数えてます。変換が面倒だし、途中でぶった切ってるかもしれないから。
pry(main)> "#{envelope.subject.toutf8}《#{envelope.mail_address_formatted("from")}》#{imap.fetch(last_uid, "RFC822.TEXT")[0].attr["RFC822.TEXT"].toutf8.gsub(/[ ‥…∴∵∞―−~─│└┴┼┘├┬┤┠┰┨┌┸╂┐━┃┗┻╋┛┣┳┫┝┯┥┏┷┿┓_/\◎+■□◆◇▲▼△▽★☆\*\-\=\+]/, "").gsub(/ +/," ").gsub(/(\r\n)+/,"\n")[0..(140 - envelope.subject.toutf8.size - envelope.mail_address_formatted("from").size - 3)]}" => "[NEニュース NO.3773]シャープのセンサ、ジェスチャーと照度、近接の三つを検知《ne@nikkeibp.co.jp》\n【NEニュース2013年6月19日号】No.3773\n発信元日経BP社日経エレクトロニクス編集\nhttp://techon.nikkeibp.co.jp/"
twitterへ流すために
ツイートするフォーマットに変換するmail_to_tweetメソッド
class Net::IMAP def escape_chars Regexp.new("[ ‥…∴∵∞~−――−~─│└┴┼┘├┬┤┠┰┨┌┸╂┐━┃┗┻╋┛┣┳┫┝┯┥┏┷┿┓__/\◎+■□◆◇▲▼△▽★☆\*\-\=\+]") end def mail_to_tweet(uid) subject = self.fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"].subject.toutf8 from = self.fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"].from[0].mailbox + "@" + self.fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"].from[0].host escape_chars body = self.fetch(uid, "RFC822.TEXT")[0].attr["RFC822.TEXT"].toutf8.gsub(escape_chars, "").gsub(/・+/, "・").gsub(/ +/," ").gsub(/\(+/,"(").gsub(/\)+/,")").gsub(/(\r\n)+/,"\n") "#{subject}《#{from}》#{body[0..(140 - 1 - 2 - subject.size - from.size)]}" end end
mail_to_tweetメソッドを使ってみる。
pry(main)> imap.mail_to_tweet(last_uid) => "[NEニュース NO.3773]シャープのセンサ、ジェスチャーと照度、近接の三つを検知《ne@nikkeibp.co.jp》\n【NEニュース2013年6月19日号】No.3773\n発信元日経BP社日経エレクトロニクス編集\nhttp://techon.nikkeibp.co.jp/"
接続終了処理
imap.logout imap.disconnect
*1:いちいちメソッドチェーンで書くよりも変数に入れた方がいい?その通りですよw 単にpryで実験してるだけですw