class MailRoom::Connection

Public Class Methods

new(mailbox) click to toggle source
# File lib/mail_room/connection.rb, line 3
def initialize(mailbox)
  @mailbox = mailbox

  # log in and set the mailbox
  reset
  setup
end

Public Instance Methods

disconnected?() click to toggle source

is the imap connection closed? @return [Boolean]

# File lib/mail_room/connection.rb, line 29
def disconnected?
  @imap.disconnected?
end
idling?() click to toggle source

is the connection blocked idling? @return [Boolean]

# File lib/mail_room/connection.rb, line 23
def idling?
  @idling
end
logged_in?() click to toggle source

is the connection logged in? @return [Boolean]

# File lib/mail_room/connection.rb, line 17
def logged_in?
  @logged_in
end
on_new_message(&block) click to toggle source
# File lib/mail_room/connection.rb, line 11
def on_new_message(&block)
  @new_message_handler = block
end
quit() click to toggle source
# File lib/mail_room/connection.rb, line 39
def quit
  stop_idling
  reset
end
ready_to_idle?() click to toggle source

is the connection ready to idle? @return [Boolean]

# File lib/mail_room/connection.rb, line 35
def ready_to_idle?
  logged_in? && !idling?
end
wait() click to toggle source
# File lib/mail_room/connection.rb, line 44
def wait
  begin
    # in case we missed any between idles
    process_mailbox

    idle

    process_mailbox
  rescue Net::IMAP::Error, IOError
    reset
    setup
  end
end

Private Instance Methods

idle() click to toggle source

maintain an imap idle connection

# File lib/mail_room/connection.rb, line 106
def idle
  return unless ready_to_idle?

  @idling = true

  imap.idle(@mailbox.idle_timeout, &idle_handler)
ensure
  @idling = false
end
idle_handler() click to toggle source

@private

# File lib/mail_room/connection.rb, line 101
def idle_handler
  lambda {|response| imap.idle_done if message_exists?(response)}
end
imap() click to toggle source

build a net/imap connection to google imap

# File lib/mail_room/connection.rb, line 73
def imap
  @imap ||= MailRoom::IMAP.new(@mailbox.host, :port => @mailbox.port, :ssl => @mailbox.ssl_options)
end
log_in() click to toggle source

send the imap login command to google

# File lib/mail_room/connection.rb, line 83
def log_in
  imap.login(@mailbox.email, @mailbox.password)
  @logged_in = true
end
message_exists?(response) click to toggle source

is the response for a new message? @param response [Net::IMAP::TaggedResponse] the imap response from idle @return [Boolean]

# File lib/mail_room/connection.rb, line 96
def message_exists?(response)
  response.respond_to?(:name) && response.name == 'EXISTS'
end
messages_for_ids(uids) click to toggle source

@private fetch the email for all given ids in RFC822 format @param ids [Array<Integer>] list of message ids @return [Array<Net::IMAP::FetchData>] the net/imap messages for the given ids

# File lib/mail_room/connection.rb, line 168
def messages_for_ids(uids)
  return [] if uids.empty?

  # uid_fetch marks as SEEN, will not be re-fetched for UNSEEN
  imap.uid_fetch(uids, "RFC822")
end
new_message_ids() click to toggle source

@private search for all new (unseen) message ids @return [Array<Integer>] message ids

# File lib/mail_room/connection.rb, line 159
def new_message_ids
  # uid_search still leaves messages UNSEEN
  imap.uid_search(@mailbox.search_command).select { |uid| @mailbox.deliver?(uid) }
end
new_messages() click to toggle source

@private fetch all messages for the new message ids

# File lib/mail_room/connection.rb, line 146
def new_messages
  # Both of these calls may results in
  #   imap raising an EOFError, we handle
  #   this exception in the watcher
  messages_for_ids(new_message_ids)
end
process_mailbox() click to toggle source
# File lib/mail_room/connection.rb, line 126
def process_mailbox
  return unless @new_message_handler

  msgs = new_messages

  msgs.
    map(&@new_message_handler). # deliver each new message, collect success
    zip(msgs). # include messages with success
    select(&:first).map(&:last). # filter failed deliveries, collect message
    each {|message| scrub(message)} # scrub delivered messages
end
reset() click to toggle source
# File lib/mail_room/connection.rb, line 60
def reset
  @imap = nil
  @logged_in = false
  @idling = false
end
scrub(message) click to toggle source
# File lib/mail_room/connection.rb, line 138
def scrub(message)
  if @mailbox.delete_after_delivery
    imap.store(message.seqno, "+FLAGS", [Net::IMAP::DELETED])
  end
end
set_mailbox() click to toggle source

select the mailbox name we want to use

# File lib/mail_room/connection.rb, line 89
def set_mailbox
  imap.select(@mailbox.name) if logged_in?
end
setup() click to toggle source
# File lib/mail_room/connection.rb, line 66
def setup
  start_tls
  log_in
  set_mailbox
end
start_tls() click to toggle source

start a TLS session

# File lib/mail_room/connection.rb, line 78
def start_tls
  imap.starttls if @mailbox.start_tls
end
stop_idling() click to toggle source

trigger the idle to finish and wait for the thread to finish

# File lib/mail_room/connection.rb, line 117
def stop_idling
  return unless idling?

  imap.idle_done
  
  # idling_thread.join
  # self.idling_thread = nil
end