目的
PlaywrightでGoogle Gmail APIを使用してメールを受信すること。
Playwrightでe2eテストコードを実装する中で、メール認証時の認証コードを取得したかったのでAPIでメールを取得したかった。
前提
- Googleアカウントがあること
事前準備
まずはgoogleapisでGmailを取得するために必要な認証情報を取得します。
Google Cloud Consoleでプロジェクトを作成
以下にアクセスしてプロジェクトを作成します。
以下の手順でプロジェクトを作成
- Google Cloud Consoleへアクセス
- プロジェクトを作成ボタンをクリック
- 適当にプロジェクト名を入力
- 作成ボタンをクリック
Gmail APIを有効化
サイドバーを開き「APIとサービス > ライブラリ」をクリックし、APIライブラリからGmail APIを有効化します。
以下の手順でGmail APIを有効化
- APIライブラリへアクセス
- 検索窓に「Gmail」と入力
- 検索結果の「Gmail API」をクリック
- 「有効にする」ボタンをクリック
OAuth 2.0 クライアントIDを作成
「APIとサービス > 認証情報」から認証情報を作成します。
- 「認証情報を作成」ボタンをクリック
- OAuth クライアントIDをクリック
- OAuth同意がまだの場合は設定が必要なので、「OAuth同意画面」へアクセスして設定
- 設定
- アプリケーションの種類:ウェブアプリケーション
- 名前:適当でOK(自分は初期値のままにした)
- 承認済のリダイレクトURI:
http://localhost:3000/oauth2callback
- 後ほどインストールするライブラリでこのように設定するよう記載があります。
認証情報を取得
クライアントIDの作成が完了すると認証情報が作成されます。
後ほど以下の項目を利用します。
- クライアント ID
- クライアントシークレット
googleapisでGmailを取得する
プロジェクトにgoogleapisをインストール
googleapisはGoogleが提供するAPIや開発者向けツールなどを含む、Google Cloud Platform(GCP)の一部です。今回はこちらを利用してGmailをAPIで取得します。
-
pnpm install googleapis
でインストール- 利用しているパッケージマネージャでインストール方法は変更してください
認証URLを生成してcodeを取得
アクセストークンを取得するためにアクセス許可を行います。
先ほど作成した認証情報と、設定したリダイレクトURIを利用します。
const oauth2Client = new google.auth.OAuth2(
'clientID', // クライアントID
'clientsecret', // クライアントシークレット
'http://localhost:3000/oauth2callback', // リダイレクトURI
);
const scopes = ['https://www.googleapis.com/auth/gmail.readonly'];
const url = oauth2Client.generateAuthUrl({
// 'online' (default) or 'offline' (gets refresh_token)
access_type: 'offline',
// If you only need one scope you can pass it as a string
scope: scopes,
prompt: 'consent',
});
// コンソールにURLを表示して、アクセスし認証をしてもらう
console.log('Authorize this app by visiting this url:', url);
- 上記のコードの認証情報の値を先ほど取得した認証情報に変更
- 上記のコードを実行
- コンソールに出力されたURLにアクセス
- 認証
- リダイレクトされたURLの
code=
以降を取得
リフレッシュトークンを取得
先ほど取得したcodeを使い、APIを実行するためのリフレッシュトークンを取得します。
const oauth2Client = new google.auth.OAuth2(
'clientID', // クライアントID
'clientsecret', // クライアントシークレット
'http://localhost:3000/oauth2callback', // リダイレクトURI
);
// URL取得した認証コード
const code =
'code';
// 認証コードをトークンに交換
const { tokens } = await oauth2Client.getToken(code);
console.log('Tokens:', tokens);
- 上記のコードの認証情報の値を先ほど取得した認証情報に変更
- 上記のコードの
code='code'
の値を先ほど取得したcodeに変更 - 上記のコードをを実行
- コンソールに出力されたURLからリフレッシュトークンを取得
Gmailを取得
最新のメールを返すgetNewGmailという関数を作成しました。
また、認証情報等の値は.envで管理するよう修正してあります。
import dotenv from 'dotenv';
import { google } from 'googleapis';
import type { gmail_v1 } from 'googleapis';
/** Read environment variables from file. https://github.com/motdotla/dotenv */
dotenv.config();
export async function getNewGmail(): Promise<null | gmail_v1.Schema$Message> {
try {
// OAuth2 クライアントを設定
const oauth2Client = new google.auth.OAuth2(
process.env.GOOGLE_CLIENT_ID, // クライアントID
process.env.GOOGLE_CLIENT_SECRET, // クライアントシークレット
'http://localhost:3000/oauth2callback', // リダイレクトURI
);
// 保存されたトークンをセット(事前に取得しておく必要があります)
oauth2Client.setCredentials({
refresh_token: process.env.GOOGLE_REFRESH_TOKEN,
});
// Gmail APIクライアントを初期化
const gmail = google.gmail({ version: 'v1', auth: oauth2Client });
// メールを取得
const res = await gmail.users.messages.list({
userId: 'me', // 自分自身
maxResults: 10, // 最大取得数
});
// メールのIDを取得
const messages = res.data.messages;
if (!messages) return null;
// 最初のメールの詳細を取得
const message = await gmail.users.messages
.get({
userId: 'me',
id: messages[0].id!,
})
.then((response) => response.data);
return message;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
- 上記のコードの認証情報の値を先ほど取得した認証情報に変更
- 上記のコードをを実行
自分の場合は特定のエイリアス付きメールアドレス(sample+1@gmail.comのように+付きのメールアドレス)宛に届いた最新のメールを取得したかったので以下のように変更
import dotenv from 'dotenv';
import { google } from 'googleapis';
import type { gmail_v1 } from 'googleapis';
/** Read environment variables from file. https://github.com/motdotla/dotenv */
dotenv.config();
/**
* 特定のメールアドレス宛の最新のGmailのメールを取得する
*
* @param toEmail
* @returns null | gmail_v1.Schema$Message
*/
export async function getNewGmail(
toEmail: string,
): Promise<null | gmail_v1.Schema$Message> {
try {
// OAuth2 クライアントを設定
const oauth2Client = new google.auth.OAuth2(
process.env.GOOGLE_CLIENT_ID, // クライアントID
process.env.GOOGLE_CLIENT_SECRET, // クライアントシークレット
'http://localhost:3000/oauth2callback', // リダイレクトURI
);
// 保存されたトークンをセット(事前に取得しておく必要があります)
oauth2Client.setCredentials({
refresh_token: process.env.GOOGLE_REFRESH_TOKEN,
});
// Gmail APIクライアントを初期化
const gmail = google.gmail({ version: 'v1', auth: oauth2Client });
// エイリアスを含むメールを検索するクエリを設定
const query = `to:${toEmail}`;
// メールを取得
const res = await gmail.users.messages.list({
userId: 'me', // 自分自身
maxResults: 10, // 最大取得数
q: query, // 検索クエリ
});
// メールのIDを取得
const messages = res.data.messages;
if (!messages) return null;
// 最初のメールの詳細を取得
const message = await gmail.users.messages
.get({
userId: 'me',
id: messages[0].id!,
})
.then((response) => response.data);
return message;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
最後に
はじめは捨てメールアドレス生成サービスを利用してメールを受診しようとしたが使い方がわからず、Gmailなら方法があるだろうとGmailでのメール取得してみたらいけた。
メールが取得できなくなった
リフレッシュトークンの期限切れ
昨日までメールの取得ができていたのにできなくなった場合は、リフレッシュトークンの期限が切れている可能性があります。
codeの取得から再度やり直し、リフレッシュトークンを再取得してみてください。
迷惑メールフォルダに入っている
メールが取得できない前に、届いていない。
いつの間にか迷惑メールフォルダに振り分けられていてメールの取得ができなくなっていました。
迷惑メールフォルダにメールが届いていないか確認し、振り分けられていた場合は「迷惑メールではありません」ボタンをクリックするなどして迷惑メールフォルダに振り分けられないようにしてください。