class IMAPMail(SMTPEmailAccount): protocol = 'imap' max_fetch = 25 # will only fetch contents for the last max_fetch messages default_port = 143 default_ssl_port = 993 default_timeout = 20 opening_email_marks_as_read = False def __init__(self, **options): d = self.default log.info("imap options: %r", options) self.imapserver = options.get('imapserver') self.require_ssl = options.get('require_ssl', d('require_ssl')) self.imapport = options.get('imapport', d('default_ssl_port') if self.require_ssl else d('imapport')) self.timeouttimer = ResetTimer(pref('imap.timeout', self.default_timeout), self.timeout_check) from mail.imapcheck import IMAPCheck self.imap = IMAPCheck(self.max_fetch) self.cmdq = CommandQueue([], [], 30, 1) #print 'IMAPMail:', repr(options['name']), repr(options['password']) SMTPEmailAccount.__init__(self, **options) can_has_preview = True def update(self): SMTPEmailAccount.update(self) info('starting timeout timer') self.timeouttimer.start() self.real_update(success = self.finish_update, error = self.on_error) def finish_update(self, result): self.error_count = 0 if isinstance(result, tuple): count, emails = result self._received_emails(emails, count) else: log.warning('finish_update expects a tuple, got a %s: %r', type(result), result) info('stopping timeout timer') self.timeouttimer.stop() @callback_cmdqueue() def real_update(self): password = self._decryptedpw() if isinstance(password, unicode): password = password.encode('utf-8') self.imap.login(self.imapserver, self.imapport, self.require_ssl, self.name, password) if self.state == self.Statuses.OFFLINE: if self.offline_reason == self.Reasons.NONE: return else: raise Exception try: result = self.imap.update() except AuthenticationError, e: traceback.print_exc() return self.bad_pw() return result
class IMAPMail(SMTPEmailAccount): protocol = 'imap' max_fetch = 25 # will only fetch contents for the last max_fetch messages default_port = 143 default_ssl_port = 993 default_timeout = 20 opening_email_marks_as_read = False def __init__(self, **options): d = self.default log.info("imap options: %r", options) self.imapserver = options.get('imapserver') self.require_ssl = options.get('require_ssl', d('require_ssl')) self.imapport = options.get( 'imapport', d('default_ssl_port') if self.require_ssl else d('imapport')) self.timeouttimer = ResetTimer( pref('imap.timeout', self.default_timeout), self.timeout_check) from mail.imapcheck import IMAPCheck self.imap = IMAPCheck(self.max_fetch) self.cmdq = CommandQueue([], [], 30, 1) #print 'IMAPMail:', repr(options['name']), repr(options['password']) SMTPEmailAccount.__init__(self, **options) can_has_preview = True def update(self): SMTPEmailAccount.update(self) info('starting timeout timer') self.timeouttimer.start() self.real_update(success=self.finish_update, error=self.on_error) def finish_update(self, result): self.error_count = 0 if isinstance(result, tuple): count, emails = result self._received_emails(emails, count) else: log.warning('finish_update expects a tuple, got a %s: %r', type(result), result) info('stopping timeout timer') self.timeouttimer.stop() @callback_cmdqueue() def real_update(self): password = self._decryptedpw() if isinstance(password, unicode): password = password.encode('utf-8') self.imap.login(self.imapserver, self.imapport, self.require_ssl, self.name, password) if self.state == self.Statuses.OFFLINE: if self.offline_reason == self.Reasons.NONE: return else: raise Exception try: result = self.imap.update() except AuthenticationError, e: traceback.print_exc() return self.bad_pw() return result
class PopMail(SMTPEmailAccount): protocol = 'pop' default_timeout = 20 opening_email_marks_as_read = False def __init__(self, **options): d = self.default self.popserver = options.get('popserver', '') self.require_ssl = options.get('require_ssl', d('require_ssl')) self.popport = options.get('popport', d('popport')) self.uidlworks = None self.topworks = True #assume it does until proven otherwise self.cmdq = CommandQueue(start_hooks=[self._connect], end_hooks=[self._quit]) self.timeouttimer = ResetTimer( pref('pop.timeout', self.default_timeout), self.timeout_check) SMTPEmailAccount.__init__(self, **options) can_has_preview = True def timeout_check(self): log.info('Checking server connection for %r', self) if self.state in (self.Statuses.OFFLINE, self.Statuses.ONLINE): log.info('%s is not currently checking', self) return True if get(self, 'conn', False): try: self.conn.noop() except: self.on_error() log.error('%s\'s server connection has failed', self) return False else: log.error('%s has no conn attribute', self) self.on_error() return False def update(self): SMTPEmailAccount.update(self) log.info('starting timeout timer') self.timeouttimer.start() self.real_update(success=self.finish_update) def finish_update(self, updates): import time if self.state == self.Statuses.OFFLINE: log.error('finish_update exiting early, state is %s', self.state) return (updated_emails, updated_count) = updates log.info("%s got %d new messages %s", self, updated_count, time.ctime(time.time())) #self.change_state(self.Statuses.ONLINE) self._received_emails(updated_emails[:25], updated_count) # if self.state in (self.Statuses.CONNECTING, self.Statuses.CHECKING): # self.change_state(self.Statuses.ONLINE) self.error_count = 0 log.info('stopping timeout timer') self.timeouttimer.stop() @callback_cmdqueue() def real_update(self): #self.change_state(self.Statuses.CHECKING) if self.state == self.Statuses.OFFLINE: return conn = self.conn num_emails, box_size = conn.stat() num_emails = int(num_emails) emails = [] def retr(mid): if self.topworks: try: return conn.top(mid, 100) except: self.topworks = False return conn.retr(mid) uidl = conn.uidl() if uidl[0].startswith("+"): self.uidlworks = True msg_tups = [tuple(tup.split()) for tup in uidl[1]][-25:] for tup in msg_tups: try: mailmsg = retr(tup[0]) except Exception: print_exc() else: try: email_id = tup[1] except IndexError: email_id = None #someone had '1 ' -> ('1',) None seems to work fine. emails.append( Email.fromEmailMessage( email_id, DecodedEmail( email.message_from_string("\n".join( mailmsg[1]))))) else: self.uidlworks = False num_to_get = min(num_emails, 25) for i in xrange(num_to_get, max(num_to_get - 25, -1), -1): try: mailmsg = retr(str(i)) except Exception: print_exc() else: emailstring = "\n".join(mailmsg[1]) de = DecodedEmail(email.message_from_string(emailstring)) emails.append( Email.fromEmailMessage( sha1(emailstring).hexdigest() + "SHA" + str(i) + "SHA", de)) return emails, num_emails #self.change_state(self.Statuses.ONLINE) # import time # print num_emails, time.time() def _connect(self): if self.require_ssl: from poplib import POP3_SSL as pop else: from poplib import POP3 as pop try: conn = pop(self.popserver, self.popport) except Exception, e: log.error('There was an error connecting: %s', e) self.on_error() raise self.conn = conn log.info(conn.user(self.name)) try: password = self._decryptedpw().encode('utf-8') log.info(conn.pass_(password)) except Exception, e: log.error('Bad password: %s', e) self._auth_error_msg = e.message self.set_offline(self.Reasons.BAD_PASSWORD) self.timer.stop() raise
class PopMail(SMTPEmailAccount): protocol = 'pop' default_timeout = 20 opening_email_marks_as_read = False def __init__(self, **options): d = self.default self.popserver = options.get('popserver', '') self.require_ssl = options.get('require_ssl', d('require_ssl')) self.popport = options.get('popport', d('popport')) self.uidlworks = None self.topworks = True #assume it does until proven otherwise self.cmdq = CommandQueue(start_hooks=[self._connect], end_hooks=[self._quit]) self.timeouttimer = ResetTimer(pref('pop.timeout',self.default_timeout), self.timeout_check) SMTPEmailAccount.__init__(self, **options) can_has_preview = True def timeout_check(self): log.info('Checking server connection for %r', self) if self.state in (self.Statuses.OFFLINE, self.Statuses.ONLINE): log.info('%s is not currently checking', self) return True if get(self, 'conn', False): try: self.conn.noop() except: self.on_error() log.error('%s\'s server connection has failed', self) return False else: log.error('%s has no conn attribute', self) self.on_error() return False def update(self): SMTPEmailAccount.update(self) log.info('starting timeout timer') self.timeouttimer.start() self.real_update(success = self.finish_update) def finish_update(self, updates): import time if self.state == self.Statuses.OFFLINE: log.error('finish_update exiting early, state is %s', self.state) return (updated_emails, updated_count) = updates log.info("%s got %d new messages %s", self, updated_count, time.ctime(time.time())) #self.change_state(self.Statuses.ONLINE) self._received_emails(updated_emails[:25], updated_count) # if self.state in (self.Statuses.CONNECTING, self.Statuses.CHECKING): # self.change_state(self.Statuses.ONLINE) self.error_count = 0 log.info('stopping timeout timer') self.timeouttimer.stop() @callback_cmdqueue() def real_update(self): #self.change_state(self.Statuses.CHECKING) if self.state == self.Statuses.OFFLINE: return conn = self.conn num_emails, box_size = conn.stat() num_emails = int(num_emails) emails = [] def retr(mid): if self.topworks: try: return conn.top(mid, 100) except: self.topworks = False return conn.retr(mid) uidl = conn.uidl() if uidl[0].startswith("+"): self.uidlworks = True msg_tups = [tuple(tup.split()) for tup in uidl[1]][-25:] for tup in msg_tups: try: mailmsg = retr(tup[0]) except Exception: print_exc() else: try: email_id = tup[1] except IndexError: email_id = None #someone had '1 ' -> ('1',) None seems to work fine. emails.append( Email.fromEmailMessage(email_id, DecodedEmail( email.message_from_string( "\n".join(mailmsg[1]) )))) else: self.uidlworks = False num_to_get = min(num_emails, 25) for i in xrange(num_to_get, max(num_to_get-25, -1), -1): try: mailmsg = retr(str(i)) except Exception: print_exc() else: emailstring = "\n".join(mailmsg[1]) de = DecodedEmail(email.message_from_string(emailstring)) emails.append(Email.fromEmailMessage( sha1(emailstring).hexdigest() + "SHA"+str(i)+"SHA", de)) return emails, num_emails #self.change_state(self.Statuses.ONLINE) # import time # print num_emails, time.time() def _connect(self): if self.require_ssl: from poplib import POP3_SSL as pop else: from poplib import POP3 as pop try: conn = pop(self.popserver, self.popport) except Exception, e: log.error('There was an error connecting: %s', e) self.on_error() raise self.conn = conn log.info(conn.user(self.name)) try: password = self._decryptedpw().encode('utf-8') log.info(conn.pass_(password)) except Exception, e: log.error('Bad password: %s', e) self._auth_error_msg = e.message self.set_offline(self.Reasons.BAD_PASSWORD) self.timer.stop() raise