def get_message_uids(mbox: IMAP4, label='INBOX'): """ Get all message UIDs to be fetched from server. Resume from the `latest UID` if there is one found. """ mbox.select(label, readonly=True) # mbox.select('"[Gmail]/All Mail"', readonly=True) latest_uid = MsgMeta.get_latest_uid() if latest_uid: box_status, box_data = mbox.uid('search', None, 'UID', latest_uid + ':*') else: box_status, box_data = mbox.uid('search', None, 'ALL') if box_status != OK_STATUS: return # This will be a list of bytes message_uids = box_data[0].split() if latest_uid and latest_uid.encode() in message_uids: message_uids.remove(latest_uid.encode()) log.info('Resuming from the latest UID.') log.info('Latest UID %s, Message count %s', latest_uid, len(message_uids)) return message_uids
def change_swa_settings(conn: imaplib.IMAP4, swa_options: dict): """Changes swa preference email or create a new one if message with preference does not exists. :param swa_options: :param conn: imaplib.IMAP4 :return: """ status, data = conn.select('#Scalix/Oddpost') if status != 'OK': raise Exception('Could not select folder #Scalix/Oddpost. ' 'Imap response: {}'.format(data)) orphan_uids = set() if not int(data[0]): # there are no messages in mailbox fetching will fail so we will # skip it email = create_preference_message() else: email, orphan_uids = find_swa_preference_email(conn) if not email: email = create_preference_message() # lets apply changes to the preferences for key, value in swa_options.items(): find_option_and_change(email.preferences, key, value) # if we have UID for previous email jus tadd it to delete if email.uid: orphan_uids.add(email.uid) if orphan_uids: uids_del = b','.join([str(uid).encode() for uid in orphan_uids]) status, data = conn.uid('STORE', uids_del.decode(), '+FLAGS', '\\Deleted') if status != 'OK': warnings.warn( 'Could not delete duplicate preference emails {}' '. Error {}.'.format(orphan_uids, data), RuntimeWarning ) status, data = conn.append('#Scalix/Oddpost', '\\Seen', imaplib.Time2Internaldate(time.time()), email.as_bytes()) if status != 'OK': if email.uid: conn.uid('STORE', email.uid, '-FLAGS', '\\Deleted') raise Exception('Could not save email. Error message {}'.format(data)) conn.expunge()
def fetch_new_mail( server: imaplib.IMAP4, last_uid: Optional[int] = None) -> Iterator[Tuple[int, bytes]]: # todo: support UIDVALIDITY # issue the search command of the form "SEARCH UID 42:*" command = "UID {}:*".format(last_uid) if last_uid else 'ALL' result, data = server.uid('search', None, command) message_id_string = data[0].strip() message_ids = message_id_string.decode().split( ' ') if message_id_string else [] # yield mails for message_uid in message_ids: # SEARCH command *always* returns at least the most # recent message, even if it has already been synced uid = int(message_uid) if last_uid is None or uid > last_uid: result, data = server.uid('fetch', message_uid, '(RFC822)') # yield raw mail body yield uid, data[0][1]
def fetch_all_messages(mbox: IMAP4, message_uids: list): """ Fetch each eligible message in RFC822 format. Returns a generator. """ for m_uid in message_uids: msg_status, msg_data = mbox.uid('fetch', m_uid, '(RFC822)') if msg_status != OK_STATUS: log.warning('Message UID %s was not OK', m_uid) yield None raw_email = msg_data[0][1] checksum = hashlib.sha256(raw_email).hexdigest() email_msg = email.message_from_bytes(raw_email) yield email_msg, checksum, m_uid
def run(self, imap_obj: imaplib.IMAP4): typ, data = imap_obj.uid('STORE', self.__uids, '+FLAGS', '\\Deleted') self.check_response(typ, data) typ, data = imap_obj.expunge() self.check_response(typ, data) return True