playwrightでMailtrapのapiからメール本文を取得する
やりたいこと
playwrightのテスト内でMailtrapのAPIを叩いて、メール本文を取得し、メールが正しく送信されているかを確認する
背景
自分が使っている環境ではメールは登録されたメアドに飛ばさずに、全てMailtrapに飛ぶようにしている。
e2eテストでメールに記載のURLにアクセスしたくなった。
が、Mailtrapにログインさせるのは避けたいので、apiを叩いてみた。
使用技術
・playwright
・Mailtrap
参考記事
・受信メールの検証、MailTrap
・Mailtrap公式
・Playwright公式
手順
1. API Tokenを取得する
MailTrapにログイン後、API Tokenを取得します。
(画面右上の自分のアカウント名が書かれている箇所をクリック後、MyProfileから確認できます。)
2.Account IDを取得する
settingsのAccount settingsにアクセスし、Account IDを取得します。
3.Inboxのidを取得する
MailTrapのAPIDocsから対象のInboxのidを取得します。
画像右上の黒い箇所に適切なAPI-Tokenとaccount_idを入れて、"Send API Request"をクリックすると後述のResponseが返ってきます。
[
{
"id": 3538,
"name": "Admin Inbox",
"username": "b3a87978452ae1",
"password": "6be9fcfc613a7c",
"max_size": 0,
"status": "active",
"email_username": "b7eae548c3-54c542",
"email_username_enabled": false,
"sent_messages_count": 52,
"forwarded_messages_count": 0,
"used": false,
"forward_from_email_address": "a3538-i4088@forward.mailtrap.info",
"project_id": 2293,
"domain": "localhost",
"pop3_domain": "localhost",
"email_domain": "localhost",
"emails_count": 0,
"emails_unread_count": 0,
"last_message_sent_at": null,
"smtp_ports": [
25,
465,
587,
2525
],
"pop3_ports": [
1100,
9950
],
"max_message_size": 5242880,
"permissions": {
"can_read": true,
"can_update": true,
"can_destroy": true,
"can_leave": true
}
}
]
(こんなめんどくさいことせずとも、任意のInboxのurlに含まれている数字がinboxIdです!)
4.inboxに保存されているメール一覧を取得する
再び、API Docsからメッセージ一覧を取得するAPIRequestを確認します。
今回はGet messagesから確認しました。
それをコードに落とし込むと以下のようになります。
import { request, APIRequestContext } from "@playwright/test";
const MailtrapApiToken = process.env.MAILTRAP_API_TOKEN;
const mailtrapAccountId = process.env.MAILTRAP_ACCOUNT_ID;
const mailtrapInboxId = process.env.MAILTRAP_INBOX_ID;
export async function getMail() {
const mailtrap: APIRequestContext = await request.newContext();
const response = await mailtrap.get(
`https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
}
コードの解説
Tokenなどは秘匿情報になるので、環境変数に入れています。
const MailtrapApiToken = process.env.MAILTRAP_API_TOKEN;
const mailtrapAccountId = process.env.MAILTRAP_ACCOUNT_ID;
const mailtrapInboxId = process.env.MAILTRAP_INBOX_ID;
playwrightで何を操作するかを明記しています。(ここはほぼおまじないなので、よくわからず。)
const mailtrap: APIRequestContext = await request.newContext();
responseをresponse定数に代入しています。
const response = await mailtrap.get(
`https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
5.responseから特定のメールを検索する
今回使っているinboxは自分だけ使っているだけではないので、1番最初のメッセージが自分が送ったメッセージとは限りません。
そのため、今回は「題名」と「メアド」で検索して、任意のメッセージを取得します。
~~中略~~
`https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
const messageResponse = await response.json();
const targetMail = messageResponse.find(
(data) => data.subject === "ホゲホゲ" && data.to_email === "hogehoge@hoge.hoge"
);
}
コード解説
レスポンスの本文をJSON形式として解析し、JavaScriptのオブジェクトとして返します。JSON形式の解析に成功すると、解析結果のオブジェクトがmessageResponseに格納されます。
const messageResponse = await response.json();
messageResponseに格納されているjsonから題名が「ホゲホゲ」で「hogehoge@hoge.hoge」に送られているメッセージを検索し、targetMailに格納しています。
const targetMail = messageResponse.find(
(data) => data.subject === "ホゲホゲ" && data.to_email === "hogehoge@hoge.hoge"
);
6.本文を取得する
先ほど検索したjsonのデータからidを取得し、再びAPIを叩きます。
APIはAPI DocsのGet text messageから確認できます。
~~中略~~
const targetMail = messageResponse.find(
(data) => data.subject === "ホゲホゲ" && data.to_email === "hogehoge@hoge.hoge"
);
const targetMailId = targetMail.id;
const targetMailText = await mailtrap.get( `https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages/${targetMailId}/body.txt`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
const messageText = await targetMailText.text();
return messageText;
}
コード解説
targetMailに格納されているjsonからidを取得し、targetMailIdに格納しています。
const targetMailId = targetMail.id;
get text messageから取得したresponseをtargetMailTextに格納しています。
const targetMailText = await mailtrap.get( `https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages/${targetMailId}/body.txt`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
targetMailTextに格納しているjsonをtextとして取得します。
const messageText = await targetMailText.text();
最後にmessageTextを返すことで、呼び出し元のテストコードで使用できます。
return messageText;
コード全体
import { request, APIRequestContext } from "@playwright/test";
const MailtrapApiToken = process.env.MAILTRAP_API_TOKEN;
const mailtrapAccountId = process.env.MAILTRAP_ACCOUNT_ID;
const mailtrapInboxId = process.env.MAILTRAP_INBOX_ID;
export async function getMail() {
const mailtrap: APIRequestContext = await request.newContext();
const response = await mailtrap.get( `https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
const messageResponse = await response.json();
const targetMail = messageResponse.find(
(data) => data.subject === "ホゲホゲ" && data.to_email === "hogehoge@hoge.hoge"
);
const targetMailId = targetMail.id;
const targetMailText = await mailtrap.get( `https://mailtrap.io/api/accounts/${mailtrapAccountId}/inboxes/${mailtrapInboxId}/messages/${targetMailId}/body.txt`,
{
headers: {
Accept: "application/json",
"Api-Token": MailtrapApiToken,
},
}
);
const messageText = await targetMailText.text();
return messageText;
}
使用例
自分は最後のテキストからURLを取得して、取得したURLにアクセスしテストを続けています。
~~中略~~
const messageText = await targetMailText.text();
// textからURLを取得する操作
const urlRegex = /https?:\/\/[\w-]+(\.[\w-]+)+([^\s]*)+/g;
const url = messageText.match(urlRegex)[0];
return url;
}
呼び出し元
const url = await getMail();
// 文面から取得したURLに移動
await page.goto(url);
最後に
jsonで受け取った後からは、こちらで好き勝手できるものなので、適宜好きにいじってみてください。
playwrighとmailtrapを使用した記事が見つからなかったので、今回作成しました。
少しでもお力になれれば幸いです!
ポップアップストアや催事イベント向けの商業スペースを簡単に予約できる「SHOPCOUNTER」と商業施設向けリーシングDXシステム「SHOPCOUNTER Enterprise」を運営しています。エンジニア採用強化中ですので、興味ある方はお気軽にご連絡ください! counterworks.co.jp/
Discussion