自分用のWebアプリケーションから、長らくPHPMailer
を使用して特定のアカウントからGmailメールを送信していました。セキュリティが厳しくなり、以下のような対応をしていました。
Googleアカウントで安全性の低いアプリのアクセスを許可- アプリパスワードを作成してSMTPパスワードの替わりに使用 こちらを参考
このたび、SMTPでなくOAuth認証にし、Gmail APIを使って送信してみることにしました。
全体の流れ
- Google Cloudの設定
- クライアントライブラリのインストール
- PHPコード作成
Google Cloud設定
Google Cloud Consoleにログインして以下を設定する。
アプリ情報の設定
-
APIとサービス > OAuth同意画面 > ブランディングを選択
項目 設定値 アプリ名 メールを送信するアプリケーションの名前 ユーザーサポートメール このアプリについての問い合わせメールアドレス 承認済みドメイン メール送信アプリを置くサーバーのドメイン
後述する認証情報の承認済みのリダイレクト URIは、承認済みドメインを含まなければならない。
Gmail APIを有効化
- APIとサービス > 有効なAPIとサービスを選択
-
+APIとサービスを有効にするをクリック
Gmail APIを選択し、有効にするクリック
認証情報を作成
- APIとサービス > 認証情報を選択
-
+認証情報を作成をクリック、OAuth クライアント IDを選択
項目 設定値 アプリケーションの種類 "ウェブアプリケーション" 名前 任意。管理上識別できれば良い。 承認済みの JavaScript 生成元 <今回は不要> 承認済みのリダイレクト URI 認証後にGoogleから呼ばれるURLを追加。プロトコルから正確に記述する。 -
作成クリックでクライアントが作成されたら、設定情報をダウンロードする。
一覧の右側のダウンロードアイコンをクリック。 ここではclient_secret.jsonとする。
スコープの設定
- APIとサービス > OAuth同意画面 > データアクセスを選択
- スコープを追加または削除をクリック。
- ../auth/gmail.sendを選択し、更新ボタンクリック
- 保存クリック
スコープは必要最小限を選ぶ
対象(オーディエンス)の設定
-
APIとサービス > OAuth同意画面 > 対象を選択
ユーザーの種類 説明 内部 組織内のユーザーのみ許可(Google Workspaceユーザーでないと選択できない) 外部 Googleアカウントを持つユーザーは誰でも使用できる
外部の場合は色々設定しないとならなので、とりあえずテスト状態にしてユーザーを制限する
クライアントライブラリの導入
- APIとサービス > ライブラリを選択
- Google WorkspaceグループのGmail APIを選択
-
このAPIを試すを選択
Gmail APIリファレンスにリダイレクトされる - Gmail APIリファレンス画面左のフレームから、クライアントライブラリ > 概要
https://developers.google.com/gmail/api/downloads?hl=ja - PHPタブからPHP 用 Gmail API クライアント ライブラリ(ベータ版)
Githubリポジトリ(googleapis/google-api-php-client)が開く。 - READMEの通り、PHPライブラリをサーバーにインストール
composer require google/apiclient
リポジトリの/doc/oauth-web.mdがコーディングの参考になります。
PHPコード作成
client_secret.jsonの配置
認証情報作成でダウンロードしたclient_secret.jsonをサーバーの直接アクセスできない場所に配置する。
認証を必要とするアクションで、Google認証画面にリダイレクトするようにする。
$client->setRedirectUri()
で指定するURLは、Cloud Consoleでクライアントに設定した「承認済みのリダイレクトURI」の1つと一致していなければならない。
$client = new Google\Client();
$client->setAuthConfig('path to client_secret.json');
$client->addScope(Google\Service\Gmail::GMAIL_SEND);
// 認証後にgoogleから呼ばれるURIをセット。
$client->setRedirectUri("https://" . $_SERVER['HTTP_HOST'] . '/callback/gmail.php');
$client->setAccessType('online');
$client->setIncludeGrantedScopes(true);
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
認証後にGoogleから呼ばれるコールバックを作成
同意(認証)キャンセルの場合でも呼ばれる。$_GET['error']がセットされる。
if(isset($_GET['error'])){
echo("認証されませんでした。".$_GET['error']);
return;
}
同意があったときは$_GET['code']に認証コードがセットされる。APIに必要なのはアクセストークンである。アクセストークンに変換する。
$accessToken = $client->fetchAccessTokenWithAuthCode($code);
このままメール送信できるのだが、このままだとURLに承認コードが表示されたままになってしまう。そこでアクセストークンをセッションに格納し、メール送信を実行するスクリプトにリダイレクトすることが推奨される。
session_start();
$_SESSION['access_token'] = $accessToken;
header('Location: ' . filter_var("/gmail/send_exec.php", FILTER_SANITIZE_URL));
メール送信実行
$access_token = $_SESSION['access_token'];
$client->setAccessToken($access_token);
:メール作成
$message = new Google\Service\Gmail\Message();
$message->setRaw($rawMessage);
$gmail = new Google\Service\Gmail($client);
$gmail->users_messages->send("me", $message);
感想
Google Client APIはサイズが大きいし、コールバック等コードも複雑になるので、特定のアカウントからメールを送信するだけなら、アプリパスワードを使用する方が簡単。
今後DriveなどほかのAPIも使ってみたい。
リンク
Google API PHP client Github
Gmail API RESTリファレンス
Gamil API PHP doc