使用 Microsoft Graph 将第三方平台消息导入 TeamsImport third-party platform messages to Teams using Microsoft Graph

重要

Microsoft Graph 和 Microsoft 团队公开预览版适用于早期访问和反馈。Microsoft Graph and Microsoft Teams public previews are available for early-access and feedback. 尽管此版本已经历大量测试,但不适合在生产中使用。Although this release has undergone extensive testing, it is not intended for use in production.

使用 Microsoft Graph,可以将用户的现有邮件历史记录和数据从外部系统迁移到团队频道。With Microsoft Graph, you can migrate users' existing message history and data from an external system into a Teams channel. 通过在团队内启用第三方平台邮件传递层次结构,用户可以采用无缝方式继续进行通信并继续进行而不会中断。By enabling the recreation of a third-party platform messaging hierarchy inside Teams, users can continue their communications in a seamless manner and proceed without interruption.

导入概述Import overview

从较高的层次来看,导入过程包含以下内容:At a high level, the import process consists of the following:

  1. 创建具有后时间戳的团队Create a team with a back-in-time timestamp
  2. 使用后向时间戳创建通道Create a channel with a back-in-time timestamp
  3. 导入外部定期邮件Import external back-in-time dated messages
  4. 完成团队和渠道迁移过程Complete the team and channel migration process
  5. 添加团队成员Add team members

必需的要求Necessary requirements

分析和准备邮件数据Analyze and prepare message data

✔查看第三方数据以确定将迁移的内容。✔ Review the third-party data to decide what will be migrated.
✔从第三方聊天系统中提取所选数据。✔ Extract the selected data from the third-party chat system.
✔将导入数据转换为迁移所需的格式。✔ Convert import data into format needed for migration.
✔将第三方聊天结构映射到团队结构。✔ Map the third-party chat structure to the Teams structure.

设置 Office 365 租户Set up your Office 365 tenant

✔确保导入数据存在 Office 365 租户。✔ Ensure that an Office 365 tenant exists for the import data. 有关为团队设置 Office 365 租赁的详细信息,请参阅准备 office 365 租户For more information on setting up an Office 365 tenancy for Teams, see, Prepare your Office 365 tenant.
✔确保团队成员在 Azure Active Directory (AAD) 中。✔ Make sure that team members are in Azure Active Directory (AAD). 有关详细信息, 请参阅向 Azure Active Directory 添加新用户For more information see Add a new user to Azure Active Directory.

第一步:创建团队Step One: Create a team

由于现有数据正在迁移,因此在迁移过程中维护原始邮件的时间戳并防止邮件活动是重新创建用户的现有邮件流的关键。Since existing data is being migrated, maintaining the original message timestamps and preventing messaging activity during the migration process are key to recreating the user's existing message flow in Teams. 这是通过以下方式实现的:This is achieved as follows:

  1. 使用 "团队" 资源属性创建具有 "后向时间戳" 的新团队 createdDateTimeCreate a new team with a back-in-time timestamp using the team resource createdDateTime property.

  2. 将新团队放在中 migration mode ,这是一种特殊状态,可从团队中的大多数活动中对用户进行横栏,直到迁移过程完成。Place the new team in migration mode, a special state that bars users from most activities within the team until the migration process is complete. teamCreationMode 实例属性包含 migration 在 POST 请求中的值,以显式标识新团队为迁移而创建。Include the teamCreationMode instance attribute with the migration value in the POST request to explicitly identify the new team as being created for migration.

权限Permissions

ScopeNameScopeName DisplayNameDisplayName 说明Description 类型Type 管理员同意?Admin Consent? 涵盖的实体/ApiEntities/APIs covered
Teamwork.Migrate.All 管理到 Microsoft 团队的迁移Manage migration to Microsoft Teams 创建、管理用于迁移到 Microsoft 团队的资源Creating, managing resources for migration to Microsoft Teams 仅限应用程序Application-only Yes POST /teams

请求 (在迁移状态中创建团队) Request (create a team in migration state)

