使用 Microsoft Graph 向 PHP 应用添加电子邮件功能

在本文中,将扩展在 使用 Microsoft Graph 邮件 API 生成 PHP 应用中 创建 Microsoft的应用程序。 使用 Microsoft Graph 列出用户的收件箱并发送电子邮件。

列出用户的收件箱

首先,在用户的电子邮件收件箱中列出邮件。

  1. 将以下代码添加到 GraphHelper 类。

    public static function getInbox(): Models\MessageCollectionResponse {
        $configuration = new MessagesRequestBuilderGetRequestConfiguration();
        $configuration->queryParameters = new MessagesRequestBuilderGetQueryParameters();
        // Only request specific properties
        $configuration->queryParameters->select = ['from','isRead','receivedDateTime','subject'];
        // Sort by received time, newest first
        $configuration->queryParameters->orderby = ['receivedDateTime DESC'];
        // Get at most 25 results
        $configuration->queryParameters->top = 25;
        return GraphHelper::$userClient->me()
            ->mailFolders()
            ->byMailFolderId('inbox')
            ->messages()
            ->get($configuration)->wait();
    }
    
  2. main.php 中的空listInbox函数替换为以下内容。

    function listInbox(): void {
        try {
            $messages = GraphHelper::getInbox();
    
            // Output each message's details
            foreach ($messages->getValue() as $message) {
                print('Message: '.$message->getSubject().PHP_EOL);
                print('  From: '.$message->getFrom()->getEmailAddress()->getName().PHP_EOL);
                $status = $message->getIsRead() ? "Read" : "Unread";
                print('  Status: '.$status.PHP_EOL);
                print('  Received: '.$message->getReceivedDateTime()->format(\DateTimeInterface::RFC2822).PHP_EOL);
            }
    
            $nextLink = $messages->getOdataNextLink();
            $moreAvailable = isset($nextLink) && $nextLink != '' ? 'True' : 'False';
            print(PHP_EOL.'More messages available? '.$moreAvailable.PHP_EOL.PHP_EOL);
        } catch (Exception $e) {
            print('Error getting user\'s inbox: '.$e->getMessage().PHP_EOL.PHP_EOL);
        }
    }
    
  3. 运行应用,登录,然后选择选项 2 列出收件箱。

    Please choose one of the following options:
    0. Exit
    1. Display access token
    2. List my inbox
    3. Send mail
    4. Make a Graph call
    2
    Message: Updates from Ask HR and other communities
      From: Contoso Demo on Yammer
      Status: Read
      Received: Mon, 18 Apr 2022 14:24:16 +0000
    Message: Employee Initiative Thoughts
      From: Patti Fernandez
      Status: Read
      Received: Mon, 18 Apr 2022 13:52:03 +0000
    Message: Voice Mail (11 seconds)
      From: Alex Wilber
      Status: Unread
      Received: Wed, 13 Apr 2022 02:30:27 +0000
    Message: Our Spring Blog Update
      From: Alex Wilber
      Status: Unread
      Received: Tue, 12 Apr 2022 16:46:01 +0000
    Message: Atlanta Flight Reservation
      From: Alex Wilber
      Status: Unread
      Received: Mon, 11 Apr 2022 13:39:10 +0000
    Message: Atlanta Trip Itinerary - down time
      From: Alex Wilber
      Status: Unread
      Received: Fri, 08 Apr 2022 18:36:01 +0000
    
    ...
    
    More messages available? True
    

getInbox 说明

请考虑 函数中的 getInbox 代码。

访问已知邮件文件夹

函数传递给 /me/mailFolders/inbox/messages 请求生成器,该生成器生成对 列表消息 API 的请求。 由于它包含 /mailFolders/inbox 段,API 仅返回请求的邮件文件夹中的邮件。 在这种情况下,由于收件箱是用户邮箱中默认的已知文件夹,因此可通过其已知名称访问该文件夹。 非默认文件夹的访问方式相同,方法是将已知名称替换为邮件文件夹的 ID 属性。 有关可用已知文件夹名称的详细信息,请参阅 mailFolder 资源类型

