def get_message_iterator(pop3_connection: POP3_SSL, username: str) -> Iterator[Tuple[EmailMessageDto, Callable]]: mails: list _, mails, _ = pop3_connection.list() mailbox_config, _ = MailboxConfig.objects.get_or_create(username=username) # Check only the last 500 emails # Since we don't delete emails from these mailboxes the total number can be very high over a perio # and increases the processing time. # The mails is a list of message number and size - message number is an increasing value so the # latest emails will always be at the end. mail_message_ids = [get_message_id(pop3_connection, m.decode(settings.DEFAULT_ENCODING)) for m in mails[-500:]] # these are mailbox message ids we've seen before read_messages = get_read_messages(mailbox_config) logging.info(f"Number of messages READ/UNPROCESSABLE in {mailbox_config.username} are {len(read_messages)}") for message_id, message_num in mail_message_ids: # only return messages we haven't seen before if message_id is not None and message_id not in read_messages: read_status, _ = MailReadStatus.objects.get_or_create( message_id=message_id, message_num=message_num, mailbox=mailbox_config ) def mark_status(status): """ :param status: A choice from `MailReadStatuses.choices` """ logging.info( f"Marking message_id {message_id} with message_num {message_num} from {read_status.mailbox.username} as {status}" ) read_status.status = status read_status.save() try: m = pop3_connection.retr(message_num) logging.info( f"Retrieved message_id {message_id} with message_num {message_num} from {read_status.mailbox.username}" ) except error_proto as err: logging.error( f"Unable to RETR message num {message_num} with Message-ID {message_id} in {mailbox_config}: {err}", exc_info=True, ) continue try: mail_message = to_mail_message_dto(m) except ValueError as ve: logging.error( f"Unable to convert message num {message_id} with Message-Id {message_id} to DTO in {mailbox_config}: {ve}", exc_info=True, ) mark_status(MailReadStatuses.UNPROCESSABLE) continue yield mail_message, mark_status
def read_last_message(pop3_connection: POP3_SSL) -> EmailMessageDto: _, mails, _ = pop3_connection.list() message_id, message_num = get_message_id(pop3_connection, mails[-1]) try: message = pop3_connection.retr(message_num) except error_proto as err: raise Exception(f"Unable to RETR message num {message_num} with Message-ID {message_id}",) from err return to_mail_message_dto(message)
def read_last_three_emails(pop3connection: POP3_SSL) -> list: _, mails, _ = pop3connection.list() reversed_mails = list(reversed(mails)) last_three_mails = reversed_mails[:3] message_ids = [get_message_id(pop3connection, line.decode(settings.DEFAULT_ENCODING)) for line in last_three_mails] emails = [] for message_id, message_num in message_ids: try: emails.append(pop3connection.retr(message_num)) except error_proto as err: raise Exception(f"Unable to RETR message num {message_num} with Message-ID {message_id}",) from err email_message_dtos = [] for email in emails: email_message_dtos.append(to_mail_message_dto(email)) return email_message_dtos