POST https://graph.microsoft.com/beta/teams

Content-Type: application/json
{
  "@microsoft.graph.teamCreationMode": "migration",
  "template@odata.bind": "https://graph.microsoft.com/beta/teamsTemplates('standard')",
  "displayName": "My Sample Team",
  "description": "My Sample Team’s Description",
  "createdDateTime": "2020-03-14T11:22:17.067Z"
}

响应Response

HTTP/1.1 202 Accepted
Location: /teams/{teamId}/operations/{operationId}
Content-Location: /teams/{teamId}

错误消息Error messages

400 Bad Request
  • createdDateTime 设置为 "将来"。createdDateTime set for future.
  • createdDateTime 正确指定,但 teamCreationMode 缺少实例属性或将实例属性设置为无效值。createdDateTime correctly specified, but teamCreationMode instance attribute is missing or set to invalid value.

步骤2:创建通道Step Two: Create a channel

为导入的邮件创建通道与创建团队方案类似:Creating a channel for the imported messages is similar to the create team scenario:

  1. 使用 "信道" 资源属性创建具有 "后向时间戳" 的新通道 createdDateTimeCreate a new channel with a back-in-time timestamp using the channel resource createdDateTime property.

  2. 将新频道放置在中 migration mode ,这是一种特殊状态,可用于在迁移过程完成前,从频道内的大多数聊天活动中对用户进行横栏。Place the new channel in migration mode, a special state that bars users from most chat activities within the channel until the migration process is complete. channelCreationMode 实例属性包含 migration 在 POST 请求中的值,以显式标识新团队为迁移而创建。Include the channelCreationMode instance attribute with the migration value in the POST request to explicitly identify the new team as being created for migration.

权限Permissions

ScopeNameScopeName DisplayNameDisplayName 说明Description 类型Type 管理员同意?Admin Consent? 涵盖的实体/ApiEntities/APIs covered
Teamwork.Migrate.All 管理到 Microsoft 团队的迁移Manage migration to Microsoft Teams 创建、管理用于迁移到 Microsoft 团队的资源Creating, managing resources for migration to Microsoft Teams 仅限应用程序Application-only Yes POST /teams

请求 (在迁移状态中创建频道) Request (create a channel in migration state)

POST https://graph.microsoft.com/beta/teams/{id}/channels

Content-Type: application/json
{
  "@microsoft.graph.channelCreationMode": "migration",
  "displayName": "Architecture Discussion",
  "description": "This channel is where we debate all future architecture plans",
  "membershipType": "standard",
  "createdDateTime": "2020-03-14T11:22:17.067Z"
}

响应Response

HTTP/1.1 202 Accepted
Location: /teams/{teamId}/channels/{channelId}/operations/{operationId}
Content-Location: /teams/{teamId}/channels/{channelId}

错误消息Error message

400 Bad Request
  • createdDateTime 设置为 "将来"。createdDateTime set for future.
  • createdDateTime 正确指定 channelCreationMode ,但缺少实例属性或将实例属性设置为无效值。createdDateTime correctly specified but channelCreationMode instance attribute is missing or set to invalid value.

第三步:导入邮件Step Three: Import messages

在创建团队和频道之后,您可以开始使用 createdDateTime 请求正文中的和键发送回送邮件 fromAfter the team and channel have been created, you can begin sending back-in-time messages using the createdDateTime and from keys in the request body.

请求 (张贴为纯文本的邮件) Request (POST message that is text-only)

POST https://graph.microsoft.com/beta/teams/teamId/channels/channelId/messages

{
    "replyToId": null,
    "messageType": "message",
    "createdDateTime": "2019-02-04T19:58:15.511Z",
    "lastModifiedDateTime": null,
    "deleted": false,
    "subject": null,
    "summary": null,
    "importance": "normal",
    "locale": "en-us",
    "policyViolation": null,
    "from": {
        "application": null,
        "device": null,
        "conversation": null,
        "user": {
            "id": "id-value",
            "displayName": "Joh Doe",
            "userIdentityType": "aadUser"
        }
    },
    "body": {
        "contentType": "html",
        "content": "Hello World"
    },
    "attachments": [],
    "mentions": [],
    "reactions": []
}

