Compare commits
12 Commits
main
...
2353-messa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f6db27618 | ||
|
|
77e41f285d | ||
|
|
2bfc7f180d | ||
|
|
6f592c144e | ||
|
|
cbad4b6070 | ||
|
|
2a426f17a1 | ||
|
|
c5a36665e5 | ||
|
|
d8de4ddc6d | ||
|
|
83d239ac11 | ||
|
|
a7c56a7d24 | ||
|
|
52572f9e88 | ||
|
|
61d3fc9d53 |
@ -3,11 +3,13 @@ package exchange
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/internal/connector/support"
|
||||||
"github.com/alcionai/corso/src/internal/connector/uploadsession"
|
"github.com/alcionai/corso/src/internal/connector/uploadsession"
|
||||||
"github.com/alcionai/corso/src/pkg/logger"
|
"github.com/alcionai/corso/src/pkg/logger"
|
||||||
)
|
)
|
||||||
@ -44,7 +46,11 @@ func uploadAttachment(
|
|||||||
attachment models.Attachmentable,
|
attachment models.Attachmentable,
|
||||||
) error {
|
) error {
|
||||||
logger.Ctx(ctx).Debugf("uploading attachment with size %d", *attachment.GetSize())
|
logger.Ctx(ctx).Debugf("uploading attachment with size %d", *attachment.GetSize())
|
||||||
attachmentType := attachmentType(attachment)
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
attachmentType = attachmentType(attachment)
|
||||||
|
)
|
||||||
|
|
||||||
// Reference attachments that are inline() do not need to be recreated. The contents are part of the body.
|
// Reference attachments that are inline() do not need to be recreated. The contents are part of the body.
|
||||||
if attachmentType == models.REFERENCE_ATTACHMENTTYPE &&
|
if attachmentType == models.REFERENCE_ATTACHMENTTYPE &&
|
||||||
@ -55,13 +61,26 @@ func uploadAttachment(
|
|||||||
|
|
||||||
// item Attachments to be skipped until the completion of Issue #2353
|
// item Attachments to be skipped until the completion of Issue #2353
|
||||||
if attachmentType == models.ITEM_ATTACHMENTTYPE {
|
if attachmentType == models.ITEM_ATTACHMENTTYPE {
|
||||||
logger.Ctx(ctx).Infow("item attachment uploads are not supported ",
|
name := ""
|
||||||
"attachment_name", *attachment.GetName(), // TODO: Update to support PII protection
|
if attachment.GetName() != nil {
|
||||||
"attachment_type", attachmentType,
|
name = *attachment.GetName()
|
||||||
"attachment_id", *attachment.GetId(),
|
}
|
||||||
)
|
|
||||||
|
|
||||||
return nil
|
prev := attachment
|
||||||
|
|
||||||
|
attachment, err = support.ToItemAttachment(attachment)
|
||||||
|
if err != nil {
|
||||||
|
logger.Ctx(ctx).Infow("item attachment uploads are not supported ",
|
||||||
|
"attachment_name", name, // TODO: Update to support PII protection
|
||||||
|
"attachment_type", models.ITEM_ATTACHMENTTYPE,
|
||||||
|
"internal_item_type", getItemAttachmentItemType(prev),
|
||||||
|
"attachment_id", prev,
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Printf("Error returned: %v\n", err)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Item/Reference attachments *or* file attachments < 3MB, use the attachments endpoint
|
// For Item/Reference attachments *or* file attachments < 3MB, use the attachments endpoint
|
||||||
@ -101,3 +120,19 @@ func uploadLargeAttachment(ctx context.Context, uploader attachmentUploadable,
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getItemAttachmentItemType(query models.Attachmentable) string {
|
||||||
|
empty := ""
|
||||||
|
attachment, ok := query.(models.ItemAttachmentable)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
|
||||||
|
item := attachment.GetItem()
|
||||||
|
if item.GetOdataType() == nil {
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
|
||||||
|
return *item.GetOdataType()
|
||||||
|
}
|
||||||
|
|||||||
@ -176,7 +176,7 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Test Mail: Item Attachment",
|
name: "Test Mail: Event Item Attachment",
|
||||||
bytes: mockconnector.GetMockMessageWithItemAttachmentEvent("Event Item Attachment"),
|
bytes: mockconnector.GetMockMessageWithItemAttachmentEvent("Event Item Attachment"),
|
||||||
category: path.EmailCategory,
|
category: path.EmailCategory,
|
||||||
destination: func(t *testing.T, ctx context.Context) string {
|
destination: func(t *testing.T, ctx context.Context) string {
|
||||||
@ -187,6 +187,18 @@ func (suite *ExchangeRestoreSuite) TestRestoreExchangeObject() {
|
|||||||
return *folder.GetId()
|
return *folder.GetId()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Test Mail: Mail Item Attachment",
|
||||||
|
bytes: mockconnector.GetMockMessageWithItemAttachmentMessage("Message Item Attachment"),
|
||||||
|
category: path.EmailCategory,
|
||||||
|
destination: func(t *testing.T, ctx context.Context) string {
|
||||||
|
folderName := "TestRestoreMailItemAttachMail: " + common.FormatSimpleDateTime(now)
|
||||||
|
folder, err := suite.ac.Mail().CreateMailFolder(ctx, userID, folderName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return *folder.GetId()
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Test Mail: One Large Attachment",
|
name: "Test Mail: One Large Attachment",
|
||||||
bytes: mockconnector.GetMockMessageWithLargeAttachment("Restore Large Attachment"),
|
bytes: mockconnector.GetMockMessageWithLargeAttachment("Restore Large Attachment"),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -1,11 +1,14 @@
|
|||||||
package support
|
package support
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const itmAttachment = "#microsoft.graph.itemAttachment"
|
||||||
|
|
||||||
// CloneMessageableFields places data from original data into new message object.
|
// CloneMessageableFields places data from original data into new message object.
|
||||||
// SingleLegacyValueProperty is not populated during this operation
|
// SingleLegacyValueProperty is not populated during this operation
|
||||||
func CloneMessageableFields(orig, message models.Messageable) models.Messageable {
|
func CloneMessageableFields(orig, message models.Messageable) models.Messageable {
|
||||||
@ -278,3 +281,137 @@ func cloneColumnDefinitionable(orig models.ColumnDefinitionable) models.ColumnDe
|
|||||||
|
|
||||||
return newColumn
|
return newColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToItemAttachment transforms internal item, OutlookItemables, into
|
||||||
|
// objects that are able to be uploaded into M365.
|
||||||
|
// Supported Internal Items:
|
||||||
|
// - Events
|
||||||
|
func ToItemAttachment(orig models.Attachmentable) (models.Attachmentable, error) {
|
||||||
|
// First things first. Find out where all the information is
|
||||||
|
transform, ok := orig.(models.ItemAttachmentable)
|
||||||
|
supported := "#microsoft.graph.event"
|
||||||
|
messageType := "#microsoft.graph.message"
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("transforming attachment to item attachment")
|
||||||
|
}
|
||||||
|
|
||||||
|
item := transform.GetItem()
|
||||||
|
itemType := item.GetOdataType()
|
||||||
|
fmt.Println(*itemType)
|
||||||
|
|
||||||
|
switch *itemType {
|
||||||
|
case supported:
|
||||||
|
event := item.(models.Eventable)
|
||||||
|
|
||||||
|
newEvent, err := sanitizeEvent(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
transform.SetItem(newEvent)
|
||||||
|
|
||||||
|
return transform, nil
|
||||||
|
case messageType:
|
||||||
|
message := item.(models.Messageable)
|
||||||
|
|
||||||
|
msg, err := sanitizeMessage(message)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
transform.SetItem(msg)
|
||||||
|
|
||||||
|
return transform, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ItemAttachment Type: %s not supported", *itemType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitizeEvent(orig models.Eventable) (models.Eventable, error) {
|
||||||
|
newEvent := models.NewEvent()
|
||||||
|
newEvent.SetAttendees(orig.GetAttendees())
|
||||||
|
newEvent.SetBody(orig.GetBody())
|
||||||
|
newEvent.SetBodyPreview(orig.GetBodyPreview())
|
||||||
|
newEvent.SetCalendar(orig.GetCalendar())
|
||||||
|
newEvent.SetCreatedDateTime(orig.GetCreatedDateTime())
|
||||||
|
newEvent.SetEnd(orig.GetEnd())
|
||||||
|
newEvent.SetHasAttachments(orig.GetHasAttachments())
|
||||||
|
newEvent.SetHideAttendees(orig.GetHideAttendees())
|
||||||
|
newEvent.SetImportance(orig.GetImportance())
|
||||||
|
newEvent.SetIsAllDay(orig.GetIsAllDay())
|
||||||
|
newEvent.SetIsOnlineMeeting(orig.GetIsOnlineMeeting())
|
||||||
|
newEvent.SetLocation(orig.GetLocation())
|
||||||
|
newEvent.SetLocations(orig.GetLocations())
|
||||||
|
newEvent.SetSensitivity(orig.GetSensitivity())
|
||||||
|
newEvent.SetReminderMinutesBeforeStart(orig.GetReminderMinutesBeforeStart())
|
||||||
|
newEvent.SetStart(orig.GetStart())
|
||||||
|
newEvent.SetSubject(orig.GetSubject())
|
||||||
|
newEvent.SetType(orig.GetType())
|
||||||
|
|
||||||
|
// Sanitation
|
||||||
|
adtl := orig.GetAdditionalData()
|
||||||
|
adtl["isOrganizer"] = orig.GetIsOrganizer()
|
||||||
|
adtl["isDraft"] = orig.GetIsDraft()
|
||||||
|
|
||||||
|
newEvent.SetIsOrganizer(nil)
|
||||||
|
newEvent.SetIsDraft(nil)
|
||||||
|
newEvent.SetAdditionalData(adtl)
|
||||||
|
|
||||||
|
attached := orig.GetAttachments()
|
||||||
|
attachments := make([]models.Attachmentable, len(attached))
|
||||||
|
|
||||||
|
for _, ax := range attached {
|
||||||
|
if *ax.GetOdataType() == "#microsoft.graph.itemAttachment" {
|
||||||
|
newAttachment, err := ToItemAttachment(ax)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments = append(attachments, newAttachment)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments = append(attachments, ax)
|
||||||
|
}
|
||||||
|
|
||||||
|
newEvent.SetAttachments(attachments)
|
||||||
|
|
||||||
|
return newEvent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitizeMessage(orig models.Messageable) (models.Messageable, error) {
|
||||||
|
newMessage := ToMessage(orig)
|
||||||
|
newMessage.SetInternetMessageHeaders(nil)
|
||||||
|
|
||||||
|
attachments, err := sanitizeAttachments(newMessage.GetAttachments())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newMessage.SetAttachments(attachments)
|
||||||
|
|
||||||
|
return newMessage, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitizeAttachments(attached []models.Attachmentable) ([]models.Attachmentable, error) {
|
||||||
|
attachments := make([]models.Attachmentable, len(attached))
|
||||||
|
|
||||||
|
for _, entry := range attached {
|
||||||
|
if entry.GetOdataType() != nil || *entry.GetOdataType() == "#microsoft.graph.itemAttachment" {
|
||||||
|
newAttachment, err := ToItemAttachment(entry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments = append(attachments, newAttachment)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments = append(attachments, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return attachments, nil
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user