module Gmail class Mailbox 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'] }.freeze attr_reader :name attr_reader :encoded_name def initialize(gmail, name = "INBOX") @name = Net::IMAP.decode_utf7(name) @encoded_name = Net::IMAP.encode_utf7(name) @gmail = gmail end def fetch_uids(*args) args << :all if args.empty? 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', Net::IMAP.format_date(opts[:after])] opts[:before] and search.concat ['BEFORE', Net::IMAP.format_date(opts[:before])] opts[:on] and search.concat ['ON', Net::IMAP.format_date(opts[:on])] 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[:message_id] and search.concat ['X-GM-MSGID', opts[:message_id].to_s] 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 # Returns list of emails which meets given criteria. # # ==== Examples # # gmail.inbox.emails(:all) # gmail.inbox.emails(:unread, :from => "friend@gmail.com") # 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 def emails(*args, &block) fetch_uids(*args).collect do |uid| message = Message.new(self, uid) yield(message) if block_given? message end end alias :search :emails alias :find :emails def emails_in_batches(*args, &block) return [] unless uids.is_a?(Array) && uids.any? uids.each_slice(100).flat_map do |slice| find_for_slice(slice, &block) end end alias :search_in_batches :emails_in_batches alias :find_in_batches :emails_in_batches # 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 => "friend@gmail.com") # gmail.mailbox("Test").count(:all, :after => Time.now-(20*24*3600)) def count(*args) emails(*args).size end # This permanently removes messages which are marked as deleted def expunge @gmail.mailbox(name) { @gmail.conn.expunge } end def wait(options = {}, &block) loop do wait_once(options, &block) end end 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 def inspect "#" end def to_s name end MAILBOX_ALIASES.each_key do |mailbox| define_method(mailbox) do |*args, &block| emails(mailbox, *args, &block) end end private def find_for_slice(slice, &block) @gmail.conn.uid_fetch(slice, Message::PREFETCH_ATTRS).map do |data| message = Message.new(self, nil, data) yield(message) if block_given? message end end end # Message end # Gmail