From d60a771024385ca43dae967a77577e87fe933f61 Mon Sep 17 00:00:00 2001 From: Danny Date: Mon, 3 Oct 2022 16:59:03 -0400 Subject: [PATCH] GC: TWO Message attachments (#1014) ## Description Introduces mock testing to ensure that objects with two or more attachments are restored properly. Minor change to restore pipeline for failure. attachments are restored separately in the event that one of the attachments is corrupted. ## Type of change - [x] :sunflower: Feature - [x] :robot: Test - [ ] :computer: CI/Deployment - [ ] :hamster: Trivial/Minor ## Issue(s) * closes #1007 ## Test Plan - [x] :zap: Unit test --- .../exchange/exchange_service_test.go | 6 +++- .../connector/exchange/service_restore.go | 30 +++++++++++++++++++ .../mockconnector/mock_data_message.go | 19 ++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/internal/connector/exchange/exchange_service_test.go b/src/internal/connector/exchange/exchange_service_test.go index 83ae9a8ec..994078462 100644 --- a/src/internal/connector/exchange/exchange_service_test.go +++ b/src/internal/connector/exchange/exchange_service_test.go @@ -394,6 +394,10 @@ func (suite *ExchangeServiceSuite) TestRestoreMessages() { name: "One Direct Attachment", bytes: mockconnector.GetMockMessageWithDirectAttachment(folderName), }, + { + name: "Two Attachments", + bytes: mockconnector.GetMockMessageWithTwoAttachments(folderName), + }, } for _, test := range tests { @@ -405,7 +409,7 @@ func (suite *ExchangeServiceSuite) TestRestoreMessages() { folderID, userID, ) - require.NoError(t, err) + require.NoError(t, err, support.ConnectorStackErrorTrace(err)) }) } diff --git a/src/internal/connector/exchange/service_restore.go b/src/internal/connector/exchange/service_restore.go index ecfaa7eed..9f2084257 100644 --- a/src/internal/connector/exchange/service_restore.go +++ b/src/internal/connector/exchange/service_restore.go @@ -236,6 +236,16 @@ func SendMailToBackStore( user, destination string, message models.Messageable, ) error { + var ( + attached []models.Attachmentable + errs error + ) + + if *message.GetHasAttachments() { + attached = message.GetAttachments() + message.SetAttachments([]models.Attachmentable{}) + } + sentMessage, err := service.Client().UsersById(user).MailFoldersById(destination).Messages().Post(ctx, message, nil) if err != nil { return errors.Wrap(err, @@ -247,6 +257,26 @@ func SendMailToBackStore( return errors.New("message not Sent: blocked by server") } + if len(attached) > 0 { + id := *sentMessage.GetId() + for _, attachment := range attached { + _, err = service.Client(). + UsersById(user). + MailFoldersById(destination). + MessagesById(id). + Attachments(). + Post(ctx, attachment, nil) + if err != nil { + errs = support.WrapAndAppend(id, + err, + errs, + ) + } + } + + return errs + } + return nil } diff --git a/src/internal/connector/mockconnector/mock_data_message.go b/src/internal/connector/mockconnector/mock_data_message.go index a4e555de1..03fd439a3 100644 --- a/src/internal/connector/mockconnector/mock_data_message.go +++ b/src/internal/connector/mockconnector/mock_data_message.go @@ -186,6 +186,25 @@ func GetMessageWithOneDriveAttachment(subject string) []byte { return []byte(message) } +// GetMockMessageWithTwoAttachments returns byte representation of message with two attachments +// Serialized with: kiota-serialization-json-go v0.7.1 +func GetMockMessageWithTwoAttachments(subject string) []byte { + //nolint:lll + message := "{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEMAADSEBNbUIB9RL6ePDeF3FIYAAB6LpD0AAA=\",\"@odata.type\":\"#microsoft.graph.message\",\"@odata.etag\":\"W/\\\"CQAAABYAAADSEBNbUIB9RL6ePDeF3FIYAAB5JBpO\\\"\",\"@odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#users('a4a472f8-ccb0-43ec-bf52-3697a91b926c')/messages/$entity\",\"categories\":[],\"changeKey\":\"CQAAABYAAADSEBNbUIB9RL6ePDeF3FIYAAB5JBpO\"," + + "\"createdDateTime\":\"2022-09-30T20:31:22Z\",\"lastModifiedDateTime\":\"2022-09-30T20:31:25Z\",\"attachments\":[{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEMAADSEBNbUIB9RL6ePDeF3FIYAAB6LpD0AAABEgAQAMIBac0_D4pPgtgr9mhVWaM=\",\"@odata.type\":\"#microsoft.graph.fileAttachment\",\"@odata.mediaContentType\":\"text/plain\",\"contentType\":\"text/plain\",\"isInline\":false,\"lastModifiedDateTime\":\"2022-09-30T20:31:22Z\"," + + "\"name\":\"sample.txt\",\"size\":198,\"contentBytes\":\"VFBTIFJlcG9ydHMgYXJlIGZvciB3aW5uZXJzCg==\"},{\"id\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEMAADSEBNbUIB9RL6ePDeF3FIYAAB6LpD0AAABEgAQAHO2tnfyTF1HnQKqNSMCO7A=\",\"@odata.type\":\"#microsoft.graph.fileAttachment\",\"@odata.mediaContentType\":\"text/plain\",\"contentType\":\"text/plain\",\"isInline\":false,\"lastModifiedDateTime\":\"2022-09-30T20:31:22Z\"," + + "\"name\":\"sample3.txt\",\"size\":234,\"contentBytes\":\"SWYgdGhlIGZvcmNlIGlzIHdpdGggeW91LCBpdCdzIHdpdGggeW91LiBOb3Qgb25seSBpbiBNYXkuCg==\"}],\"bccRecipients\":[],\"body\":{\"content\":\"\\r\\n
Lidia,

We have to decide between two items for our speech writers to go over. Please let me know which is the best for the " + + "upcoming retreat. 

Best, 

Dustin
\",\"contentType\":\"html\",\"@odata.type\":\"#microsoft.graph.itemBody\"},\"bodyPreview\":\"Lidia,\\r\\n\\r\\nWe have to decide between two items for our speech writers to go over. Please let me know which is the best for the upcoming retreat.\\r\\n\\r\\nBest,\\r\\n\\r\\nDustin\",\"ccRecipients\":[]," + + "\"conversationId\":\"AAQkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAQANHUb9Zc-aBAvBW5io77k-g=\",\"conversationIndex\":\"AQHY1Qss0dRv1lz9oEC8FbmKjvuT+A==\",\"flag\":{\"flagStatus\":\"notFlagged\",\"@odata.type\":\"#microsoft.graph.followupFlag\"},\"from\":{\"emailAddress\":{\"address\":\"dustina@8qzvrj.onmicrosoft.com\",\"name\":\"Dustin Abbot\",\"@odata.type\":\"#microsoft.graph.emailAddress\"},\"@odata.type\":\"#microsoft.graph.recipient\"},\"hasAttachments\":true," + + "\"importance\":\"normal\",\"inferenceClassification\":\"focused\",\"internetMessageId\":\"\",\"isDeliveryReceiptRequested\":false,\"isDraft\":false,\"isRead\":false,\"isReadReceiptRequested\":false,\"parentFolderId\":\"AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwAuAAAAAADCNgjhM9QmQYWNcI7hCpPrAQDSEBNbUIB9RL6ePDeF3FIYAAAAAAEMAAA=\",\"receivedDateTime\":\"2022-09-30T20:31:23Z\",\"replyTo\":[]," + + "\"sender\":{\"emailAddress\":{\"address\":\"dustina@8qzvrj.onmicrosoft.com\",\"name\":\"Dustin Abbot\",\"@odata.type\":\"#microsoft.graph.emailAddress\"},\"@odata.type\":\"#microsoft.graph.recipient\"},\"sentDateTime\":\"2022-09-30T20:31:19Z\"," + + "\"subject\":\"" + subject + "\",\"toRecipients\":[{\"emailAddress\":{\"address\":\"LidiaH@8qzvrj.onmicrosoft.com\",\"name\":\"Lidia Holloway\",\"@odata.type\":\"#microsoft.graph.emailAddress\"},\"@odata.type\":\"#microsoft.graph.recipient\"}],\"webLink\":\"https://outlook.office365.com/owa/?ItemID=AAMkAGZmNjNlYjI3LWJlZWYtNGI4Mi04YjMyLTIxYThkNGQ4NmY1MwBGAAAAAADCNgjhM9QmQYWNcI7hCpPrBwDSEBNbUIB9RL6ePDeF3FIYAAAAAAEMAADSEBNbUIB9RL6ePDeF3FIYAAB6LpD0AAA%3D&exvsurl=1&viewmodel=ReadMessageItem\"}" + + return []byte(message) +} + // GetMockContactBytes returns bytes for Contactable item. // When hydrated: contact.GetGivenName() shows differences func GetMockContactBytes(middleName string) []byte {