GMailの読み込み

出張であちこち移動している間に、GMailの読み込み処理がバッチでできるように少しソースを書いてみた。

ザックリと作ったので、まだかっこわるいが、私のスキルだとこんなもの(笑)。

使い方としては、以下の感じ。文字は全てUTF-8で処理して、時刻とかはTimeクラスに変換してある。

 conn = GMail.connect("id","pass")
 conn.search.each do |mail|
    mail.subject
    mail.body
    mail.from
    mail.to
    mail.date
    mail.id
 end
 conn.dissconect


検索がunseen固定になっていて、もっとほかの検索方法があるとおもうんだけど、IMAPに詳しくないので、その辺は調査中。あと、各クラス間で@imapオブジェクトを渡しまくってるのがかなりかっこわるいんだけど、作るのが簡単だったということで、とりあえず放置中。もうちょっときれいにできるといいんだけどな。

以下が作ってみたソース。

require "net/imap"
require "kconv"
require "time"
	
class GMail
  GMAIL_SERVER = {:server=>"imap.gmail.com",:port=>993,:ssl=>true}
  SEARCH_TYPR  = {:unseen=>"UNSEEN",:recent=>"RECENT"}
  class Data
    attr_reader :subject,:body,:from,:to,:date,:mailid
    def initialize(subject,body,from,to,date,id)
                   @subject = subject.toutf8
                   @body    = body.toutf8
                   @from    = from.toutf8
                   @to      = to.toutf8
                   @date    = Time.parse(date)
                   @mailid  = id;
    end
  end
=begin
  GMailから受信したメールIDのリストを格納し、指示に応じてメールの実受信を行う
=end
  class List
    def initialize(imap,list)
      @imap = imap
      @list = list ? list : []
    end
    def size
      @list.size
    end
    def each
      @list.each do |id|
        yield(create_mail_data(id))
      end
    end
    def [](pos)
      return create_mail_data(@list[pos])
    end
    private
    def create_mail_data(mail_id)
      env  = @imap.fetch(mail_id,"ENVELOPE")[0].attr["ENVELOPE"]
      body = @imap.fetch(mail_id,"BODY[TEXT]")[0].attr["BODY[TEXT]"]	
      from_addr = env.from[0].mailbox.to_s + "@" + env.from[0].host.to_s
      to_addr   = env.to[0].mailbox.to_s + "@" + env.to[0].host.to_s
      gm = GMail::Data.new(env.subject,
                           body,
                           from_addr,
                           to_addr,
                           env.date,
                           mail_id
                           )
    end
  end
  class Conn
    def initialize(imap)
      @imap = imap
    end
    def search(search_type=:unseen)
      @imap.select("INBOX")
      mail_ids = @imap.search(SEARCH_TYPR[search_type])
      GMail::List.new(@imap,mail_ids)
    end
    def logout()
      if nil != @imap
        begin
          @imap.logout()
          @imap.disconeect()
	rescue
        #保留
	ensure
          @imap = nil
	end
      end
    end
    alias disconnect logout
  end
=begin
GMail処理全体を管理。GMailへの接続を行いコネクションオブジェクトを作成する
=end
  def initialize(id,pass)
    self.connect(id,pass)
  end
  def self.connect(id,pass)
    imap = Net::IMAP.new(GMAIL_SERVER[:server],GMAIL_SERVER[:port],GMAIL_SERVER[:ssl])
    begin
      imap.login(id,pass)
    rescue Net::IMAP::NoResponseError
      raise "Login Failed"
    end
    GMail::Conn.new(imap)
  end
end