# PHP なしで HTML フォームをメールに送る

> mail() を呼ぶ contact.php スクリプトを、ホストされたエンドポイントに送信するフォームに置き換えます。フィールド名、サンクスページ、返信はそのままです。

公開日 2026-10-25 · https://ikiform.com/ja/guides/send-form-to-email/without-php

フォームの `action` を PHP スクリプトからフォームバックエンドの URL に変え、フィールド名はそのままにして、スクリプトを削除します。バックエンドは `mail()` がしていたことに加え、それが苦手だったスパム除外、保存、迷惑メールにならない送信も行います。PHP がまったく動かない静的ホストでも動きます。

## ここが違う

PHP のお問い合わせフォームのほとんどは、何年も前にチュートリアルからコピーされた同じ 20 行ほどのコードです。`$_POST` を読んで文字列を組み立て、`mail()` を呼んでリダイレクトします。典型的な例です:

`contact.php`:

```php
<?php
$name = $_POST["name"];
$email = $_POST["email"];
$phone = $_POST["phone"];
$message = $_POST["message"];

$to = "hello@example.com";
$subject = "Website enquiry from $name";
$body = "Name: $name\nEmail: $email\nPhone: $phone\n\n$message";
$headers = "From: $email\r\nReply-To: $email";

if (mail($to, $subject, $body, $headers)) {
  header("Location: /thanks.html");
} else {
  echo "Sorry, something went wrong.";
}
```

一見無害で、書かれた当時は動いていました。しかし今は 4 つの点で壊れていて、明らかなのは最初の 1 つだけです:

| 問題 | 原因 |
| --- | --- |
| ホストに PHP がない | GitHub Pages、Netlify、Vercel、Cloudflare Pages、S3 はファイルを配信するだけで、PHP は実行しません。フォームは実行されないファイルに送信され、`404` か `405` が返ります。 |
| メールが迷惑メールになる、または消える | `mail()` はメッセージをサーバー内のメールプログラムに渡します。`From:` ヘッダーは訪問者のアドレスを名乗りますが、メールはホストのサーバーから送られるので、訪問者のドメインの SPF と DMARC のチェックに通りません。Gmail や Outlook はそれを振り分けるか拒否し、多くの場合は何も通知しません。 |
| ヘッダーインジェクション | `$email` は確認されないままヘッダーに入ります。改行を含む値を送るボットは独自の `Bcc:` 行を追加し、あなたのフォームを使ってスパムを送れるので、ホストの IP がブロックリストに載ってしまいます。 |
| 何も残らない | メールが失われると、メッセージも失われます。記録もスパムフィルターもなく、先月の問い合わせを見返す手段もありません。 |

それぞれ直すこともできます。すべての値を検証し、PHPMailer などのライブラリで SMTP プロバイダー経由で送り、自分のドメインに SPF と DKIM を設定し、ハニーポットとレート制限を追加し、データベースに記録します。すでに PHP を運用しているなら妥当な作業です。そうしたくないなら、その仕事をフォームバックエンドに任せましょう。

図: PHP の mail() を使う場合とフォームバックエンドを使う場合の同じフォーム

1. contact.php では、フォームはホストに送信し、mail() は訪問者から来たと名乗るメッセージを送ります。受信側のサーバーは送信者がドメインと一致しないと判断し、迷惑メールに振り分けるか破棄します。
2. フォームバックエンドでは、フォームは同じフィールドを Ikiform に送信します。Ikiform は自身のドメインからメールを送り、訪問者のアドレスを Reply-To に入れます。Reply-To は本来そのためのものです。

到達率の解決策は、よりよいスクリプトではありません。送信を許可されたドメインから送ることです。

## フォームを PHP から移す

フィールド名は今のまま変えないでください。変えるのは `action` と、2 つの hidden 入力欄の追加だけです:

`変更前`:

```html
<form action="/contact.php" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>
```

