diff --git a/src/internal/m365/collection/groups/conversation_handler.go b/src/internal/m365/collection/groups/conversation_handler.go index 2fb02f09e..f36be0e93 100644 --- a/src/internal/m365/collection/groups/conversation_handler.go +++ b/src/internal/m365/collection/groups/conversation_handler.go @@ -19,15 +19,19 @@ var _ backupHandler[models.Conversationable, models.Postable] = &conversationsBa type conversationsBackupHandler struct { ac api.Conversations protectedResource string + // SMTP address for the group + resourceEmail string } func NewConversationBackupHandler( protectedResource string, ac api.Conversations, + resourceEmail string, ) conversationsBackupHandler { return conversationsBackupHandler{ ac: ac, protectedResource: protectedResource, + resourceEmail: resourceEmail, } } @@ -134,6 +138,14 @@ func (bh conversationsBackupHandler) augmentItemInfo( dgi *details.GroupsInfo, c models.Conversationable, ) { + // Posts are always sent to the group email address, along with additional + // recipients if any. Currently we don't have a way to get the unique + // recipient list for individual posts due to graph api limitations. + // + // Store the group mail address in details so that SDK users can use it. + // This information will also be persisted in metadata files so that we + // can use it during export & restore. + dgi.Post.Recipients = []string{bh.resourceEmail} dgi.Post.Topic = ptr.Val(c.GetTopic()) } diff --git a/src/internal/m365/service/groups/backup.go b/src/internal/m365/service/groups/backup.go index 4dcae200a..07b1e1ada 100644 --- a/src/internal/m365/service/groups/backup.go +++ b/src/internal/m365/service/groups/backup.go @@ -3,6 +3,7 @@ package groups import ( "context" "fmt" + "strings" "github.com/alcionai/clues" "github.com/kopia/kopia/repo/manifest" @@ -319,10 +320,17 @@ func backupConversations( counter *count.Bus, errs *fault.Bus, ) ([]data.BackupCollection, error) { + groupEmail := strings.Clone(ptr.Val(bc.group.GetMail())) + // This is unlikely, but if it does happen in the wild, we should investigate it. + if len(groupEmail) == 0 { + return nil, clues.New("group has no mail address") + } + var ( bh = groups.NewConversationBackupHandler( bc.producerConfig.ProtectedResource.ID(), - bc.apiCli.Conversations()) + bc.apiCli.Conversations(), + groupEmail) colls []data.BackupCollection ) diff --git a/src/pkg/backup/details/groups.go b/src/pkg/backup/details/groups.go index 99829f05a..34f167e77 100644 --- a/src/pkg/backup/details/groups.go +++ b/src/pkg/backup/details/groups.go @@ -61,11 +61,12 @@ type GroupsInfo struct { } type ConversationPostInfo struct { - CreatedAt time.Time `json:"createdAt,omitempty"` - Creator string `json:"creator,omitempty"` - Preview string `json:"preview,omitempty"` - Size int64 `json:"size,omitempty"` - Topic string `json:"topic,omitempty"` + CreatedAt time.Time `json:"createdAt,omitempty"` + Creator string `json:"creator,omitempty"` + Preview string `json:"preview,omitempty"` + Recipients []string `json:"recipients,omitempty"` + Size int64 `json:"size,omitempty"` + Topic string `json:"topic,omitempty"` } type ChannelMessageInfo struct {