def imapclient_test(login, password): server = IMAPClient(HOST, use_uid=True, ssl=ssl) server.login(login, password) capabilities = server.capabilities() #print("list folders = %s\n" %(server.list_folders())) select_info = server.select_folder('[Gmail]/All Mail') #print '%d messages in INBOX' % select_info['EXISTS'] messages = server.search(['NOT DELETED']) print "%d messages in [Gmail]/Inbox" % len(messages) for msg in messages[:20]: print("msg uid = %d\n" % (msg)) sys.exit() select_info = server.select_folder('[Gmail]/Sent Mail') #print '%d messages in INBOX' % select_info['EXISTS'] messages = server.search(['NOT DELETED']) print "%d messages in [Gmail]/Sent Mail" % len(messages)
def login(self): try: context = ssl.create_default_context(cafile=certifi.where()) # context.check_hostname = False # context.verify_mode = ssl.CERT_NONE mailbox = IMAPClient( self.source.host, port=self.source.port, use_uid=True, ssl=self.source.use_ssl, ssl_context=context) # mailbox.debug = 5 capabilities = mailbox.capabilities() if b'STARTTLS' in capabilities: # Always use starttls if server supports it mailbox.starttls(context) if b'IDLE' in capabilities: self.can_push = True mailbox.login(self.source.username, self.source.password) mailbox.select_folder(self.source.folder) self.selected_folder = True self.mailbox = mailbox except IMAP4.abort as e: raise IrrecoverableError(e) except IMAP4.error as e: raise ClientError(e)
def imapclient_test(login, password): server = IMAPClient(HOST, use_uid=True, ssl=ssl) server.login(login, password) capabilities = server.capabilities() #print("list folders = %s\n" %(server.list_folders())) select_info = server.select_folder('[Gmail]/All Mail') #print '%d messages in INBOX' % select_info['EXISTS'] messages = server.search(['NOT DELETED']) print "%d messages in [Gmail]/Inbox" % len(messages) for msg in messages[:20]: print("msg uid = %d\n" %(msg)) sys.exit() select_info = server.select_folder('[Gmail]/Sent Mail') #print '%d messages in INBOX' % select_info['EXISTS'] messages = server.search(['NOT DELETED']) print "%d messages in [Gmail]/Sent Mail" % len(messages)
def debug(account): c = ACCOUNTS[account] if 'pass_cmd' in c: c['pass'] = check_output([c['pass_cmd']], shell=True).strip() client = IMAPClient(c['host'], use_uid=True, ssl=c['ssl']) client.login(c['user'], c['pass']) print(client.capabilities())
def make_imap(self): server_string = ( f'{self.config.username}@{self.config.host}:{self.config.port} ' f'(ssl={self.config.ssl})' ) self.config.log('debug', f'Connecting to IMAP server: {server_string}') ssl_context = ssl.create_default_context() if self.config.ssl_verify_hostname is False: self.config.log('warning', 'Disabling SSL hostname verification!') ssl_context.check_hostname = False imap = IMAPClient( self.config.host, port=self.config.port, ssl=self.config.ssl, ssl_context=ssl_context, timeout=self.config.timeout, use_uid=True, ) imap.normalise_times = False if self.config.oauth_provider: try: imap.oauth2_login(self.config.username, self.config.get_oauth_access_token()) except LoginError as e: # TODO: Tidy this up/move it if 'AUTHENTICATIONFAILED' in f'{e}': self.config.log('info', 'Refreshing OAuth acccess token') invalidate_access_token(self.config.oauth_refresh_token) imap.oauth2_login(self.config.username, self.config.get_oauth_access_token()) else: imap.login(self.config.username, self.config.password) if self._selected_folder: imap.select_folder(self._selected_folder) # Ensure the IMAP object has capabilities cached as this is used internally # within imapclient. imap.capabilities() self._imap = imap self.config.log('info', f'Connected to IMAP server: {server_string}')
def debug(account): c = ACCOUNTS[account] if 'pass_cmd' in c: c['pass'] = check_output([c['pass_cmd']], shell=True).strip() client = IMAPClient( c['host'], use_uid=True, ssl=c['ssl']) try: client.login(c['user'], c['pass']) print(client.capabilities()) finally: client.logout()
def main(): if len(sys.argv) != 3: print("usage: %s hostname username" % sys.argv[0]) sys.exit(2) hostname, username = sys.argv[1:] c = IMAPClient(hostname, ssl=True) try: c.login(username, getpass.getpass()) except c.Error as e: print("could not log in:", e) else: print('capabilities:', c.capabilities()) print("listing mailboxes:") data = c.list_folders() for flags, delimiter, folder_name in data: print('%-30s%s %s' % (' '.join(flags), delimiter, folder_name)) finally: c.logout()
def connect_account(self, account): """ Returns an authenticated IMAP connection for the given account. Raises ------ ValidationError If IMAP LOGIN failed because of invalid username/password imapclient.IMAPClient.Error, socket.error If other errors occurred establishing the connection or logging in. """ host, port = account.imap_endpoint try: conn = IMAPClient(host, port=port, use_uid=True, ssl=(port == 993)) if port != 993: # Raises an exception if TLS can't be established conn._imap.starttls() except (IMAPClient.Error, socket.error) as exc: log.error('Error instantiating IMAP connection', account_id=account.id, email=account.email_address, host=host, port=port, error=exc) raise try: conn.login(account.email_address, account.password) except IMAPClient.Error as exc: if _auth_is_invalid(exc): log.error('IMAP login failed', account_id=account.id, email=account.email_address, host=host, port=port, error=exc) raise ValidationError(exc) else: log.error('IMAP login failed for an unknown reason', account_id=account.id, email=account.email_address, host=host, port=port, error=exc) raise if 'ID' in conn.capabilities(): # Try to issue an IMAP ID command. Some whacky servers # (163.com) require this, but it's an encouraged practice in any # case. Since this isn't integral to the sync in general, don't # fail if there are any errors. # (Note that as of May 2015, this depends on a patched imapclient # that implements the ID command.) try: conn.id_({'name': 'Nylas Sync Engine', 'vendor': 'Nylas', 'contact': '*****@*****.**'}) except Exception as exc: log.warning('Error issuing IMAP ID command; continuing', account_id=account.id, email=account.email_address, host=host, port=port, error=exc) return conn
#!/usr/bin/env python3 import sys from imapclient import IMAPClient import getpass username = input('Enter your username:'******'Enter your password:'******'imap.gmail.com', ssl=True) try: server.login(username, password) except server.Error as e: print('Could not log in:', e) sys.exit(1) print('Capabilities:', server.capabilities()) print('Listing mailboxes:') data = server.list_folders() for flags, delimiter, folder_name in data: print(' %-30s%s %s' % (' '.join(str(flags)), delimiter, folder_name)) server.logout()
#!/usr/bin/env python # Foundations of Python Network Programming - Chapter 15 - open_imap.py # Opening an IMAP connection with the powerful IMAPClient import getpass, sys from imapclient import IMAPClient try: hostname, username = sys.argv[1:] except ValueError: print 'usage: %s hostname username' % sys.argv[0] sys.exit(2) c = IMAPClient(hostname, ssl=True) try: c.login(username, getpass.getpass()) except c.Error, e: print 'Could not log in:', e sys.exit(1) print 'Capabilities:', c.capabilities() print 'Listing mailboxes:' data = c.list_folders() for flags, delimiter, folder_name in data: print ' %-30s%s %s' % (' '.join(flags), delimiter, folder_name) c.logout()
def fetch_new_messages(): new_messages = server.search(NEW_MSG_CRITERIA) response = server.fetch(new_messages, ['RFC822']) for msgid, data in response.iteritems(): msg = email.message_from_string(data['RFC822']) logging.debug(u"Payload: " + msg.get_payload(None,True)) if msg["subject"] == "SET_LED": set_led(msg.get_payload(None,True)) elif msg["subject"] == "PRINT": send_print(msg.get_payload(None,True)) while True: try: server = IMAPClient(HOST, port=993, use_uid=True, ssl=ssl) print server.capabilities() server.login(USERNAME, PASSWORD) select_info = server.select_folder('INBOX') logging.debug('%d messages in INBOX' % select_info['EXISTS']) fetch_new_messages() while True: server.idle() try: while True: responses = server.idle_check(timeout=200) if [i for i, v in enumerate(responses) if v[1] in (u'EXISTS',u'FETCH')]: logging.debug("will fetch new messages") server.idle_done()
class IMAPBot(object): IMAPBotError = IMAPBotError def __init__(self, host, username, password, ssl=True): self.server = IMAPClient(host, use_uid=True, ssl=ssl) self.server.login(username, password) if 'IDLE' not in self.server.capabilities(): raise IMAPBotError('Sorry, this IMAP server does not support IDLE.') # the folder where processed emails go self.processed_folder = 'imapbot_processed' self.idle_timeout = 5 # seconds self._is_idle = False self._run = True self._create_folder(self.processed_folder) def check_mail(self): select_info = self.server.select_folder('INBOX') print '%d messages in INBOX' % select_info['EXISTS'] messages = self.server.search(['UNSEEN']) messages = self.server.search(['NOT DELETED']) print "%d messages that haven't been seen" % len(messages) if not messages: return #response = self.server.fetch(messages, ['FLAGS', 'INTERNALDATE', 'RFC822.SIZE', 'ENVELOPE', 'RFC822.TEXT']) response = self.server.fetch(messages, ['FLAGS', 'ENVELOPE', 'RFC822.TEXT']) for message_id, data in response.iteritems(): message = Message(message_id, data['ENVELOPE'], data['RFC822.TEXT'], data['FLAGS']) self.process(message) def complete(self, message): message_ids = [message.id] self.server.copy(message_ids, self.processed_folder) self.server.delete_messages(message_ids) self.server.expunge() def _create_folder(self, name): # make sure the folder doesn't already exist if self.server.folder_exists(name): return self.server.create_folder(name) def handle_message(self, message): print 'message id: {}, from: {}:'.format(message.id, message.envelope.get_email('from')) with open('message.txt', 'ab') as fh: fh.write('{}\n\n'.format(message.text)) print message.plain or message.html or 'no message' def idle(self): if self._is_idle: return self.server.idle() self._is_idle = True return True # this actually changed state def unidle(self): if not self._is_idle: return self.server.idle_done() self._is_idle = False return True # this call actually changed state def process(self, message): self.handle_message(message) self.complete(message) def run(self): # process any mail that was in the inbox before coming online self.check_mail() # put the connection in idle mode so we get notifications self.idle() # loop forever looking for stuff while self._run: for message in self.server.idle_check(timeout=self.idle_timeout): if message[0] == 'OK': continue with Unidle(self): self.check_mail() def quit(self): self._run = False self.unidle() print self.server.logout()
class ImapConn(object): def __init__(self, db, foldername, conn_info): self.db = db self.foldername = foldername self._thread = None self.MHOST, self.MUSER, self.MPASSWORD = conn_info self.event_initial_polling_complete = threading.Event() self.pending_imap_jobs = False # persistent database state below self.db_folder = self.db.setdefault(foldername, {}) self.db_messages = self.db.setdefault(":message-full", {}) last_sync_uid = db_folder_attr("last_sync_uid") @contextlib.contextmanager def wlog(self, msg): t = time.time() - started with lock_log: print("%03.2f [%s] %s -->" % (t, self.foldername, msg)) t0 = time.time() yield t1 = time.time() with lock_log: print("%03.2f [%s] ... finish %s (%3.2f secs)" % (t1 - started, self.foldername, msg, t1 - t0)) def log(self, *msgs): t = time.time() - started bmsg = "%03.2f [%s]" % (t, self.foldername) with lock_log: print(bmsg, *msgs) def connect(self): with self.wlog("IMAP_CONNECT {}: {}".format(self.MUSER, self.MPASSWORD)): ssl_context = ssl.create_default_context() # don't check if certificate hostname doesn't match target hostname ssl_context.check_hostname = False # don't check if the certificate is trusted by a certificate authority ssl_context.verify_mode = ssl.CERT_NONE self.conn = IMAPClient(self.MHOST, ssl_context=ssl_context) self.conn.login(self.MUSER, self.MPASSWORD) self.log(self.conn.welcome) try: self.select_info = self.conn.select_folder(self.foldername) except IMAPClientError: self.ensure_folder_exists() self.select_info = self.conn.select_folder(self.foldername) self.log('folder has %d messages' % self.select_info[b'EXISTS']) self.log('capabilities', self.conn.capabilities()) def ensure_folder_exists(self): with self.wlog("ensure_folder_exists: {}".format(self.foldername)): try: resp = self.conn.create_folder(self.foldername) except IMAPClientError as e: if "ALREADYEXISTS" in str(e): return print("EXCEPTION:" + str(e)) else: print("Server sent:", resp if resp else "nothing") def move(self, messages): self.log("IMAP_MOVE to {}: {}".format(MVBOX, messages)) try: resp = self.conn.move(messages, MVBOX) except IMAPClientError as e: if "EXPUNGEISSUED" in str(e): self.log( "IMAP_MOVE errored with EXPUNGEISSUED, probably another client moved it" ) else: self.log( "IMAP_MOVE {} successfully completed.".format(messages)) def perform_imap_idle(self): if self.pending_imap_jobs: self.log("perform_imap_idle skipped because jobs are pending") return with self.wlog("IMAP_IDLE()"): res = self.conn.idle() interrupted = False while not interrupted: # Wait for up to 30 seconds for an IDLE response responses = self.conn.idle_check(timeout=30) self.log("Server sent:", responses if responses else "nothing") for resp in responses: if resp[1] == b"EXISTS": # we ignore what is returned and just let # perform_imap_fetch look since lastseen # id = resp[0] interrupted = True resp = self.conn.idle_done() def perform_imap_fetch(self): range = "%s:*" % (self.last_sync_uid + 1, ) with self.wlog("IMAP_PERFORM_FETCH %s" % (range, )): requested_fields = [ b"RFC822.SIZE", b'FLAGS', b"BODY.PEEK[HEADER.FIELDS (FROM TO CC DATE CHAT-VERSION MESSAGE-ID IN-REPLY-TO)]" ] resp = self.conn.fetch(range, requested_fields) timestamp_fetch = time.time() for uid in sorted(resp): # get lower uids first if uid < self.last_sync_uid: self.log( "IMAP-ODDITY: ignoring bogus uid %s, it is lower than min-requested %s" % (uid, self.last_sync_uid)) continue data = resp[uid] headers = data[requested_fields[-1].replace(b'.PEEK', b'')] msg_headers = email.message_from_bytes(headers) message_id = normalized_messageid(msg_headers) chat_version = msg_headers.get("Chat-Version") in_reply_to = msg_headers.get("In-Reply-To", "").lower() if not self.has_message(normalized_messageid(msg_headers)): self.log('fetching body of ID %d: %d bytes, message-id=%s ' 'in-reply-to=%s chat-version=%s' % ( uid, data[b'RFC822.SIZE'], message_id, in_reply_to, chat_version, )) fetchbody_resp = self.conn.fetch(uid, [b'BODY.PEEK[]']) msg = email.message_from_bytes( fetchbody_resp[uid][b'BODY[]']) msg.fetch_retrieve_time = timestamp_fetch msg.foldername = self.foldername msg.uid = uid msg.move_state = DC_CONSTANT_MSG_MOVESTATE_PENDING self.store_message(message_id, msg) else: msg = self.get_message_from_db(message_id) self.log('fetching-from-db: ID %s message-id=%s' % (uid, message_id)) if msg.foldername != self.foldername: self.log("detected moved message", message_id) msg.foldername = self.foldername msg.move_state = DC_CONSTANT_MSG_MOVESTATE_STAY if self.foldername in (INBOX, SENT): if self.resolve_move_status( msg) != DC_CONSTANT_MSG_MOVESTATE_PENDING: # see if there are pending messages which have a in-reply-to # to our currnet msg # NOTE: should be one sql-statement to find the # possibly multiple messages that waited on us for dbmid, dbmsg in self.db_messages.items(): if dbmsg.move_state == DC_CONSTANT_MSG_MOVESTATE_PENDING: if dbmsg.get("In-Reply-To", "").lower() == message_id: self.log("resolving pending message", dbmid) # resolving the dependent message must work now res = self.resolve_move_status(dbmsg) assert res != DC_CONSTANT_MSG_MOVESTATE_PENDING, ( dbmid, res) if not self.has_message(message_id): self.store_message(message_id, msg) self.last_sync_uid = max(uid, self.last_sync_uid) self.log("last-sync-uid after fetch:", self.last_sync_uid) self.db.sync() def resolve_move_status(self, msg): """ Return move-state after this message's next move-state is determined (i.e. it is not PENDING)""" message_id = normalized_messageid(msg) if msg.move_state == DC_CONSTANT_MSG_MOVESTATE_PENDING: res = self.determine_next_move_state(msg) if res == DC_CONSTANT_MSG_MOVESTATE_MOVING: self.schedule_move(msg) msg.move_state = DC_CONSTANT_MSG_MOVESTATE_MOVING elif res == DC_CONSTANT_MSG_MOVESTATE_STAY: self.log("STAY uid=%s message-id=%s" % (msg.uid, message_id)) msg.move_state = DC_CONSTANT_MSG_MOVESTATE_STAY else: self.log("PENDING uid=%s message-id=%s in-reply-to=%s" % (msg.uid, message_id, msg["In-Reply-To"])) return msg.move_state def determine_next_move_state(self, msg): """ Return the next move state for this message. Only call this function if the message is pending. This function works with the DB, does not perform any IMAP commands. """ self.log("shall_move %s " % (normalized_messageid(msg))) assert self.foldername in (INBOX, SENT) assert msg.move_state == DC_CONSTANT_MSG_MOVESTATE_PENDING if msg.foldername == MVBOX: self.log("is already in mvbox, next state is STAY %s" % (normalized_messageid(msg))) return DC_CONSTANT_MSG_MOVESTATE_STAY last_dc_count = 0 while 1: last_dc_count = (last_dc_count + 1) if is_dc_message(msg) else 0 in_reply_to = normalized_messageid(msg.get("In-Reply-To", "")) if not in_reply_to: type_msg = "DC" if last_dc_count else "CLEAR" self.log("detected thread-start %s message" % type_msg, normalized_messageid(msg)) if last_dc_count > 0: return DC_CONSTANT_MSG_MOVESTATE_MOVING else: return DC_CONSTANT_MSG_MOVESTATE_STAY newmsg = self.get_message_from_db(in_reply_to) if not newmsg: self.log("failed to fetch from db:", in_reply_to) # we don't have the parent message ... maybe because # it hasn't arrived (yet), was deleted or we failed to # scan/fetch it: if last_dc_count >= 4: self.log( "no thread-start found, but last 4 messages were DC") return DC_CONSTANT_MSG_MOVESTATE_MOVING else: self.log("pending: missing parent, last_dc_count=%x" % (last_dc_count, )) return DC_CONSTANT_MSG_MOVESTATE_PENDING elif newmsg.move_state == DC_CONSTANT_MSG_MOVESTATE_MOVING: self.log("parent was a moved message") return DC_CONSTANT_MSG_MOVESTATE_MOVING else: msg = newmsg assert 0, "should never arrive here" def schedule_move(self, msg): message_id = normalized_messageid(msg) assert msg.foldername != MVBOX self.log("scheduling move message-id=%s" % (message_id)) self.pending_imap_jobs = True def has_message(self, message_id): assert isinstance(message_id, str) return message_id in self.db_messages def get_message_from_db(self, message_id): return self.db_messages.get(normalized_messageid(message_id)) def store_message(self, message_id, msg): mid2 = normalized_messageid(msg) message_id = normalized_messageid(message_id) assert message_id == mid2 assert message_id not in self.db_messages, message_id assert msg.foldername in (MVBOX, SENT, INBOX) self.db_messages[message_id] = msg self.log("stored new message message-id=%s" % (message_id, )) def forget_about_too_old_pending_messages(self): # some housekeeping but not sure if neccessary # because the involved sql-statements # probably don't care if there are some foreever-pending messages now = time.time() for dbmid, dbmsg in self.db_messages.items(): if dbmsg.move_state == DC_CONSTANT_MSG_MOVESTATE_PENDING: delay = now - dbmsg.fetch_retrieve_time if delay > self.pendingtimeout: dbmsg.move_state = DC_CONSTANT_MSG_MOVESTATE_STAY self.log("pendingtimeout: message now set to stay", dbmid) def perform_imap_jobs(self): with self.wlog("perform_imap_jobs()"): if self.foldername in (INBOX, SENT): to_move_uids = [] to_move_msgs = [] # determine all uids of messages that are to be moved for dbmid, dbmsg in self.db_messages.items(): if dbmsg.move_state == DC_CONSTANT_MSG_MOVESTATE_MOVING: if dbmsg.uid > 0: # else it's already moved? to_move_uids.append(dbmsg.uid) to_move_msgs.append(dbmsg) if to_move_uids: self.move(to_move_uids) # now that we moved let's invalidate "uid" because it's # not there anyore in thie folder for dbmsg in to_move_msgs: dbmsg.uid = 0 self.pending_imap_jobs = False def _run_in_thread(self): self.connect() if self.foldername == INBOX: # INBOX loop should wait until MVBOX polled once mvbox.event_initial_polling_complete.wait() now = time.time() while True: self.perform_imap_jobs() self.perform_imap_fetch() if self.foldername == MVBOX: # signal that MVBOX has polled once self.event_initial_polling_complete.set() elif self.foldername == INBOX: # it's not clear we need to do this housekeeping # (depends on the SQL statements) self.forget_about_too_old_pending_messages() self.perform_imap_idle() def start_thread_loop(self): assert not self._thread self._thread = t = threading.Thread(target=self._run_in_thread) t.start()
#!/usr/bin/python from imapclient import IMAPClient HOST = 'imap.mail.yahoo.com' USER = '******' PW = 'ihateYahoo1' print 'connecting...' conn = IMAPClient(HOST, use_uid=True, ssl=True) conn.login(USER, PW) #conn = IMAPClient('imap.gmail.com', use_uid=True, ssl=True) #conn.login('testinboxapp', 'ihategmail') print '\n\ncapabilities = ', conn.capabilities() folders = conn.list_folders() print folders #print '\n\nfolders = ', [f[2] for f in folders] for f in folders: sub_folders = conn.list_sub_folders(directory=f[2]) print '\n\nsub_folders for folder %s = ' %(f[2]), sub_folders namespace = conn.namespace() print '\n\nnamespace = ', namespace for f in folders: name = f[2] info = conn.select_folder(name)
def connect_account(self, account): """Returns an authenticated IMAP connection for the given account. Raises ------ ValidationError If IMAP LOGIN failed because of invalid username/password imapclient.IMAPClient.Error, socket.error If other errors occurred establishing the connection or logging in. """ host, port = account.imap_endpoint try: conn = IMAPClient(host, port=port, use_uid=True, ssl=(port == 993)) if port != 993: # Raises an exception if TLS can't be established conn._imap.starttls() except (IMAPClient.Error, socket.error) as exc: log.error( "Error instantiating IMAP connection", account_id=account.id, email=account.email_address, host=host, port=port, error=exc, ) raise try: conn.login(account.email_address, account.password) except IMAPClient.Error as exc: if _auth_is_invalid(exc): log.error( "IMAP login failed", account_id=account.id, email=account.email_address, host=host, port=port, error=exc, ) raise ValidationError(exc) else: log.error( "IMAP login failed for an unknown reason", account_id=account.id, email=account.email_address, host=host, port=port, error=exc, ) raise if "ID" in conn.capabilities(): # Try to issue an IMAP ID command. Some whacky servers # (163.com) require this, but it's an encouraged practice in any # case. Since this isn't integral to the sync in general, don't # fail if there are any errors. # (Note that as of May 2015, this depends on a patched imapclient # that implements the ID command.) try: conn.id_({"name": "Nylas Sync Engine", "vendor": "Nylas", "contact": "*****@*****.**"}) except Exception as exc: log.warning( "Error issuing IMAP ID command; continuing", account_id=account.id, email=account.email_address, host=host, port=port, error=exc, ) return conn
#!/usr/bin/env python # Foundations of Python Network Programming - Chapter 15 - open_imap.py # Opening an IMAP connection with the powerful IMAPClient import getpass, sys from imapclient import IMAPClient try: hostname, username = sys.argv[1:] except ValueError: print('usage: %s hostname username' % sys.argv[0]) sys.exit(2) c = IMAPClient(hostname, ssl=True) try: c.login(username, getpass.getpass()) except c.Error as e: print('Could not log in:', e) sys.exit(1) print('Capabilities:', c.capabilities()) print('Listing mailboxes:') data = c.list_folders() for flags, delimiter, folder_name in data: print(' %-30s%s %s' % (' '.join(flags), delimiter, folder_name)) c.logout()
from imapclient import IMAPClient HOST = 'imap.mail.yahoo.com' USERNAME = '******' PASSWORD = '******' ssl = True server = IMAPClient(HOST, use_uid=True, ssl=ssl) server.login(USERNAME, PASSWORD) select_info = server.select_folder('INBOX') print('%d messages in current box' % select_info['EXISTS']) messages = server.search(['NOT DELETED']) print("%d messages that aren't deleted" % len(messages)) print() print("Messages:") response = server.fetch(messages, ['FLAGS', 'RFC822.SIZE']) for msgid, data in response.iteritems(): print(' ID %d: %d bytes, flags=%s' % (msgid, data['RFC822.SIZE'], data['FLAGS'])) print server.capabilities()