Class: Gmail::Mailbox

Inherits:
Object show all
Defined in:
lib/gmail/mailbox.rb

Constant Summary collapse

MAILBOX_ALIASES =
{
  :all       => ['ALL'],
  :seen      => ['SEEN'],
  :unseen    => ['UNSEEN'],
  :read      => ['SEEN'],
  :unread    => ['UNSEEN'],
  :flagged   => ['FLAGGED'],
  :unflagged => ['UNFLAGGED'],
  :starred   => ['FLAGGED'],
  :unstarred => ['UNFLAGGED'],
  :deleted   => ['DELETED'],
  :undeleted => ['UNDELETED'],
  :draft     => ['DRAFT'],
  :undrafted => ['UNDRAFT']
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(gmail, name = "INBOX") ⇒ Mailbox

Returns a new instance of Mailbox


22
23
24
25
26
# File 'lib/gmail/mailbox.rb', line 22

def initialize(gmail, name = "INBOX")
  @name = Net::IMAP.decode_utf7(name)
  @encoded_name = Net::IMAP.encode_utf7(name)
  @gmail = gmail
end

Instance Attribute Details

#encoded_nameObject (readonly)

Returns the value of attribute encoded_name


20
21
22
# File 'lib/gmail/mailbox.rb', line 20

def encoded_name
  @encoded_name
end

#nameObject (readonly)

Returns the value of attribute name


19
20
21
# File 'lib/gmail/mailbox.rb', line 19

def name
  @name
end

Instance Method Details

#count(*args) ⇒ Object

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.

Examples

gmail.inbox.count(:all)
gmail.inbox.count(:unread, :from => "[email protected]")
gmail.mailbox("Test").count(:all, :after => Time.now-(20*24*3600))

112
113
114
# File 'lib/gmail/mailbox.rb', line 112

def count(*args)
  emails(*args).size
end

#emails(*args, &block) ⇒ Object Also known as: search, find

Returns list of emails which meets given criteria.

Examples

gmail.inbox.emails(:all)
gmail.inbox.emails(:unread, :from => "[email protected]")
gmail.inbox.emails(:all, :after => Time.now-(20*24*3600))
gmail.mailbox("Test").emails(:read)

gmail.mailbox("Test") do |box|
  box.emails(:read)
  box.emails(:unread) do |email|
    ... do something with each email...
  end
end

74
75
76
77
78
79
80
# File 'lib/gmail/mailbox.rb', line 74

def emails(*args, &block)
  fetch_uids(*args).collect do |uid|
    message = Message.new(self, uid)
    yield(message) if block_given?
    message
  end
end

#emails_in_batches(*args, &block) ⇒ Object Also known as: search_in_batches, find_in_batches


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/gmail/mailbox.rb', line 84

def emails_in_batches(*args, &block)
  messages = Array.new

  uids = fetch_uids(*args)
  if uids && uids.any?
    uids.each_slice(100) do |slice|
      @gmail.conn.uid_fetch(slice, Message::PREFETCH_ATTRS).each do |data|
        message = Message.new(self, nil, data)
        yield(message) if block_given?
        messages << message
      end
    end
  end

  messages
end

#expungeObject

This permanently removes messages which are marked as deleted


117
118
119
# File 'lib/gmail/mailbox.rb', line 117

def expunge
  @gmail.mailbox(name) { @gmail.conn.expunge }
end

#fetch_uids(*args) ⇒ Object


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/gmail/mailbox.rb', line 28

def fetch_uids(*args)
  args << :all if args.size == 0

  if args.first.is_a?(Symbol)
    search = MAILBOX_ALIASES[args.shift].dup
    opts = args.first.is_a?(Hash) ? args.first : {}

    opts[:after]      and search.concat ['SINCE', opts[:after].to_imap_date]
    opts[:before]     and search.concat ['BEFORE', opts[:before].to_imap_date]
    opts[:on]         and search.concat ['ON', opts[:on].to_imap_date]
    opts[:from]       and search.concat ['FROM', opts[:from]]
    opts[:to]         and search.concat ['TO', opts[:to]]
    opts[:subject]    and search.concat ['SUBJECT', opts[:subject]]
    opts[:label]      and search.concat ['LABEL', opts[:label]]
    opts[:attachment] and search.concat ['HAS', 'attachment']
    opts[:search]     and search.concat ['BODY', opts[:search]]
    opts[:body]       and search.concat ['BODY', opts[:body]]
    opts[:uid]        and search.concat ['UID', opts[:uid]]
    opts[:gm]         and search.concat ['X-GM-RAW', opts[:gm]]
    opts[:query]      and search.concat opts[:query]

    @gmail.mailbox(name) do
      @gmail.conn.uid_search(search)
    end
  elsif args.first.is_a?(Hash)
    fetch_uids(:all, args.first)
  else
    raise ArgumentError, "Invalid search criteria"
  end
end

#inspectObject


161
162
163
# File 'lib/gmail/mailbox.rb', line 161

def inspect
  "#<Gmail::Mailbox#{'0x%04x' % (object_id << 1)} name=#{name}>"
end

#to_sObject


165
166
167
# File 'lib/gmail/mailbox.rb', line 165

def to_s
  name
end

#wait(options = {}, &block) ⇒ Object


121
122
123
124
125
# File 'lib/gmail/mailbox.rb', line 121

def wait(options = {}, &block)
  loop do
    wait_once(options, &block)
  end
end

#wait_once(options = {}) {|response| ... } ⇒ Object

Yields:

  • (response)

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/gmail/mailbox.rb', line 127

def wait_once(options = {})
  options[:idle_timeout] ||= 29 * 60

  response = nil
  loop do
    complete_cond = @gmail.conn.new_cond
    complete_now = false

    @gmail.conn.idle do |resp|
      if resp.is_a?(Net::IMAP::ContinuationRequest) && resp.data.text == 'idling'
        Thread.new do
          @gmail.conn.synchronize do
            complete_cond.wait(options[:idle_timeout]) unless complete_now
            @gmail.conn.idle_done
          end
        end
      elsif resp.is_a?(Net::IMAP::UntaggedResponse) && resp.name == 'EXISTS'
        response = resp

        @gmail.conn.synchronize do
          complete_now = true
          complete_cond.signal
        end
      end
    end

    break if response
  end

  yield response if block_given?

  nil
end