访问集合

与上一 getUser 部分中返回单个 对象的函数不同,此方法返回消息集合。 Microsoft Graph 中返回集合的大多数 API 不会在单个响应中返回所有可用结果。 相反,它们使用 分页 返回部分结果,同时为客户端提供请求下一页的方法。

默认页面大小

使用分页的 API 实现默认页面大小。 对于消息,默认值为 10。 客户端可以使用 $top 查询参数请求更多 (或更少的 ) 。 在 中getInbox,使用查询参数中的 属性完成queryParameters->top添加$top

注意

传入的值 queryParameters->top 是上限,而不是显式数字。 API 返回一些 消息,最多返回 指定值。

获取后续页面

如果服务器上有更多可用的结果,则集合响应将包含一个 @odata.nextLink 具有 API URL 的属性,用于访问下一页。 PHP SDK 针对集合请求对象提供 getOdataNextLink 方法。 如果此方法返回非空字符串,则有更多可用的结果。 有关详细信息,请参阅 使用 Microsoft Graph SDK 对集合进行分页

集合排序

函数使用 $orderby 查询参数 请求按消息接收时间排序的结果, receivedDateTime (属性) 。 它包含DESC关键字 (keyword) 以便先列出最近收到的消息。

发送邮件

现在,添加以经过身份验证的用户身份发送电子邮件的功能。

  1. 将以下代码添加到 GraphHelper 类。

    public static function sendMail(string $subject, string $body, string $recipient): void {
        $message = new Models\Message();
        $message->setSubject($subject);
    
        $itemBody = new Models\ItemBody();
        $itemBody->setContent($body);
        $itemBody->setContentType(new Models\BodyType(Models\BodyType::TEXT));
        $message->setBody($itemBody);
    
        $email = new Models\EmailAddress();
        $email->setAddress($recipient);
        $to = new Models\Recipient();
        $to->setEmailAddress($email);
        $message->setToRecipients([$to]);
    
        $sendMailBody = new SendMailPostRequestBody();
        $sendMailBody->setMessage($message);
    
        GraphHelper::$userClient->me()->sendMail()->post($sendMailBody)->wait();
    }
    
  2. main.php 中的空sendMail函数替换为以下内容。

    function sendMail(): void {
        try {
            // Send mail to the signed-in user
            // Get the user for their email address
            $user = GraphHelper::getUser();
    
            // For Work/school accounts, email is in Mail property
            // Personal accounts, email is in UserPrincipalName
            $email = $user->getMail();
            if (empty($email)) {
                $email = $user->getUserPrincipalName();
            }
    
            GraphHelper::sendMail('Testing Microsoft Graph', 'Hello world!', $email);
    
            print(PHP_EOL.'Mail sent.'.PHP_EOL.PHP_EOL);
        } catch (Exception $e) {
            print('Error sending mail: '.$e->getMessage().PHP_EOL.PHP_EOL);
        }
    }
    
  3. 运行应用,登录并选择选项 3 以向自己发送电子邮件。

    Please choose one of the following options:
    0. Exit
    1. Display access token
    2. List my inbox
    3. Send mail
    4. Make a Graph call
    3
    
    Mail sent.
    

    注意

    如果使用 Microsoft 365 开发人员计划中的开发人员租户进行测试,则发送的电子邮件可能未送达,并且可能会收到无法交付的报告。 如果要取消阻止从租户发送邮件,请通过Microsoft 365 管理中心联系支持人员。

  4. 若要验证是否已收到邮件,请选择选项 2 列出收件箱。

sendMail 说明

请考虑 函数中的 sendMail 代码。

发送邮件

函数使用 $userClient->me()->sendMail() 请求生成器,该生成器生成对 发送邮件 API 的请求。 请求生成器采用包含要发送的消息的请求正文。

创建对象

与以前调用 Microsoft Graph(仅读取数据)不同,此调用会创建数据。 若要使用客户端库创建项,请创建一个表示数据的关联数组,设置所需的属性,然后在 API 调用中发送它。 由于调用正在发送数据,因此使用 POST 方法而不是 GET

后续步骤