From 88b35117aee79417a5e2e8c30b25e67fa54efbe8 Mon Sep 17 00:00:00 2001 From: Mike Varga Date: Fri, 14 Oct 2022 13:49:59 -0400 Subject: [PATCH] Implement read-only mail fetching --- django_mailbox/transports/generic.py | 3 ++ django_mailbox/transports/imap.py | 45 ++++++++++++++++++++++------ django_mailbox/transports/pop3.py | 3 ++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/django_mailbox/transports/generic.py b/django_mailbox/transports/generic.py index 5832fda..2d27fba 100644 --- a/django_mailbox/transports/generic.py +++ b/django_mailbox/transports/generic.py @@ -24,3 +24,6 @@ class GenericFileMailbox(EmailTransport): yield message repository.flush() repository.unlock() + + def get_new_message_ro(self, since=None): + raise NotImplementedError("GenericFileMailbox.get_new_message_ro not implemented!") diff --git a/django_mailbox/transports/imap.py b/django_mailbox/transports/imap.py index 2599ada..79d5b49 100644 --- a/django_mailbox/transports/imap.py +++ b/django_mailbox/transports/imap.py @@ -99,19 +99,47 @@ class ImapTransport(EmailTransport): if not message_ids: return - # Limit the uids to the small ones if we care about that - if self.max_message_size: - message_ids = self._get_small_message_ids(message_ids) - if self.archive: typ, folders = self.server.list(pattern=self.archive) if folders[0] is None: # If the archive folder does not exist, create it self.server.create(self.archive) + for message in self._iter_messages(message_ids): + yield message + + self.server.expunge() + return + + def get_new_message_ro(self, since): + """Read-only version of `get_message`. Uses a timestamp to fetch only messages + originating later than `since` parameter. + """ + + date_format = "%d-%b-%Y" + typ, [raw_msg_ids] = self.server.search(None, '(since "%s")' % (since.strftime(date_format))) + + message_ids = raw_msg_ids.decode().split() + + if not message_ids: + return + + for message in self._iter_messages(message_ids, archive=False, delete=False): + yield message + + self.server.expunge() + return + + + def _iter_messages(self, message_ids, condition=None, archive=True, delete=True): + + # Limit the uids to the small ones if we care about that + if self.max_message_size: + message_ids = self._get_small_message_ids(message_ids) + for uid in message_ids: try: - typ, msg_contents = self.server.uid('fetch', uid, '(RFC822)') + typ, msg_contents = self.server.fetch(uid, '(RFC822)') if not msg_contents: continue try: @@ -129,9 +157,8 @@ class ImapTransport(EmailTransport): except MessageParseError: continue - if self.archive: + if archive and self.archive: self.server.uid('copy', uid, self.archive) - self.server.uid('store', uid, "+FLAGS", "(\\Deleted)") - self.server.expunge() - return + if delete: + self.server.uid('store', uid, "+FLAGS", "(\\Deleted)") \ No newline at end of file diff --git a/django_mailbox/transports/pop3.py b/django_mailbox/transports/pop3.py index 6dbe995..3c861f0 100644 --- a/django_mailbox/transports/pop3.py +++ b/django_mailbox/transports/pop3.py @@ -42,3 +42,6 @@ class Pop3Transport(EmailTransport): self.server.dele(i + 1) self.server.quit() return + + def get_new_message_ro(self, since=None): + raise NotImplementedError("Pop3Transport.get_new_message_ro not implemented!") \ No newline at end of file