🌟

phpでmicrosoft365のメールアカウントからメール送信

2024/12/07に公開

初めに

コーポレート系お問合せフォームからのメール送信でSendmailなんて使えないので、
SMTPを利用するんだけど、
Microsoft365とかgogleWorkspaceとかを利用してると、SMTPすら使えなくて、
APIを利用する事になる。

そして、Microsoft365で利用してるメールアドレスからphpを利用して送信する方法を
調べても本当に情報が無くて苦労したので、まとめておく。

phpからMicrosoft365のAPIを利用するには、SDKを利用する
https://github.com/microsoftgraph/msgraph-sdk-php/tree/main

仕組み

microsoft365のメール送信をphpやその他のプログラム言語で行う為には
Graph Apiを利用する必要が有る。

また、
Graph Apiの認証方法でアプリ専用認証を利用する事で、
アカウントにログインせずに、メール送信が利用できる。

ただし、
送信元ユーザー(アドレス)は明示的に指定する必要が有る。
送信元ユーザーUserIdの取得方法も合わせて書いておく

全体の流れ

バクっと全体の流れをまとめておく

  1. Microsoft365のEntra管理センターでアプリを作成して【クライアントID】と【テナントID】を取得
  2. アプリにAPIのMail.send権限を付与
  3. 【クライアントシークレット】を作成する
  4. 送信元ユーザーの【UserId】を取得
  5. phpで処理を書く

Microsoft365のEntra管理センターでアプリを作成

ポータルでアプリを登録する

Microsoft Entra 管理センターに移動して、
 [ID] を展開し、[ アプリケーション] を展開して、[ アプリの登録] を選択

アプリの登録画面でアプリを作成する

登録する内容はこんな感じ
① : アプリ名を入力する。日本語でOKだし、自分に解ればOK
  とりあえず「サイトメール送信アプリ1」にした
② :この組織ディレクトリに含まれるアカウントにチェック。
③ : リダイレクトURLは空白でOK
④ : 登録をクリック

登録したアプリの画面が表示される。

2つの文字列をメモしておく

  1. アプリケーション (クライアント) ID
  2. ディレクトリ (テナント) ID

アプリにAPIのMail.send権限を付与

既存の「User.Read」権限は削除する

「Mail.Send」権限を付与する

これで、
一覧に「Mail.send」が入るが、
状態の列で「〇〇〇に付与されていません」という表示が出る

〇〇〇に管理者の同意を与えます」をクリックし
出てきたフロートウィンドの中の「はい」をクリックする

クライアントシークレットを作成する

下の画像の感じでシークレットを作成する

説明は自分が解る名前にしとけばいい。
有効期限カスタムにすると、起動終了を入力できるようになり、
起動は今日の日付
終了はエラー文に2年後の日付が表示されるのでその日付を指定
画面下の「保存」をクリックする

クライアントシークレットができるのでの方の文字列をメモしておく
これがクライアントシークレットとなるのでメモ
この値は1回しか表示しないので注意

送信者のUserIDを取得

これも管理者のEntraから確認できる

ユーザー全てのユーザー→一覧から該当のユーザー名をクリックして、ユーザーの詳細を開く

オブジェクトID」部分がUserIdになるので、メモっておく

phpで処理を書く

あとは、普通にブラウザから利用する為のphpを作成する。

ComposerでSDKをインストール

composer require microsoft/microsoft-graph

完成後フォルダ構成はこんな感じ

root/
├── GraphMail.php
├── composer.json
├── composer.lock
├── index.php
└── vendor/

メール送信クラスの作成「GraphMail.php」

GraphMail.php
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext;
use Microsoft\Graph\Generated\Users\Item\SendMail\SendMailPostRequestBody;
use Microsoft\Graph\Generated\Models\BodyType;
use Microsoft\Graph\Generated\Models\EmailAddress;
use Microsoft\Graph\Generated\Models\ItemBody;
use Microsoft\Graph\Generated\Models\Message;
use Microsoft\Graph\Generated\Models\Recipient;

class GraphMail
{
	private  $tokenContext;
	private  $appClient;
	private  $userId = '${UserId}';
	private  $fromEmailAddress ='${送信元メールアドレス}'; //送信元アドレス;
	private  $clientId = '${クライアントID}';
	private  $clientSecret = '${クライアントシークレット}';
	private  $tenantId = '${テナントID}';

	public  function initializeGraphForAppOnlyAuth()
	{

		$this->tokenContext = new ClientCredentialContext(
			$this->tenantId,
			$this->clientId,
			$this->clientSecret
		);

		$this->appClient = new GraphServiceClient(
			$this->tokenContext,
			['https://graph.microsoft.com/.default']
		);

	}

	public function sendMail($toEmailAddress, $subject, $body): void
	{
		//送信元
		$sender = new EmailAddress();
		$sender->setAddress($this->fromEmailAddress);
		$fromRecipient = new Recipient();
		$fromRecipient->setEmailAddress($sender);
	
		//送信先
		$recipients = [];	
		$recipientEmail = new EmailAddress();
		$recipientEmail->setAddress($toEmailAddress);
		$toRecipient = new Recipient();
		$toRecipient->setEmailAddress($recipientEmail);
		$recipients[] = $toRecipient;
	
		//メール本文
		$emailBody = new ItemBody();
		$emailBody->setContent($body);
		$emailBody->setContentType(new BodyType(BodyType::TEXT));
	
		//メール作成
		$message = new Message();
		$message->setSubject($subject);
		$message->setFrom($fromRecipient);
		$message->setToRecipients($recipients);
		$message->setBody($emailBody);
	
		//メール送信
		$requestBody = new SendMailPostRequestBody();
		$requestBody->setMessage($message);
		$this->appClient->users()->byUserId($this->userId)->sendMail()->post($requestBody)->wait();
	}
}

メール送信処理の作成「index.php」

index.php
<?php
require 'vendor/autoload.php';
require 'GraphMail.php';
$graphMail = new GraphMail();
//クライアントの作成
$graphMail->initializeGraphForAppOnlyAuth();
try {
	//メール送信
	$graphMail->sendMail('${送信先メールアドレス}', '${件名}', '${本文}');
} catch (Exception $e) {
	print(PHP_EOL . 'Error getting users: ' . $e->getMessage() . PHP_EOL . PHP_EOL);
}

最後に

日本語の情報が無さ過ぎて苦労したので、
誰かの役に立てば嬉しいです。

2024/12/06現在は、これで送信できてる
このへんのAzureとかのAPIは、ガンガン仕様変更されていくので、
半年後ぐらいには約に立たないかもしれないけど
ちょっとは役に立ってくれると嬉しいです。

参考記事

SDKのリポジトリ

https://github.com/microsoftgraph/msgraph-sdk-php/tree/main

SDKの解説ドキュメント

https://github.com/microsoftgraph/msgraph-sdk-php/blob/main/docs/Examples.md
アプリ認証のやり方は「o make requests without a signed-in use」でページ内検索したらある

メール送信

https://github.com/microsoftgraph/msgraph-sdk-php/blob/main/docs/Examples.md#send-an-email

公式のメール送信についてのドキュメント

https://learn.microsoft.com/ja-jp/graph/api/user-sendmail?view=graph-rest-1.0&tabs=php

公式のチュートリアル「Microsoft Graph とアプリ専用認証を使用して PHP アプリを構築する」

https://learn.microsoft.com/ja-jp/graph/tutorials/php-app-only?tabs=aad

GitHubで編集を提案

Discussion