aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2020-01-31 16:10:52 -0400
committerJason Gunthorpe <jgg@mellanox.com>2020-01-31 16:48:07 -0400
commit184b8f4bc8a820c43e40dbc205974f196d6bf234 (patch)
tree6989858a8ed63b7be4dfd068493bd4cdb128b422
parent5a8e0e554679223319d03a242e7985602fe66bcb (diff)
downloadcloud_mdir_sync-184b8f4bc8a820c43e40dbc205974f196d6bf234.tar.gz
cloud_mdir_sync-184b8f4bc8a820c43e40dbc205974f196d6bf234.tar.bz2
cloud_mdir_sync-184b8f4bc8a820c43e40dbc205974f196d6bf234.zip
Support FLAG_DELETED in Office365
When a local message is tagged deleted then update the cloud flags and delete the message. Using the Trash flag in a mail dir allows the cloud upload step to see the original message and then upload the local flags before deleting it. For instance, this will allow the Replied flag to be set upon deletion. Once deleted in the cloud the next sync iteration will delete the message locally. Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r--cloud_mdir_sync/office365.py42
1 files changed, 26 insertions, 16 deletions
diff --git a/cloud_mdir_sync/office365.py b/cloud_mdir_sync/office365.py
index 5742fea..1400ced 100644
--- a/cloud_mdir_sync/office365.py
+++ b/cloud_mdir_sync/office365.py
@@ -535,12 +535,14 @@ class O365Mailbox(mailbox.Mailbox):
def _update_msg_flags(self, cmsg: messages.Message,
old_cmsg_flags: int, lmsg: messages.Message):
- if lmsg.flags == old_cmsg_flags or lmsg.flags == cmsg.flags:
+ lflags = lmsg.flags & (messages.Message.ALL_FLAGS
+ ^ messages.Message.FLAG_DELETED)
+ if lflags == old_cmsg_flags or lflags == cmsg.flags:
return None
cloud_flags = cmsg.flags ^ old_cmsg_flags
flag_mask = messages.Message.ALL_FLAGS ^ cloud_flags
- nflags = (lmsg.flags & flag_mask) | (cmsg.flags & cloud_flags)
+ nflags = (lflags & flag_mask) | (cmsg.flags & cloud_flags)
modified_flags = nflags ^ cmsg.flags
# FIXME: https://docs.microsoft.com/en-us/graph/best-practices-concept#getting-minimal-responses
@@ -607,7 +609,8 @@ class O365Mailbox(mailbox.Mailbox):
# There is a batching API for this kind of stuff as well:
# https://docs.microsoft.com/en-us/graph/json-batching
self.last_merge_len = 0
- todo = []
+ todo_flags = []
+ todo_del = []
if self.cfg.trace_file is not None:
pickle.dump(["merge_content", self.name, self.messages, msgs],
self.cfg.trace_file)
@@ -617,26 +620,33 @@ class O365Mailbox(mailbox.Mailbox):
# old_cmsg is the original cloud message from the last sync
lmsg, old_cmsg = mpair
cmsg = self.messages.get(ch)
+ assert old_cmsg is not None
- # Cloud message was deleted, cloud takes priority
- if cmsg is None:
- continue
- if lmsg is None:
- # Debugging that the message really is to be deleted
+ # Update flags
+ if cmsg is not None and old_cmsg is not None and lmsg is not None:
+ patch = self._update_msg_flags(cmsg, old_cmsg.flags, lmsg)
+ if patch:
+ todo_flags.append(patch)
+
+ # Debugging that the message really is to be deleted
+ if cmsg is not None and lmsg is None:
assert os.stat(os.path.join(self.cfg.msgdb.hashes_dir,
ch)).st_nlink == 1
+
+ # This only happens if the user is not using DeletedMailDir and
+ # the delete_msgs path below
+ if cmsg is not None and (lmsg is None or lmsg.flags
+ & messages.Message.FLAG_DELETED):
# Delete cloud message
- todo.append(
+ todo_del.append(
self.graph.post_json(
"v1.0",
f"/me/mailFolders/{self.mailbox}/messages/{cmsg.storage_id}/move",
body={"destinationId": "deleteditems"}))
del self.messages[ch]
- continue
- patch = self._update_msg_flags(cmsg, old_cmsg.flags, lmsg)
- if patch:
- todo.append(patch)
-
- await asyncio.gather(*todo)
- self.last_merge_len = len(todo)
+ await asyncio.gather(*todo_flags)
+ # Delete must be temporally after move as move will change the mailbox
+ # id.
+ await asyncio.gather(*todo_del)
+ self.last_merge_len = len(todo_flags) + len(todo_del)