4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ruby-gmailにて、ある1日のメールを絞り込んで取得する

Last updated at Posted at 2014-08-25

ruby-gmailにて、ある1日のメールを絞り込んで取得するには、
:ONに当該日付を設定する。

:BEFOREや:AFTERに設定してはいけない。

:BEFOREと:AFTERに同一の日付を設定すると、絞り込みが行われなくなる。
厄介な仕様だ(´・д・`)

使い勝手が悪いので、コードを変更。
以下のような処理を挿入。

lib/gmail/mailbox.rb
if opts[:after] === opts[:before]
  opts[:on]     = opts[:before]
  opts[:after]  = nil
  opts[:before] = nil
end

ダメモトで本家にも、つたない英語で'Pull Request'投げてみたら、通った!!
やってみるもんだ。
Commits_·_dcparker_ruby-gmail.png

次回のバージョンからは反映させるだろう。

なお、コードの全貌は以下。

lib/gmail/mailbox.rb
require 'date'
require 'time'
class Object
  def to_imap_date
    Date.parse(to_s).strftime("%d-%B-%Y")
  end
end

class Gmail
  class Mailbox
    attr_reader :name

    def initialize(gmail, name)
      @gmail = gmail
      @name = name
    end

    def inspect
      "<#Mailbox name=#{@name}>"
    end

    def to_s
      name
    end

    # Method: emails
    # Args: [ :all | :unread | :read ]
    # Opts: {:since => Date.new}
    def emails(key_or_opts = :all, opts={})
      if key_or_opts.is_a?(Hash) && opts.empty?
        search = ['ALL']
        opts = key_or_opts
      elsif key_or_opts.is_a?(Symbol) && opts.is_a?(Hash)
        aliases = {
          :all => ['ALL'],
          :unread => ['UNSEEN'],
          :read => ['SEEN']
        }
        search = aliases[key_or_opts]
      elsif key_or_opts.is_a?(Array) && opts.empty?
        search = key_or_opts
      else
        raise ArgumentError, "Couldn't make sense of arguments to #emails - should be an optional hash of options preceded by an optional read-status bit; OR simply an array of parameters to pass directly to the IMAP uid_search call."
      end
      if !opts.empty?

        if opts[:after] === opts[:before]
          opts[:on]     = opts[:before]
          opts[:after]  = nil
          opts[:before] = nil
        end
        
        # Support for several search macros
        # :before => Date, :on => Date, :since => Date, :from => String, :to => String
        search.concat ['SINCE', opts[:after].to_imap_date] if opts[:after]
        search.concat ['BEFORE', opts[:before].to_imap_date] if opts[:before]
        search.concat ['ON', opts[:on].to_imap_date] if opts[:on]
        search.concat ['FROM', opts[:from]] if opts[:from]
        search.concat ['TO', opts[:to]] if opts[:to]
        search.concat ['SUBJECT', opts[:subject]] if opts[:subject]

        # Gmail offers us to search the same way we do on the web interface
        # https://developers.google.com/gmail/imap_extensions
        # example: gmail.emails(gm: 'has:attachment in:unread "who is john galt"')
        # 
        search.concat ['X-GM-RAW', opts[:gm]] if opts[:gm]
      end

      # puts "Gathering #{(aliases[key] || key).inspect} messages for mailbox '#{name}'..."
      @gmail.in_mailbox(self) do
        @gmail.imap.uid_search(search).collect { |uid| messages[uid] ||= Message.new(@gmail, self, uid) }
      end
    end

    # This is a convenience method that really probably shouldn't need to exist, but it does make code more readable
    # if seriously all you want is the count of messages.
    def count(*args)
      emails(*args).length
    end

    def messages
      @messages ||= {}
    end
  end
end
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?