twitterのフォロー通知メールとか、Amazonの発送通知メールとか、そういうメールを受け取ったらその内容に応じていろいろ処理したい時ってありますよね。
でもまあ、今時個人でメールサーバ立てるのなんて流行らないですし、自由にprocmailを仕込むわけにもいかないですよね。というわけでGmailのIMAPを使いましょう。
rubyで書くとこんな感じ。
require 'rubygems' require 'net/imap' require 'kconv' require 'pit' require 'logger' class ImapFetcher def initialize(pit_name) @pit = Pit.get( pit_name, :require=>{ 'host'=>'imap.gmail.com', 'port'=>993, 'use_ssl'=>'true', 'login'=>'', 'password'=>'' } ) end def logger unless @logger @logger = Logger.new(STDOUT) @logger.level = Logger::DEBUG end @logger end def logger=(logger) @logger = logger end def fetch(filter) mails = [] begin # GmailにIMAPで接続、ログインする @imap = Net::IMAP.new( @pit['host'], @pit['port'].to_i, @pit['use_ssl']=='true' ) logger.debug 'IMAP.new' @imap.login( @pit['login'], @pit['password'] ) # ID、パスワード logger.debug "IMAP LOGIN #{@pit['login'].inspect}" # 受信箱を開く @imap.select( 'INBOX' ) logger.debug 'IMAP SELECT INBOX' # メールを開く logger.debug "IMAP SEARCH #{filter.inspect}" @imap.search( filter ).each do | msg_id | logger.debug "FOUND msg_id:#{msg_id.inspect}" # 本文を取得する fetch_attr = '(UID RFC822.SIZE ENVELOPE BODY[HEADER] BODY[TEXT])' msg = @imap.fetch( msg_id, fetch_attr ).first logger.debug "IMAP FETCH #{msg_id.inspect} #{fetch_attr.inspect}" fetched_mail = { :body => msg.attr['BODY[TEXT]'].toutf8, :header => msg.attr['BODY[HEADER]'].toutf8 } mails.push fetched_mail logger.debug "PUSHED #{fetched_mail[:header][/^Subject:.*$/]}" # 既読のフラグを立てる @imap.store( msg_id, '+FLAGS', [:Seen] ) logger.debug "IMAP STORE #{msg_id.inspect} +FLAGS SEEN" #@imap.store( msg_id, '+FLAGS', [:Deleted] ) end # フラグを反映 @imap.expunge logger.debug "IMAP EXPUNGE" rescue Object=>e raise e # 例外処理 ensure # 切断する @imap.logout logger.debug "IMAP LOGOUT" #@imap.disconnect #logger.debug "IMAP DISCONNECT" end mails end end
使い方
Pitがなければ
$ gem install pit
する。
そんで ruby からは
imap = ImapFetcher.new('imap_fetcher_test') mails = imap.fetch(['FROM', 'hogehoge@example.com', 'UNSEEN']) pp mails
こんな感じ。
mailsには「hogehoge@example.com」から送られてきた未読メールのheaderとbodyがハッシュの配列になって入る。
IMAP FETCH のフィルターとしてUNSEENを指定しているので、未読メールのみが取得される。
ここで取得したメールには既読フラグを書き込んでいるので次回以降は取得されない。
github(gist)にも上げた。
imap_fetcher.rb
参考文献
- RFC3501
- http://tools.ietf.org/html/rfc3501
- IMAP4 rev1 の仕様。
- Ruby on Gmail (App2u)
- http://blog.app2u.jp/index/ruby/ruby-gmail
- こちらのコードをほぼ真似させていただきました。この場を借りてお礼申し上げます。
- logoutしたあとにdissconnectするとなぜかエラーになったのでコメントアウトした。