aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2020-01-31 15:58:34 -0400
committerJason Gunthorpe <jgg@mellanox.com>2020-01-31 16:11:39 -0400
commit2a8249a4c0ff136c8b6a819f700b95285258ef10 (patch)
tree8a80dc5d9b5c59483fb6ebae3ffa2dba151b9a35
parentd9343f65d319615fe59e2b0a49d90348a0541496 (diff)
downloadcloud_mdir_sync-2a8249a4c0ff136c8b6a819f700b95285258ef10.tar.gz
cloud_mdir_sync-2a8249a4c0ff136c8b6a819f700b95285258ef10.tar.bz2
cloud_mdir_sync-2a8249a4c0ff136c8b6a819f700b95285258ef10.zip
Move Office365 flag manipulation into a function
For reuse in the next patches Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r--cloud_mdir_sync/office365.py137
1 files changed, 70 insertions, 67 deletions
diff --git a/cloud_mdir_sync/office365.py b/cloud_mdir_sync/office365.py
index bf8ccf1..5742fea 100644
--- a/cloud_mdir_sync/office365.py
+++ b/cloud_mdir_sync/office365.py
@@ -533,10 +533,77 @@ class O365Mailbox(mailbox.Mailbox):
def force_content(self, msgdb, msgs):
raise RuntimeError("Cannot move messages into the Cloud")
+ 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:
+ 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)
+ modified_flags = nflags ^ cmsg.flags
+
+ # FIXME: https://docs.microsoft.com/en-us/graph/best-practices-concept#getting-minimal-responses
+ # FIXME: Does the ID change?
+ patch: Dict[str, Any] = {}
+ if modified_flags & messages.Message.FLAG_READ:
+ patch["isRead"] = bool(nflags & messages.Message.FLAG_READ)
+ if modified_flags & messages.Message.FLAG_FLAGGED:
+ patch["flag"] = {
+ "flagStatus":
+ "flagged" if nflags
+ & messages.Message.FLAG_FLAGGED else "notFlagged"
+ }
+ if modified_flags & messages.Message.FLAG_REPLIED:
+ # This can only be described as an undocumented disaster.
+ # Different clients set different things. The Icon shows up in
+ # OWS and the Mobile app. The MessageStatus shows up in
+ # IMAP. IMAP sets the MessageStatus but otherwise does not
+ # interact with the other two. We can't seem to set
+ # MessageStatus over REST because it needs RopSetMessageStatus.
+ if nflags & messages.Message.FLAG_REPLIED:
+ now = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
+ patch["singleValueExtendedProperties"] = [
+ # PidTagLastVerbExecuted
+ {
+ "id": "Integer 0x1081",
+ "value": "103"
+ },
+ # PidTagLastVerbExecutionTime
+ {
+ "id": "SystemTime 0x1082",
+ "value": now
+ },
+ # PidTagIconIndex
+ {
+ "id": "Integer 0x1080",
+ "value": "261"
+ },
+ ]
+ else:
+ # Rarely does anything undo a replied flag, but it is
+ # useful for testing.
+ patch["singleValueExtendedProperties"] = [
+ {
+ "id":
+ "Integer 0x1080", # PidTagIconIndex
+ "value":
+ "256" if nflags
+ & messages.Message.FLAG_READ else "-1"
+ },
+ ]
+ if not patch:
+ return None
+ cmsg.flags = nflags
+ return self.graph.patch_json(
+ "v1.0",
+ f"/me/mailFolders/{self.mailbox}/messages/{cmsg.storage_id}",
+ body=patch)
+
@util.log_progress(lambda self: f"Uploading local changes for {self.name}",
lambda self: f", {self.last_merge_len} changes ")
@mailbox.update_on_failure
- async def merge_content(self, msgs):
+ async def merge_content(self, msgs: messages.CHMsgMappingDict_Type):
# 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
@@ -564,76 +631,12 @@ class O365Mailbox(mailbox.Mailbox):
"v1.0",
f"/me/mailFolders/{self.mailbox}/messages/{cmsg.storage_id}/move",
body={"destinationId": "deleteditems"}))
- # FIXME: This should be after the operation completes?
del self.messages[ch]
continue
- if (lmsg.flags == old_cmsg.flags or lmsg.flags == cmsg.flags):
- continue
-
- cloud_flags = cmsg.flags ^ old_cmsg.flags
- flag_mask = messages.Message.ALL_FLAGS ^ cloud_flags
- nflags = (lmsg.flags & 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
- # FIXME: Does the ID change?
- patch: Dict[str, Any] = {}
- if modified_flags & messages.Message.FLAG_READ:
- patch["isRead"] = bool(nflags & messages.Message.FLAG_READ)
- if modified_flags & messages.Message.FLAG_FLAGGED:
- patch["flag"] = {
- "flagStatus":
- "flagged" if nflags
- & messages.Message.FLAG_FLAGGED else "notFlagged"
- }
- if modified_flags & messages.Message.FLAG_REPLIED:
- # This can only be described as an undocumented disaster.
- # Different clients set different things. The Icon shows up in
- # OWS and the Mobile app. The MessageStatus shows up in
- # IMAP. IMAP sets the MessageStatus but otherwise does not
- # interact with the other two. We can't seem to set
- # MessageStatus over REST because it needs RopSetMessageStatus.
- if nflags & messages.Message.FLAG_REPLIED:
- now = datetime.datetime.utcnow().strftime(
- "%Y-%m-%dT%H:%M:%SZ")
- patch["singleValueExtendedProperties"] = [
- # PidTagLastVerbExecuted
- {
- "id": "Integer 0x1081",
- "value": "103"
- },
- # PidTagLastVerbExecutionTime
- {
- "id": "SystemTime 0x1082",
- "value": now
- },
- # PidTagIconIndex
- {
- "id": "Integer 0x1080",
- "value": "261"
- },
- ]
- else:
- # Rarely does anything undo a replied flag, but it is
- # useful for testing.
- patch["singleValueExtendedProperties"] = [
- {
- "id":
- "Integer 0x1080", # PidTagIconIndex
- "value":
- "256" if nflags
- & messages.Message.FLAG_READ else "-1"
- },
- ]
-
+ patch = self._update_msg_flags(cmsg, old_cmsg.flags, lmsg)
if patch:
- todo.append(
- self.graph.patch_json(
- "v1.0",
- f"/me/mailFolders/{self.mailbox}/messages/{cmsg.storage_id}",
- body=patch))
- cmsg.flags = nflags
+ todo.append(patch)
await asyncio.gather(*todo)
self.last_merge_len = len(todo)