コンテンツへスキップ

WordPress 管理画面の「6 ヶ月ごとの管理者メール確認画面」を Playwright で自動突破する

WordPress 管理画面を Playwright で自動操作していると、ある日突然、約半年に 1 回だけ出てくる謎の画面でログイン後の処理が止まることがあります。

管理者のメールアドレスは合っていますか?
admin@example.com

[ 正しいメールアドレスです ]
[ 別のメールに変更する ]

WordPress の 管理者メール確認画面。約 6 ヶ月ごとに、管理者がログインした直後に挟まる確認画面で、WP 4.9 以降の標準仕様です。手動でログインしている人にとっては「OK」を押すだけの 1 ステップですが、自動化スクリプトには見えない壁になります。

なぜ自動化が詰まるのか

ログイン処理を素直に書くと、Playwright の流れはこうなります:

page.fill('#user_login', user)
page.fill('#user_pass', pwd)
page.click('input[type="submit"]')           # ログインボタン
page.wait_for_load_state('domcontentloaded')
# ← ダッシュボードに着いた前提で次の操作
page.goto('/wp-admin/plugins.php')

ところが確認画面が挟まる日は、wait_for_load_state の直後にいる URL が /wp-admin/profile.php?...action=confirm_admin_email... のような確認画面です。プラグイン一覧に飛ぶつもりが、確認画面のままで「プラグイン一覧の DOM が無い → スクレイピング失敗 → 後続全滅」というドミノが起きます。

確認画面を判別するセレクタ

WordPress が確認画面で出す送信ボタンは固有のセレクタを持っています:

<input type="submit"
       name="correct-admin-email"
       value="正しいメールアドレスです" />

name="correct-admin-email" の input がページに存在すれば、それは確認画面。この 1 件のセレクタが存在判定とクリック対象を兼ねるので、ハンドリングは数行で済みます。

admin_email_confirm = page.locator(
    'input[type="submit"][name="correct-admin-email"]'
)
if admin_email_confirm.count() > 0:
    logger.info("管理者メール確認画面を検出。『正しいメールアドレスです』をクリック")
    admin_email_confirm.first.click()
    page.wait_for_load_state('domcontentloaded', timeout=30000)

パスワード送信直後の wait_for_load_state、後続処理の に挟む。これで確認画面が出ても出なくても透過的に動きます。

コード重複によるハンドリング欠落バグ

実は、私たちのアプリ内でこの処理を 4 箇所に重複実装していました:

  • メンテナンス本体のログイン処理 ✓
  • visual_check(更新前後のスクリーンショット取得)のログイン処理 ✓
  • サムネイル取得用ログイン処理 ✓
  • ブラウザ補完更新(プラグイン管理画面経由の独自 updater 対応)のログイン処理 ❌

最後のブラウザ補完更新は新規追加時に他 3 箇所からのコピーを忘れたため、ハンドラが入っていませんでした。実害として、確認画面が出るタイミングで ACF Pro / Yoast SEO Premium / WP Rocket / Elementor Pro 等の有料プラグイン更新を完全に逃す可能性があった。

似た構造の問題は SSH 秘密鍵 7 形式の互換ローダー でも踏んでいて、「同じ処理が複数箇所に複製されると、新規追加時にコピー漏れが発生する」というのは典型的な構造バグです。共通化を後付けで進めるか、最低でもテストで「全箇所で同じ振る舞いをするか」を網羅するのが現実的な防止策になります。

テストでの再発防止

修正と同時に 3 件のテストを追加しました:

  1. 確認画面あり → click 発生: 確認画面 HTML を返すモックで、click() が呼ばれることを確認
  2. 確認画面なし → click 発生せず: 通常のダッシュボード HTML で、click() が呼ばれないことを確認(誤検出しない)
  3. click 後も認証失敗 → ログイン失敗扱いのまま: 確認画面はクリックしたが結局ダッシュボードに辿り着けない場合、誤って成功扱いにしないことを確認

特に 2 番目と 3 番目は「ハンドラが入ったことで別の誤動作を生まないか」のリグレッション防止用。「機能追加時に並走させるネガティブテスト」は地味だけど効きます。

まとめ — WordPress の「半年ごとの罠」

WordPress 管理画面を Playwright で長期運用していると、実装時には目に見えない「半年に 1 回だけ出る画面」が後から牙を剥く場面が複数あります。管理者メール確認画面はその代表例で、出ない日にテストが通っていても、出る日には全部止まる。

確認画面の存在をコードに明示的に書くことと、コードを複数箇所に複製しているなら全箇所に同じハンドリングを揃えること。この 2 点を意識しておくと、WordPress × Playwright の長期運用が安定します。