Project

General

Profile

« Previous | Next » 

Revision e279cb2a

Added by Marc Dequènes almost 13 years ago

  • ID e279cb2a35cd77522e283b0feef6c555a93b8da2

[fix] IMAP: better handle IDLE sessions, process BYE messages from server, and add disconnection detection as Net::IMAP seems not to send BYE messages everytime it should

View differences:

lib/cyborghood/imap.rb
@config = Config.instance
@imap = nil
@is_loggued = false
@need_reconnect = false
@available_mails = 0
@available_mails_mutex = Mutex.new
......
true
end
def connected?
return false if @imap.nil?
return false if @need_reconnect
not @imap.disconnected?
end
def authenticate
raise CyberError.new(:unrecoverable, "fixme", "Trying to authenticate to the IMAP server, but we are not connected yet") unless @imap
......
def listen_to_events
@imap.add_response_handler do |resp|
logger.debug "IMAP event: " + resp.inspect if @config.debug.flags.include?('debug_imapverbose')
if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
@available_mails_mutex.synchronize do
@available_mails = resp.data.to_i
logger.debug "*** Received new mails (#{@available_mails})" if @available_mails > 0
if resp.kind_of?(Net::IMAP::UntaggedResponse)
case resp.name
when "EXISTS"
@available_mails_mutex.synchronize do
@available_mails = resp.data.to_i
logger.debug "*** Received new mails (#{@available_mails})" if @available_mails > 0
end
when "BYE"
@need_reconnect = true
logger.debug "IMAP reconnection needed"
end
end
end
......
if self.capabilities.include?("IDLE")
logger.debug "Waiting for new mails in idle mode"
@imap.idle
sleep(1) until @stop_mail_check or waiting_mails?
@imap.idle_done
until @stop_mail_check
return if @imap.nil? or not connected?
@imap.idle
# restart IDLE after 5 min
t = Time.now.to_i
sleep(1) until Time.now.to_i - t >= 300 or @stop_mail_check or waiting_mails?
@imap.idle_done
end
end
end
end
......
t2 = Time.now.to_i
sleep_time = @min_check_interval - (t2 - t)
rescue SocketError, Errno::EPIPE, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::ENETUNREACH => e
rescue SocketError, Errno::EPIPE, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::ENETUNREACH, IOError => e
logger.warn "Network error: " + e.message.strip
sleep_time = @min_check_interval
end
......
end
def check_inbox(&message_handler)
return unless @imap
logger.debug "Examining INBOX"
@imap.select('INBOX')
......
return unless @imap
begin
@imap.logout if @is_loggued
unless @imap.disconnected?
@imap.logout if @is_loggued
logger.debug "Disconnecting from IMAP server..."
@imap.disconnect
logger.debug "Disconnected from IMAP server"
logger.debug "Disconnecting from IMAP server..."
@imap.disconnect
logger.debug "Disconnected from IMAP server"
end
rescue IOError
logger.debug "Already diconnected from IMAP server"
logger.debug "Already disconnected from IMAP server"
ensure
@imap = nil
@is_loggued = false
@imap_capab = nil
@need_reconnect = false
end
end
end

Also available in: Unified diff