# フォームは成功表示なのにメールが来ないときの切り分け

送信リクエスト、API応答、保存、迷惑送信、受信者確認、Turnstileを順に確認して原因を探します。

Author: Formgong
Published: 2026-10-01
Language: ja
Canonical: https://formgong.com/blog/contact-form-not-sending-email?lang=ja

サイトのリクエスト、Formgongの記録、確認済み受信者へのメール通知を分けて確認します。success: trueは受付の応答で、メール到着の証明ではありません。迷惑送信や未確認アカウント、Turnstileも調べてください。

## 受付・保存・通知は別の結果

お礼の表示は画面上だけで出せます。保存された記録と到着したメールは別の段階です。公開サイトで識別しやすいテストを送り、同じ送信を追いましょう。以下のコードはFormgong固有です。他サービスではそのドキュメントを参照します。

## Networkで送信を探す

開発者ツールを開いて送信し、`https://formgong.com/submit`へのPOSTを探します。キー、フィールド、応答を確認してください。リクエストがなければボタンや送信処理を見直します。HTMLは`action`と`method`、JavaScriptは`fetch`のURLを確認します。

## 応答を読んで成功を判断

`Accept: application/json`でJSONを求め、HTTPと`success`を両方確認します。fetchが完了してもエラー応答の場合があります。通常のHTML送信はリダイレクトを受け取ります。例は`try/catch`で呼び、失敗時に入力を残します。

```javascript
// Call from your form's submit handler inside try/catch.
// Keep the entered fields when the request fails.
async function sendContactForm(form) {
  const response = await fetch("https://formgong.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: JSON.stringify({
      ...Object.fromEntries(new FormData(form)),
      access_key: "fk_your_access_key",
    }),
  });
  const result = await response.json();
  if (!response.ok || result.success !== true) {
    throw new Error(result.message || "Submission failed");
  }
  // Accepted by Formgong; this is not email-delivery confirmation.
  return result.id;
}
```

## エラーコードに合わせて調べる

`unknown_access_key`はキー、`origin_not_allowed`は許可ドメインの問題です。`turnstile_missing`や`turnstile_failed`はトークンを確認します。`rate_limited`と`limit_exceeded`は異なる制限で、連打では解決しません。

送信中はボタンを無効にし、完了後に戻します。失敗してもメッセージを消さないでください。

## 対象フォームと迷惑送信を確認

サイトのキーに対応するフォームを開きます。`botcheck`が埋まると、成功に見える応答でも迷惑送信として保存され、通知されない場合があります。AI評価で迷惑送信を保留する設定なら、その判定も確認します。

## 記録があればメール設定へ

アカウントのメール確認、通知の有効化、受信者の確認を調べます。続いて迷惑メール、フィルター、転送設定を確認してください。

Telegramへの到着はメール側に原因を絞る手掛かりですが、メール到着の証明ではありません。訪問者への自動返信も別のメールです。

## 対策変更後に止まった場合

最新のsite keyと`cf-turnstile-response`を使います。トークンは期限付きで一度だけ有効なので、再試行時にウィジェット更新が必要な場合があります。secret keyはブラウザーに入れません。

## 調査を続けるための記録

URL、時刻、HTTP状態、エラーコード、存在する場合は送信IDを残します。顧客情報や秘密キーは公開しないでください。修正したら全経路をもう一度確認します。

シンプルな接続は[HTMLの例](/blog/html-contact-form-without-backend?lang=ja)、別の通知先は[Telegramガイド](/blog/website-form-to-telegram?lang=ja)で設定できます。

## よくある質問

### success: trueはメール到着を意味しますか？

いいえ。リクエストが受け付けられたことを示し、通知の配信は別の処理です。

### Telegramだけ届くのはなぜですか？

別々の通知経路だからです。メール通知、受信者確認、迷惑メールを調べてください。

### botcheckでエラーにならないのはなぜですか？

Bot対策のため、成功に見せたまま迷惑送信として保存し、通知しない場合があります。

### Turnstileの再試行はどうしますか？

新しいトークンを取得し、cf-turnstile-responseで送られることを確認します。使用済みトークンは再利用しません。

## 参考資料・ドキュメント

- [MDN: Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
- [Cloudflare: Turnstile token validation](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/)
- [Formgongドキュメント](https://formgong.com/docs?lang=ja)

[フォームキーを取得](https://formgong.com/?lang=ja#top)
