0
0

Gmail api (gpc) OAuth認証でメールの送信

Last updated at Posted at 2024-06-21

追記情報

  1. googleが信頼性の低いアプリの使用を禁止したため、2段階認証によるメールの送信ができなくなった。
  2. yahoo.co.jp のアカウントをつかってのメール送信もかなり制限されている。
  3. OAuth認証をつかったmail apiは Azure, Microsoft,Yahoo.com などの大手もある。
  4. 正直 SendGrid のほうが使いやすい。
    SendGrid は個人利用ができなくなった。
    審査も厳しくなり、途中でバンされたという報告が多数ある。
  5. 独自ドメインの利用は Google Workspace(月額 680 円/ユーザー)で可能。
  6. oauth認証のメールで送信し、差出人メールを同じメールアカウントで送ることで送信ドメイン認証もオールPASSになる。
    image.png

参考サイト

ほぼ下の手順通り 2024/6/19 少し変更がある。
大きな変更はテストユーザーでは不可になったのでユーザーにアカウント追加する必要がある。

必要なもの

  1. GCPのプロジェクトを作成して、gmail apiを有効にする
  2. refresh token

refresh tokenの取得

  1. ドキュメントで公開されている quickstart.phpで取得 する方法
  2. PHPMailerに付属している get_auth_token.phpを使って取得する方法
    🙅 get_oauth_token.php にURLからアクセスするため 簡易サーバーの起動 は駄目
    なので、Xampplamp などの開発環境が必要
$ 簡易サーバーの起動
🙅 // php -S 127.0.0.1:80 簡易サーバーではリレフレシュトークンが取得できない。

クライアントIDとクライアントシークレットの取得のための手続き

gmail_apiはアプリ名

$ gmail_apiという作業ディレクトリを作成した
cd gmail_api

googleのリダイレクトURLの登録にPHPMailerのget_auth_token.phpを使用するため

$
composer require phpmailer/phpmailer

get_oauth_token.php にアクセス
http://localhost/gmail_api/vendor/phpmailer/phpmailer/get_oauth_token.php
このURLがリダイレクトURLになる。

image.png

GCPでプロジェクトを作成する

image.png
gmail api で検索をかけて 選択

image.png
gmail api を有効にする

image.png
認証情報を作成

image.png
まずは OAuth同意画面 を作成する

image.png
add Userでuser名は アカウントのgmailアドレス

image.png
Oauhtクライアントを選択

image.png
http://localhost/vendor/phpmailer/phpmailer/get_oauth_token.phpを登録

image.png
クライアントIDクライアントシークレットが取得できる

image.png

PHPMailerでのリフレッシュトークンの取得

get_oauth_token.php にアクセス
http://localhost/gmail_api/vendor/phpmailer/phpmailer/get_oauth_token.php
入力してcontinue
image.png
2つくらいcontinueをおしてたら下記のサイトがでてくるのでチェックをいれてcontinue

image.png

refresh token: ここがリフレッシュトークン
1度しか発行されないので注意
image.png

メールの送信

リフレッシュトークンを gmail apiになげてアクセストークンを取得することでメールが送れる。
アクセストークンの有効期限は1時間くらい。

refresh tokenの期限切れ

Gmail APIのリフレッシュトークンは通常、期限切れにならない。
一度発行されたら期限が切れるまで再発行(再取得)されない。
以下のいくつかの特別な状況で期限切れになる可能性がある。

  1. Gmail アカウントの所有者がアプリのアクセスを取り消した場合
  2. リフレッシュトークンが6ヶ月間使用されていない場合

XOAUTH2 用のパッケージ(league/oauth2-google)をインストール

$
composer require league/oauth2-google

テストコード 

webdesignleavesから丸パクリ 注意事項も 必読
$google_email,$clientId,$clientSecret,$refreshToken は変更

index.php
<?php
// https://www.webdesignleaves.com/pr/php/php_phpmailer.php から丸パクリ

// HPMailer のクラスをグローバル名前空間(global namespace)にインポート
// スクリプトの先頭で宣言する必要があります
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\OAuth; //  ### 追加 ### 
 
// Alias the League Google OAuth2 provider class
use League\OAuth2\Client\Provider\Google;//  ### 追加 ### 
 
// Composer のオートローダーの読み込み(ファイルの位置によりパスを適宜変更)
require 'vendor/autoload.php';
 
//mbstring の日本語設定
mb_language("japanese");
mb_internal_encoding("UTF-8");
 
// インスタンスを生成(引数に true を指定して例外 Exception を有効に)
$mail = new PHPMailer(true);
 
//日本語用設定
$mail->CharSet = "iso-2022-jp";
$mail->Encoding = "7bit";
 
