Example #1
0
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
Example #2
0
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)
Example #3
0
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