Sent / Receive DateTime Stamp Incorrect (#792)
## Description Single Legacy Policies added to allow the values for sent / receive times to correspond to the original content for `exchange.Mail` objects ## Type of change - [x] 🐛 Bugfix ## Issue(s) <!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. --> *closes #645 ## Test Plan <!-- How will this be tested prior to merging.--> - [x] 💪 Manual Values can be inspected using e2e restore pipelines.
This commit is contained in:
parent
f509543856
commit
2e3ee15fd4
@ -8,6 +8,7 @@ import (
|
||||
const (
|
||||
StandardTimeFormat = time.RFC3339Nano
|
||||
SimpleDateTimeFormat = "02-Jan-2006_15:04:05"
|
||||
LegacyFormat = time.RFC3339
|
||||
)
|
||||
|
||||
// FormatNow produces the current time in UTC using the provided
|
||||
@ -28,6 +29,12 @@ func FormatSimpleDateTime(t time.Time) string {
|
||||
return t.UTC().Format(SimpleDateTimeFormat)
|
||||
}
|
||||
|
||||
// FormatLegacyTime produces standard format for string values
|
||||
// that are placed in SingleValueExtendedProperty tags
|
||||
func FormatLegacyTime(t time.Time) string {
|
||||
return t.UTC().Format(LegacyFormat)
|
||||
}
|
||||
|
||||
// ParseTime makes a best attempt to produce a time value from
|
||||
// the provided string. Always returns a UTC timezone value.
|
||||
func ParseTime(s string) (time.Time, error) {
|
||||
|
||||
@ -26,6 +26,13 @@ func (suite *CommonTimeUnitSuite) TestFormatTime() {
|
||||
assert.Equal(t, now.UTC().Format(time.RFC3339Nano), result)
|
||||
}
|
||||
|
||||
func (suite *CommonTimeUnitSuite) TestLegacyTime() {
|
||||
t := suite.T()
|
||||
now := time.Now()
|
||||
result := common.FormatLegacyTime(now)
|
||||
assert.Equal(t, now.UTC().Format(time.RFC3339), result)
|
||||
}
|
||||
|
||||
func (suite *CommonTimeUnitSuite) TestParseTime() {
|
||||
t := suite.T()
|
||||
now := time.Now()
|
||||
|
||||
@ -407,6 +407,33 @@ func (suite *ExchangeServiceSuite) TestGetContainerID() {
|
||||
}
|
||||
}
|
||||
|
||||
// Restore Functions
|
||||
// TestRestoreMessages uses mock data to ensure GraphConnector
|
||||
// is able to restore a several messageable item to a Mailbox.
|
||||
// The result should be all successful items restored within the same folder.
|
||||
func (suite *ExchangeServiceSuite) TestRestoreMessages() {
|
||||
t := suite.T()
|
||||
userID := tester.M365UserID(t)
|
||||
now := time.Now()
|
||||
|
||||
folderName := "TestRestoreMessage: " + common.FormatSimpleDateTime(now)
|
||||
folder, err := CreateMailFolder(suite.es, userID, folderName)
|
||||
require.NoError(t, err)
|
||||
|
||||
folderID := *folder.GetId()
|
||||
|
||||
err = RestoreMailMessage(context.Background(),
|
||||
mockconnector.GetMockMessageBytes("Exchange Service Mail Test"),
|
||||
suite.es,
|
||||
control.Copy,
|
||||
folderID,
|
||||
userID,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
err = DeleteMailFolder(suite.es, userID, folderID)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// TestRestoreContact ensures contact object can be created, placed into
|
||||
// the Corso Folder. The function handles test clean-up.
|
||||
func (suite *ExchangeServiceSuite) TestRestoreContact() {
|
||||
|
||||
@ -448,14 +448,29 @@ func RestoreMailMessage(
|
||||
clone := support.ToMessage(originalMessage)
|
||||
valueID := RestorePropertyTag
|
||||
enableValue := RestoreCanonicalEnableValue
|
||||
sv := models.NewSingleValueLegacyExtendedProperty()
|
||||
sv.SetId(&valueID)
|
||||
sv.SetValue(&enableValue)
|
||||
svlep := []models.SingleValueLegacyExtendedPropertyable{sv}
|
||||
clone.SetSingleValueExtendedProperties(svlep)
|
||||
|
||||
draft := false
|
||||
clone.SetIsDraft(&draft)
|
||||
// Set Extended Properties:
|
||||
// 1st: No transmission
|
||||
// 2nd: Send Date
|
||||
// 3rd: Recv Date
|
||||
sv1 := models.NewSingleValueLegacyExtendedProperty()
|
||||
sv1.SetId(&valueID)
|
||||
sv1.SetValue(&enableValue)
|
||||
|
||||
sv2 := models.NewSingleValueLegacyExtendedProperty()
|
||||
sendPropertyValue := common.FormatLegacyTime(*clone.GetSentDateTime())
|
||||
sendPropertyTag := "SystemTime 0x0039"
|
||||
sv2.SetId(&sendPropertyTag)
|
||||
sv2.SetValue(&sendPropertyValue)
|
||||
|
||||
sv3 := models.NewSingleValueLegacyExtendedProperty()
|
||||
recvPropertyValue := common.FormatLegacyTime(*clone.GetReceivedDateTime())
|
||||
recvPropertyTag := "SystemTime 0x0E06"
|
||||
sv3.SetId(&recvPropertyTag)
|
||||
sv3.SetValue(&recvPropertyValue)
|
||||
|
||||
svlep := []models.SingleValueLegacyExtendedPropertyable{sv1, sv2, sv3}
|
||||
clone.SetSingleValueExtendedProperties(svlep)
|
||||
|
||||
// Switch workflow based on collision policy
|
||||
switch cp {
|
||||
@ -482,5 +497,9 @@ func SendMailToBackStore(service graph.Service, user, destination string, messag
|
||||
return errors.New("message not Sent: blocked by server")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return support.WrapAndAppend(": "+support.ConnectorStackErrorTrace(err), err, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -14,10 +14,8 @@ import (
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common"
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange"
|
||||
"github.com/alcionai/corso/src/internal/connector/mockconnector"
|
||||
"github.com/alcionai/corso/src/internal/connector/support"
|
||||
"github.com/alcionai/corso/src/internal/data"
|
||||
"github.com/alcionai/corso/src/internal/path"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
)
|
||||
@ -240,32 +238,6 @@ func (suite *GraphConnectorIntegrationSuite) TestEventsSerializationRegression()
|
||||
suite.Equal(status.ObjectCount, status.Successful)
|
||||
}
|
||||
|
||||
// Restore Functions
|
||||
// TestRestoreMessages uses mock data to ensure GraphConnector
|
||||
// is able to restore a several messageable item to a Mailbox.
|
||||
// The result should be all successful items restored within the same folder.
|
||||
func (suite *GraphConnectorIntegrationSuite) TestRestoreMessages() {
|
||||
t := suite.T()
|
||||
category := path.EmailCategory
|
||||
connector := loadConnector(t)
|
||||
collection := make([]data.Collection, 0)
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
mdc := mockconnector.NewMockExchangeCollection(
|
||||
[]string{"tenant", path.ExchangeService.String(), suite.user, category.String(), "Inbox"},
|
||||
1)
|
||||
collection = append(collection, mdc)
|
||||
}
|
||||
|
||||
err := connector.RestoreExchangeDataCollection(context.Background(), collection)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
status := connector.AwaitStatus()
|
||||
assert.NotNil(t, status)
|
||||
assert.Equal(t, status.ObjectCount, status.Successful)
|
||||
assert.Equal(t, status.FolderCount, 1)
|
||||
}
|
||||
|
||||
// TestAccessOfInboxAllUsers verifies that GraphConnector can
|
||||
// support `--all-users` for backup operations. Selector.DiscreteScopes
|
||||
// returns all of the users within one scope. Only users who have
|
||||
|
||||
@ -38,6 +38,7 @@ func CloneMessageableFields(orig, message models.Messageable) models.Messageable
|
||||
message.SetInternetMessageId(orig.GetInternetMessageId())
|
||||
message.SetInternetMessageHeaders(orig.GetInternetMessageHeaders())
|
||||
message.SetIsDeliveryReceiptRequested(orig.GetIsDeliveryReceiptRequested())
|
||||
message.SetIsDraft(orig.GetIsDraft())
|
||||
message.SetIsRead(orig.GetIsRead())
|
||||
message.SetIsReadReceiptRequested(orig.GetIsReadReceiptRequested())
|
||||
message.SetParentFolderId(orig.GetParentFolderId())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user