try {
  //サーバの設定
  $mail->SMTPDebug = SMTP::DEBUG_SERVER;  // デバグの出力を有効に(テスト環境での検証用)
  $mail->isSMTP();   // SMTP を使用
  $mail->Host       = 'smtp.gmail.com';  // ★★★ Gmail SMTP サーバーを指定
  $mail->SMTPAuth   = true;   // SMTP authentication を有効に
  $mail->AuthType = 'XOAUTH2';//  ### 追加 ###   AuthType を XOAUTH2 に指定
  //$mail->Username   = 'xxxxxx@gmail.com';  //  ### 不要 ### 
  //$mail->Password   = 'xxxxxx';  //  ### 不要 ###  
  // ★★★ 暗号化を有効に PHPMailer::ENCRYPTION_STARTTLS を使う場合はポートを 587 に
  $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; 
  $mail->Port = 465;  //ポートの指定
  
  // ###  OAUTH2 の設定  ### 
  //Gmail メールアドレス
  $google_email = 'ここ変更@gmail.com';
  //クライアント ID
  $clientId = 'ここ変更';
  //クライアントシークレット
  $clientSecret = 'ここ変更';
  //トークン(Refresh Token)
  $refreshToken = 'ここ変更';
 
  //OAuth2 プロバイダのインスタンスの生成 
  $provider = new Google(
    [
      'clientId' => $clientId,
      'clientSecret' => $clientSecret,
    ]
  );
 
  //OAuth プロバイダのインスタンスを PHPMailer へ渡す
  $mail->setOAuth(
    new OAuth(
      [
        'provider' => $provider,
        'clientId' => $clientId,
        'clientSecret' => $clientSecret,
        'refreshToken' => $refreshToken,
        'userName' => $google_email,
      ]
    )
  );
  // ###  OAUTH2 の設定 ここまで  ### 
 
  //受信者設定
  //差出人アドレス(Gmail のアドレス), 差出人名 
  $mail->setFrom($google_email, mb_encode_mimeheader('差出人名'));  //  ### 変更 ### 
  // 送信先アドレス, 受信者名(受信者名はオプション)
  $mail->addAddress('ここ変更', mb_encode_mimeheader("受信者名")); 
  // 追加の受信者(受信者名は省略可能)
//   $mail->addAddress('xxxxxx@xxxxxx.com'); 
  //返信用アドレス(差出人以外に必要であれば)
  $mail->addReplyTo('info@example.com', mb_encode_mimeheader("お問い合わせ"));  
  //Cc 受信者の指定
//   $mail->addCC('xxxxxx@xxxxxx.com'); 
 
  //コンテンツ設定
  $mail->isHTML(true);   // HTML形式を指定
  //メール表題(タイトル)
  $mail->Subject = mb_encode_mimeheader('日本語メールタイトル');  
  //本文(HTML用)
  $mail->Body  = mb_convert_encoding('HTML メッセージ <b>BOLD</b>',"JIS","UTF-8"); 
  //テキスト表示の本文
  $mail->AltBody = mb_convert_encoding('テキストメッセージ',"JIS","UTF-8"); 
 
  $mail->send();  //送信
  echo 'Message has been sent';
} catch (Exception $e) {
  echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}

gmail apiでメールを取得

$
composer require google/apiclient:^2.0
$ .envファイルで読み込むため
composer require vlucas/phpdotenv
<?php
require_once __DIR__ . '/vendor/autoload.php';

use Google\Client;
use Google\Service\Gmail;

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$clientId = $_ENV['CLIENT_ID'];
$clientSecret =  $_ENV['CLIENT_SECRET'];

$filePath = __DIR__ . '/gmail_refresh_token.txt';

if (is_readable($filePath)) {
    $refreshToken = file_get_contents($filePath);
} else {
    echo "ファイルが見つからないか、読み取りできません。";
}


$client = new Client();
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);
$client->refreshToken($refreshToken);
$client->setScopes(['https://mail.google.com/']);

// Gmail サービスを作成
$service = new Gmail($client);

// 受信箱メッセージを取得
$optParams = [];
$optParams['maxResults'] = 5; // 例えば、最初の5件のメッセージだけを取得
$optParams['labelIds'] = 'INBOX'; // 受信箱のメッセージのみ


$messagesResponse = $service->users_messages->listUsersMessages('me', $optParams);

foreach ($messagesResponse->getMessages() as $message) {
    $messageId = $message->getId();
    $message_contents = $service->users_messages->get('me', $messageId, ['format' => 'full']);
    $body_parts = $message_contents->getPayload()->getParts();

    echo get_body($body_parts);
}

function get_body($parts) {
    $body = '';
    foreach ($parts as $part) {
    //$part['mimeType'] === 'text/plain'とかある
      if ($part['mimeType'] === 'text/html' && $part['body'] && $part['body']['data']) {
            $rawData = $part['body']['data'];
            $sanitizedData = strtr($rawData, '-_', '+/');
            $decodedMessage = base64_decode($sanitizedData);
            $body .= $decodedMessage;
        } elseif (!empty($part['parts'])) {
            $body .= get_body($part['parts']);
        }
    }
    return $body;
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0