响应Response

HTTP/1.1 200 OK

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#teams('teamId')/channels('channelId')/messages/$entity",
    "id": "id-value",
    "replyToId": null,
    "etag": "id-value",
    "messageType": "message",
    "createdDateTime": "2019-02-04T19:58:15.511Z",
    "lastModifiedDateTime": null,
    "deleted": false,
    "subject": null,
    "summary": null,
    "importance": "normal",
    "locale": "en-us",
    "policyViolation": null,
    "from": {
        "application": null,
        "device": null,
        "conversation": null,
        "user": {
            "id": "id-value",
            "displayName": "Joh Doe",
            "userIdentityType": "aadUser"
        }
    },
    "body": {
        "contentType": "html",
        "content": "Hello World"
    },
    "attachments": [],
    "mentions": [],
    "reactions": []
}

请求 (发布包含内联 "图像) 的邮件Request (POST a message with inline `image)

注意:此方案中没有特殊的权限范围,因为该请求是了 chatmessage 的一部分;了 chatmessage 的作用域也适用于此处。Note: There are no special permission scopes in this scenario since the request is part of chatMessage; scopes for chatMessage apply here as well.

POST https://graph.microsoft.com/beta/teams/teamId/channels/channelId/messages

{
  "body": {
        "contentType": "html",
        "content": "<div><div>\n<div><span><img height=\"250\" src=\"../hostedContents/1/$value\" width=\"176.2295081967213\" style=\"vertical-align:bottom; width:176px; height:250px\"></span>\n\n</div>\n\n\n</div>\n</div>"
    },
    "hostedContents":[
        {
            "@microsoft.graph.temporaryId": "1",
            "contentBytes": "iVBORw0KGgoAAAANSUhEUgAAANcAAAExCAYAAADvFzeeAAAXjklEQVR4Ae2d/XNU1RnH+9e0FFrA0RCIyaS8hRA0HV5KbS1gHRgVpjMClY4GHJ3yYm1HCmXaWttaaZUZtIIFKYi8lFAkvOQ9u5vN225IARVBbX9/Os9NbrLZbMjmhCfJPX5+2Lmb3T25y3O+n/M599x7w9f+++UXwoMakIF7n4GvUdR7X1RqSk01A8CFuZm5GGUAuIwKi72wF3ABF+YyygBwGRUWc2Eu4AIuzGWUAeAyKizmwlzABVyYyygDwGVUWMyFuYALuDCXUQaAy6iwmAtzARdwfWXMdeuzT+TGxz3Sfb1LunrapL07IW3pePDQ5/qavqef0c+OdYAELuAac4jGGkLL9rdvfyo9N9ODQAqBGmmrwGlb/R0u3xG4gMspOC5hG882CoRaaCSA8n1ff9doIQMu4PIOrus3u+8ZVNnw6e/Od5AALuDKOyz5hmqiPnfnzi1J9bSbgRWCpvvQfY307wQu4BoxJCOFaDK8rwsQmQsUIQhWW93XSIsewAVckYdLQ24F0Ui/926AARdwRRounZ6Np7GyYdN9DzdFBC7gijRc43GMlQ1U9s/6HXJNjYELuHI<<-----Removed----->>>>",
            "contentType": "image/png"
        }
    ]
}

响应Response

HTTP/1.1 200 OK

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#teams('teamId')/channels('channelId')/messages/$entity",
    "id": "id-value",
    "replyToId": null,
    "etag": "id-value",
    "messageType": "message",
    "createdDateTime": "2019-02-04T19:58:15.511Z",
    "lastModifiedDateTime": null,
    "deleted": false,
    "subject": null,
    "summary": null,
    "importance": "normal",
    "locale": "en-us",
    "policyViolation": null,
    "from": {
        "application": null,
        "device": null,
        "conversation": null,
        "user": {
            "id": "id-value",
            "displayName": "Joh Doe",
            "userIdentityType": "aadUser"
        }
    },
    {
      "body": {
        "contentType": "html",
        "content": "<div><div>\n<div><span><img height=\"250\" src=\"https://graph.microsoft.com/teams/teamId/channels/channelId/messages/id-value/hostedContents/hostedContentId/$value\" width=\"176.2295081967213\" style=\"vertical-align:bottom; width:176px; height:250px\"></span>\n\n</div>\n\n\n</div>\n</div>"
    },
    "attachments": [],
    "mentions": [],
    "reactions": []
}

步骤4:完成迁移模式Step Four: Complete migration mode

邮件迁移过程完成后,团队和通道将使用方法从迁移模式中去掉 completeMigrationOnce the message migration process has completed, both the team and channel are taken out of migration mode using the completeMigration method. 此步骤将打开团队和渠道资源,以供工作组成员进行常规使用。This step opens the team and channel resources for general use by team members. 操作将绑定到 team 实例。The action is bound to the team instance.

请求 (结束团队迁移模式) Request (end team migration mode)

POST https://graph.microsoft.com/beta/teams/teamId/completeMigration

响应Response

HTTP/1.1 204 NoContent

请求 (结束通道迁移模式) Request (end channel migration mode)

POST https://graph.microsoft.com/beta/teams/teamId/channels/channelId/completeMigration

响应Response

HTTP/1.1 204 NoContent

错误响应Error response

400 Bad Request
  • 在或上调用的操作 team channel 不在中 migrationModeAction called on a team or channel that is not in migrationMode.

第5步:添加团队成员Step Five: Add team members

您可以 使用 "团队 UI" 或 Microsoft Graph 添加成员 API 将成员添加到团队中:You can add a member to a team using the Teams UI or Microsoft Graph Add member API:

请求 (添加成员) Request (add member)

POST https://graph.microsoft.com/beta/groups/{id}/members/$ref
Content-type: application/json
Content-length: 30

{
  "@odata.id": "https://graph.microsoft.com/beta/directoryObjects/{id}"
}

响应Response

HTTP/1.1 204 No Content

提示和其他信息Tips and additional information

  • 您可以导入不在工作组中的用户的邮件。You can import messages from users who are not in Teams.

  • completeMigration发出请求后,将无法再向团队中导入邮件。Once the completeMigration request is made, you cannot import further messages into the team.

  • 只有在请求返回成功的响应后,才能将团队成员添加到新团队 completeMigrationTeam members can only be added to the new team after the completeMigration request has returned a successful response.

  • 限制:邮件将导入每通道5个 RPS。Throttling: Messages import at 5 RPS per channel.

  • 如果需要对迁移结果进行更正,则需要删除团队并重复步骤以创建团队和频道并重新迁移邮件。If you need to make a correction to the migration results, you need to delete the team and repeat the steps to create the team and channel and re-migrate the messages.

备注

目前,嵌入式图像是导入邮件 API 架构支持的唯一媒体类型。Currently, Inline images is the only type of media supported by the import message API schema.

导入内容范围Import content scope
范围内In-scope 当前超出范围Currently out-of-scope
团队和频道消息Team and channel messages 1:1 和分组聊天消息1:1 and group chat messages
原始邮件的创建时间Created time of the original message 专用频道Private channels
作为邮件的一部分的嵌入式图像Inline images as part of the message 提到At mentions
指向 SPO/OneDrive 中的现有文件的链接Links to existing files in SPO/OneDrive 作出Reactions
带格式文本的邮件Messages with rich text 视频Videos
邮件答复链Message reply chain 公告Announcements
高吞吐量处理High throughput processing 代码段Code snippets
自适应卡片Adaptive cards
不干胶Stickers
表情符号Emojis
股票Quotes
通道之间的跨文章Cross posts between channels