From d7806757c54ebcd41b20eddc45bae41266e19572 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Wed, 2 Sep 2020 01:34:18 +0200 Subject: [PATCH] Polished mail integration --- platypush/backend/mail.py | 8 ++--- platypush/message/event/mail.py | 3 +- platypush/plugins/mail/imap.py | 56 ++++++++++++++++++++++++++------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/platypush/backend/mail.py b/platypush/backend/mail.py index 80da1eebe0..6860752865 100644 --- a/platypush/backend/mail.py +++ b/platypush/backend/mail.py @@ -227,16 +227,16 @@ class MailBackend(Backend): for msg in unread: if msg.date and last_checked_date and msg.date < last_checked_date: continue - self.bus.post(MailReceivedEvent(mailbox=self.mailboxes[mailbox_id].name, msg=msg)) + self.bus.post(MailReceivedEvent(mailbox=self.mailboxes[mailbox_id].name, message=msg)) for msg in seen: - self.bus.post(MailSeenEvent(mailbox=self.mailboxes[mailbox_id].name, msg=msg)) + self.bus.post(MailSeenEvent(mailbox=self.mailboxes[mailbox_id].name, message=msg)) for msg in flagged: - self.bus.post(MailFlaggedEvent(mailbox=self.mailboxes[mailbox_id].name, msg=msg)) + self.bus.post(MailFlaggedEvent(mailbox=self.mailboxes[mailbox_id].name, message=msg)) for msg in unflagged: - self.bus.post(MailUnflaggedEvent(mailbox=self.mailboxes[mailbox_id].name, msg=msg)) + self.bus.post(MailUnflaggedEvent(mailbox=self.mailboxes[mailbox_id].name, message=msg)) def _check_mailboxes(self) -> List[Tuple[Dict[int, Mail], Dict[int, Mail]]]: workers = [] diff --git a/platypush/message/event/mail.py b/platypush/message/event/mail.py index ec94b3a3ca..7d5edea801 100644 --- a/platypush/message/event/mail.py +++ b/platypush/message/event/mail.py @@ -1,10 +1,11 @@ from typing import Optional, Dict from platypush.message.event import Event +from platypush.plugins.mail import Mail class MailEvent(Event): - def __init__(self, mailbox: str, message: Optional[Dict] = None, *args, **kwargs): + def __init__(self, mailbox: str, message: Optional[Mail] = None, *args, **kwargs): super().__init__(*args, mailbox=mailbox, message=message or {}, **kwargs) diff --git a/platypush/plugins/mail/imap.py b/platypush/plugins/mail/imap.py index 8d548728f3..23dafcb1ec 100644 --- a/platypush/plugins/mail/imap.py +++ b/platypush/plugins/mail/imap.py @@ -356,11 +356,11 @@ class MailImapPlugin(MailInPlugin): return msg_ids @action - def get_message(self, id: int, folder: str = 'INBOX', **connect_args) -> Mail: + def get_message(self, message: int, folder: str = 'INBOX', **connect_args) -> Mail: """ Get the full content of a message given the ID returned by :meth:`.search`. - :param id: Message ID. + :param message: Message ID. :param folder: Folder name (default: ``INBOX``). :param connect_args: Arguments to pass to :meth:`._get_server_info` for server configuration override. :return: A message in the same format as :meth:`.search`, with an added ``payload`` attribute containing the @@ -368,11 +368,11 @@ class MailImapPlugin(MailInPlugin): """ with self.connect(**connect_args) as client: client.select_folder(folder, readonly=True) - data = client.fetch(id, ['ALL', 'RFC822']) - assert id in data, 'No such message ID: {}'.format(id) + data = client.fetch(message, ['ALL', 'RFC822']) + assert message in data, 'No such message ID: {}'.format(message) - data = data[id] - ret = self._parse_message(id, data) + data = data[message] + ret = self._parse_message(message, data) msg = email.message_from_bytes(data[b'RFC822']) ret.payload = msg.get_payload() @@ -413,8 +413,14 @@ class MailImapPlugin(MailInPlugin): with self.connect(**connect_args) as client: client.delete_folder(folder) + @staticmethod + def _convert_flags(flags: Union[str, List[str]]) -> List[bytes]: + if isinstance(flags, str): + flags = [flag.strip() for flag in flags.split(',')] + return [('\\' + flag).encode() for flag in flags] + @action - def add_flags(self, messages: List[int], flags: List[str], folder: str = 'INBOX', **connect_args): + def add_flags(self, messages: List[int], flags: Union[str, List[str]], folder: str = 'INBOX', **connect_args): """ Add a set of flags to the specified set of message IDs. @@ -432,10 +438,10 @@ class MailImapPlugin(MailInPlugin): """ with self.connect(**connect_args) as client: client.select_folder(folder) - client.add_flags(messages, flags) + client.add_flags(messages, self._convert_flags(flags)) @action - def set_flags(self, messages: List[int], flags: List[str], folder: str = 'INBOX', **connect_args): + def set_flags(self, messages: List[int], flags: Union[str, List[str]], folder: str = 'INBOX', **connect_args): """ Set a set of flags to the specified set of message IDs. @@ -453,10 +459,10 @@ class MailImapPlugin(MailInPlugin): """ with self.connect(**connect_args) as client: client.select_folder(folder) - client.set_flags(messages, flags) + client.set_flags(messages, self._convert_flags(flags)) @action - def remove_flags(self, messages: List[int], flags: List[str], folder: str = 'INBOX', **connect_args): + def remove_flags(self, messages: List[int], flags: Union[str, List[str]], folder: str = 'INBOX', **connect_args): """ Remove a set of flags to the specified set of message IDs. @@ -474,7 +480,7 @@ class MailImapPlugin(MailInPlugin): """ with self.connect(**connect_args) as client: client.select_folder(folder) - client.remove_flags(messages, flags) + client.remove_flags(messages, self._convert_flags(flags)) @action def flag_messages(self, messages: List[int], folder: str = 'INBOX', **connect_args): @@ -520,6 +526,32 @@ class MailImapPlugin(MailInPlugin): """ return self.unflag_messages([message], folder=folder, **connect_args) + @action + def delete_messages(self, messages: List[int], folder: str = 'INBOX', expunge: bool = True, **connect_args): + """ + Set a specified set of message IDs as deleted. + + :param messages: List of message IDs. + :param folder: IMAP folder (default: ``INBOX``). + :param expunge: If set then the messages will also be expunged from the folder, otherwise they will only be + marked as deleted (default: ``True``). + :param connect_args: Arguments to pass to :meth:`._get_server_info` for server configuration override. + """ + self.add_flags(messages, ['Deleted'], folder=folder, **connect_args) + if expunge: + self.expunge_messages(folder=folder, messages=messages, **connect_args) + + @action + def undelete_messages(self, messages: List[int], folder: str = 'INBOX', **connect_args): + """ + Remove the ``Deleted`` flag from the specified set of message IDs. + + :param messages: List of message IDs. + :param folder: IMAP folder (default: ``INBOX``). + :param connect_args: Arguments to pass to :meth:`._get_server_info` for server configuration override. + """ + return self.remove_flags(messages, ['Deleted'], folder=folder, **connect_args) + @action def copy_messages(self, messages: List[int], dest_folder: str, source_folder: str = 'INBOX', **connect_args): """