`変更後`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <input type="hidden" name="_redirect" value="https://example.com/thanks.html" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>
```

次に、スクリプトがしていたことを、今どこで行うかに対応づけます:

| contact.php での処理 | 現在 |
| --- | --- |
| `$to = "hello@example.com"` | フォームの **Notifications** 設定にある受信者 |
| `header("Location: /thanks.html")` | hidden 入力欄の `_redirect`、またはフォーム設定の **Redirect after submit** |
| `Reply-To: $email` | フィールド名が `email` なので自動 |
| `$subject = "Website enquiry from $name"` | `New submission: <form name>` で固定。文言を残したいなら、フォーム名を「Website enquiry」にします |
| `echo "Sorry, something went wrong."` | 通常の送信なら Ikiform のエラーページ、`fetch` なら自分のメッセージ |
| 自分では書いていなかったチェック | `_gotcha` ハニーポット、スパムスコア、レート制限、フィールドのバリデーション |

- 自分のドメインを **Allowed domains**（許可ドメイン）に追加します。`_redirect` は、それらのドメインにある `https:` の URL でしか機能しません。
- 新しいフォームが動いたら、サーバーから `contact.php` を削除します。放置されたスクリプトは、URL を覚えているボットにとって開いたままのメールリレーです。
- 静的ホストに移った場合、古い `/contact.php` の URL はもう存在しません。そこに直接送信するボットは `404` を受け取りますが、それで問題ありません。

> フォームがスクリプトではなく WordPress のプラグインだった場合も、考え方は同じです。ブロックテーマのどこにフォームを置くかは [WordPress のガイド](https://ikiform.com/ja/docs/guides/wordpress.md)にあります。

## 動作を確認する

1. フォームの **Allowed domains** に自分のサイトのドメインと、開発中は `localhost` を追加します。空にしておくと、どこからの送信でも受け付けます。
2. 公開中のページでフォームを送信します。以前の `thanks.html` に移動します。
3. ダッシュボードで **Submissions** を開きます。送ったすべてのフィールドを含む新しい送信データがあります。
4. メールを開きます。訪問者のアドレスではなく Ikiform から届き、迷惑メールにも入っていません。送信元を連絡先に追加しておけば、以降のメールも迷惑メールに入りません。
5. **Reply**（返信）を押します。**To** 欄に訪問者のアドレスが入っています。
6. ハニーポットを埋めて `_gotcha=bot` で送信します。成功の応答は返りますが、送信データはスパムとして保存され、メールも Webhook も送られません。

## ハマりどころ

- **角かっこ付きの古いフィールド名。** PHP のフォームでは `contact[email]` のような名前がよく使われます。Ikiform はそのまま保存しますが、返信先は `email` という名前のフィールドか、それに近いいくつかの名前からしか取りません。フィールド名を変えるか、`_replyto` を追加してください。
- **件名に名前を入れられません。** スクリプトの件名には訪問者の名前が入っていました。通知メールの件名は固定で、`_subject` は Webhook と API に渡されるだけで、メールは変わりません。
- **文字コード。** `mail()` のスクリプトは charset を設定していないことが多く、アクセント記号がよく文字化けしていました。Ikiform のメールは UTF-8 なので、どの文字体系の名前も崩れずに届きます。
- **`$to` に複数のアドレス。** スクリプトのカンマ区切りのリストは、ダッシュボードではそれぞれ別の受信者になります。外部のアドレスは、何かを受け取る前にリンクで確認します。[複数の受信者](https://ikiform.com/ja/guides/send-form-to-email/multiple-recipients.md) を参照してください。

## うまくいかないとき

| 問題 | 対処法 |
| --- | --- |
| ブラウザーが自分のページではなく Ikiform のサンクスページに移動する | `_redirect` は、ドメインが **Allowed domains** にあり、かつ `https:` の URL でないと無視されます。ドメインを追加するか、代わりにフォーム設定で **Redirect after submit** を設定してください。 |
| `403 origin_not_allowed` が返るか、すべての送信がスパムになる | ページのドメインがフォームの **Allowed domains** にありません。追加し、ローカルでのテスト用に `localhost` も追加してください。登録したドメインのサブドメインは許可されます。 |
| フォームがまだ PHP ファイルに送信している | キャッシュされたページや、フッターのインクルードなどフォームの 2 つ目のコピーに、古い `action` が残っています。サイト全体で `contact.php` を検索してください。 |
| 送信データはダッシュボードにあるのに、メールも Webhook も届かない | スパムとして保存されています。スパムでは何も送られません。**Spam** フィルターで開いて理由を確認し、スパムではないとマークすればメールと Webhook が送られます。 |

## よくある質問

### 切り替えの間も古いフォームは動き続けますか？

はい。フォームの action を変えるまで古いスクリプトは動き続けるので、まずページのコピーで新しいエンドポイントをテストし、それから切り替えてスクリプトを削除できます。

### PHP なしで HTML フォームをメールに送れますか？

はい。フォームの action を PHP スクリプトではなくフォームバックエンドに向けます。バックエンドが送信を受け取ってメールで知らせるので、サイトはどの静的ホスト上のプレーンな HTML でも構いません。

### PHP の mail() で送ったメールが迷惑メールになるのはなぜですか？

スクリプトはたいてい From ヘッダーを訪問者のアドレスにしますが、メールはあなたのホストのサーバーから送られます。そのため訪問者のドメインの SPF と DMARC のチェックに失敗し、Gmail や Outlook は偽装とみなします。フォームバックエンドは自分のドメインから送信し、代わりに訪問者を Reply-To に入れます。

### フィールド名を変える必要はありますか？

いいえ。Ikiform は送信されたどんな名前でも保存します。返信が訪問者に届くよう、メールのフィールド名は email、email_address、your_email、reply_to、contact_email のいずれかにするか、_replyto フィールドを追加してください。

### SMTP を使う PHPMailer のほうがよいですか？

SPF と DKIM を設定した自分のドメインでプロバイダー経由で送れば、到達率の問題は解決します。それでも PHP のホスト、バリデーション、スパムフィルター、メッセージの保管場所は必要です。すでに PHP のコードを保守しているなら良い選択です。

## その他のガイド

- [フォームをメールに送る](https://ikiform.com/ja/guides/send-form-to-email.md): メールサーバーなしで、すべての送信データを受信トレイに届けます。mailto: と PHP の mail() がうまくいかない理由と、スパムを除外して返信もできる構成を解説します。
- [Gmail へ](https://ikiform.com/ja/guides/send-form-to-email/gmail.md): mailto: リンクもアプリパスワードも Apps Script も使わずに、フォームの送信データを Gmail で受け取り、ラベルを付け、迷惑メールを避け、Gmail から返信します。
- [受信トレイから返信](https://ikiform.com/ja/guides/send-form-to-email/reply-to.md): フォームの通知メールで Reply を押すと、フォームに入力した人宛てになるようにします。使えるフィールド名、_replyto を使う場面、返信が迷子になる理由を説明します。
- [複数の受信者](https://ikiform.com/ja/guides/send-form-to-email/multiple-recipients.md): 1 つのフォームをチーム全員にメールで送ったり、トピックごとに適切な担当者に振り分けたり。ただし、誰に送るかをフォーム自身には決めさせません。
- [EmailJS の代替](https://ikiform.com/ja/guides/send-form-to-email/emailjs-alternative.md): お問い合わせフォームを EmailJS から移行。ブラウザー側のメールキーのリスク、コードの変更点、自動返信など失うものを解説します。
- [Next.js](https://ikiform.com/ja/guides/send-form-to-email/nextjs.md): Server Action で Next.js のフォームをメールで送る 2 つの方法を公平に比較します。Resend や Nodemailer で自分で送るか、フォームバックエンドに転送するかです。
