メールを送るJavaScriptお問い合わせフォーム
Formgong team ·
JavaScriptのお問い合わせにもPOSTの宛先が要ります。fetchを呼び、項目を送り、JSONの返事を読みます。Formgongはその呼び出しを、あなたのサーバなしで受けます。ライブラリもAPI経路も要りません。無料プランではTelegramはすぐで、メールは1日1通のまとめです。
このJavaScriptフォームをコピー
<form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="en">
<label>Name <input type="text" name="name" autocomplete="name" placeholder="Your name" required></label>
<label>Email <input type="email" name="email" autocomplete="email" placeholder="you@example.com" required></label>
<label>Message <textarea name="message" placeholder="How can we help?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Leave this field empty<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Send</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Sent. Thank you!" : "Could not send. Please try again.");
if (result.success) form.reset();
} catch {
status.textContent = "Connection failed. Please try again.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="uk">
<label>Ім’я <input type="text" name="name" autocomplete="name" placeholder="Ваше ім’я" required></label>
<label>Email <input type="email" name="email" autocomplete="email" placeholder="you@example.com" required></label>
<label>Повідомлення <textarea name="message" placeholder="Чим ми можемо допомогти?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Залиште це поле порожнім<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Надіслати</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Надіслано. Дякуємо!" : "Не вдалося надіслати. Спробуйте ще раз.");
if (result.success) form.reset();
} catch {
status.textContent = "Немає з’єднання. Спробуйте ще раз.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="pl">
<label>Imię <input type="text" name="name" autocomplete="name" placeholder="Twoje imię" required></label>
<label>E-mail <input type="email" name="email" autocomplete="email" placeholder="ty@example.com" required></label>
<label>Wiadomość <textarea name="message" placeholder="W czym możemy pomóc?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Pozostaw to pole puste<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Wyślij</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Wysłano. Dziękujemy!" : "Nie udało się wysłać. Spróbuj ponownie.");
if (result.success) form.reset();
} catch {
status.textContent = "Brak połączenia. Spróbuj ponownie.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="tr">
<label>Ad <input type="text" name="name" autocomplete="name" placeholder="Adınız" required></label>
<label>E-posta <input type="email" name="email" autocomplete="email" placeholder="siz@ornek.com" required></label>
<label>Mesaj <textarea name="message" placeholder="Size nasıl yardımcı olabiliriz?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Bu alanı boş bırakın<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Gönder</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Gönderildi. Teşekkürler!" : "Gönderilemedi. Lütfen tekrar deneyin.");
if (result.success) form.reset();
} catch {
status.textContent = "Bağlantı kurulamadı. Lütfen tekrar deneyin.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="es">
<label>Nombre <input type="text" name="name" autocomplete="name" placeholder="Tu nombre" required></label>
<label>Correo electrónico <input type="email" name="email" autocomplete="email" placeholder="tu@ejemplo.com" required></label>
<label>Mensaje <textarea name="message" placeholder="¿En qué podemos ayudarte?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Deja este campo vacío<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Enviar</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Enviado. ¡Gracias!" : "No se pudo enviar. Inténtalo de nuevo.");
if (result.success) form.reset();
} catch {
status.textContent = "Error de conexión. Inténtalo de nuevo.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="fr">
<label>Nom <input type="text" name="name" autocomplete="name" placeholder="Votre nom" required></label>
<label>E-mail <input type="email" name="email" autocomplete="email" placeholder="vous@exemple.com" required></label>
<label>Message <textarea name="message" placeholder="Comment pouvons-nous vous aider ?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Laissez ce champ vide<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Envoyer</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Envoyé. Merci !" : "Échec de l’envoi. Veuillez réessayer.");
if (result.success) form.reset();
} catch {
status.textContent = "Connexion impossible. Veuillez réessayer.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="pt">
<label>Nome <input type="text" name="name" autocomplete="name" placeholder="O seu nome" required></label>
<label>E-mail <input type="email" name="email" autocomplete="email" placeholder="voce@exemplo.com" required></label>
<label>Mensagem <textarea name="message" placeholder="Como podemos ajudar?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Deixe este campo vazio<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Enviar</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Enviado. Obrigado!" : "Não foi possível enviar. Tente novamente.");
if (result.success) form.reset();
} catch {
status.textContent = "Falha na ligação. Tente novamente.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="ar">
<label>الاسم <input type="text" name="name" autocomplete="name" placeholder="اسمك" required></label>
<label>البريد الإلكتروني <input type="email" name="email" autocomplete="email" placeholder="you@example.com" required></label>
<label>الرسالة <textarea name="message" placeholder="كيف يمكننا مساعدتك؟" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>اترك هذا الحقل فارغًا<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">إرسال</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "تم الإرسال. شكرًا لك!" : "تعذّر الإرسال. يرجى المحاولة مرة أخرى.");
if (result.success) form.reset();
} catch {
status.textContent = "فشل الاتصال. يرجى المحاولة مرة أخرى.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="he">
<label>שם <input type="text" name="name" autocomplete="name" placeholder="השם שלך" required></label>
<label>אימייל <input type="email" name="email" autocomplete="email" placeholder="you@example.com" required></label>
<label>הודעה <textarea name="message" placeholder="איך נוכל לעזור?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>השאירו שדה זה ריק<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">שליחה</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "נשלח. תודה!" : "השליחה נכשלה. נא לנסות שוב.");
if (result.success) form.reset();
} catch {
status.textContent = "אין חיבור. נא לנסות שוב.";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="hi">
<label>नाम <input type="text" name="name" autocomplete="name" placeholder="आपका नाम" required></label>
<label>ईमेल <input type="email" name="email" autocomplete="email" placeholder="you@example.com" required></label>
<label>संदेश <textarea name="message" placeholder="हम आपकी कैसे मदद कर सकते हैं?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>इस फ़ील्ड को खाली छोड़ें<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">भेजें</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "भेज दिया गया। धन्यवाद!" : "भेजा नहीं जा सका। कृपया फिर से कोशिश करें।");
if (result.success) form.reset();
} catch {
status.textContent = "कनेक्शन विफल। कृपया फिर से कोशिश करें।";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="ja">
<label>お名前 <input type="text" name="name" autocomplete="name" placeholder="山田 太郎" required></label>
<label>メールアドレス <input type="email" name="email" autocomplete="email" placeholder="you@example.com" required></label>
<label>メッセージ <textarea name="message" placeholder="ご用件をご記入ください" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>この欄は空のままにしてください<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">送信</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "送信しました。ありがとうございます。" : "送信できませんでした。もう一度お試しください。");
if (result.success) form.reset();
} catch {
status.textContent = "接続できませんでした。もう一度お試しください。";
} finally {
button.disabled = false;
}
});
</script><form id="fg-contact" action="https://formgong.com/submit" method="POST">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="de">
<label>Name <input type="text" name="name" autocomplete="name" placeholder="Ihr Name" required></label>
<label>E-Mail <input type="email" name="email" autocomplete="email" placeholder="name@beispiel.de" required></label>
<label>Nachricht <textarea name="message" placeholder="Wie können wir Ihnen helfen?" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Lassen Sie dieses Feld leer<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<button type="submit">Senden</button>
<p role="status"></p>
</form>
<script>
const form = document.querySelector("#fg-contact");
const status = form.querySelector("[role=status]");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const button = form.querySelector("button");
button.disabled = true;
const fields = Object.fromEntries(new FormData(form));
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(fields),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "Gesendet. Vielen Dank!" : "Das Senden ist fehlgeschlagen. Bitte versuchen Sie es erneut.");
if (result.success) form.reset();
} catch {
status.textContent = "Die Verbindung ist fehlgeschlagen. Bitte versuchen Sie es erneut.";
} finally {
button.disabled = false;
}
});
</script>JSONの代わりにFormDataを送る
<script>
const form = document.querySelector("#fg-contact");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const status = form.querySelector("[role=status]");
try {
const response = await fetch("https://formgong.com/submit", {
method: "POST",
headers: { Accept: "application/json" },
body: new FormData(form),
});
const result = await response.json();
status.textContent = result.message || (result.success ? "送信しました。ありがとうございます。" : "送信できませんでした。もう一度お試しください。");
if (!result.success) return;
form.reset();
} catch {
status.textContent = "接続できませんでした。もう一度お試しください。";
}
});
</script>フォームが既にあるときのfetchだけ
async function onSubmit(event) {
event.preventDefault();
const fields = Object.fromEntries(new FormData(event.currentTarget));
const response = await fetch("https://formgong.com/submit", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
// _lang: language of Formgong messages and the autoreply (multilingual site: document.documentElement.lang).
body: JSON.stringify({ _lang: "ja", ...fields, access_key: "fk_your_access_key" }),
});
const result = await response.json();
if (!result.success) throw new Error(result.message || "送信できませんでした。もう一度お試しください。");
return result.message; // localized "Sent. Thank you!"
}JavaScriptでのフォームの仕組み
探すのはメールを送るJavaScriptフォームで、fetchフォームではありません。fetchはPOSTをするブラウザの呼び出しにすぎません。EmailJSもAxiosもサーバ経路も要りません。
Acceptにapplication/jsonを付けないと、素のフォームと同じく転送が返ります。失敗したfetchは例外になります。拒まれた件はsuccessがfalseで、見せられる文が返ります。
JavaScriptでの設定手順
- Formgongでフォームを作り、鍵をコピーします。
- 上のコードを貼ります。フォームと短いスクリプトです。asyncとawait、JSON、通信失敗のtry catchです。
- 罠の項目は空のまま、画面の外に置きます。ボットが埋めると、件は迷惑として残り、届きません。
- スクリプトは送信中にボタンを止め、返事の文を出します。成功するとフォームを空にします。
- 公開ページを開き、試験を送ります。受信箱を見て、電話に知らせるならTelegramをつなぎます。
JavaScriptフォームを送る方法
| 方法 | 自分で動かすもの | 届くもの |
|---|---|---|
| mailto: | サーバには何もありません。メールアプリが開きます。 | 相手が送ったときだけ届きます。電話では壊れやすいです。 |
| 自分のAPI経路 | サーバ、SMTP、秘密です。 | 自分で扱うメールです。迷惑メール、停止、コードも自分のものです。 |
| EmailJS | ページ上の相手のスクリプトです。 | 相手のサービス経由のメールです。この行に料金はありません。その日は料金を見直していません。 |
| Formspree | なし。ブラウザがFormspreeへ送ります。 | メールと画面です。無料は月50件です。Personalは月15ドルです。 |
| Formgong | なし。fetchがFormgongへ送ります。 | Telegramはすぐです。Freeのメールは1日1通のまとめです。月300件で、データはEUです。 |
Formspreeの料金は2026-10-06のformspree.io/plansです。Formgongの上限はコードです。EmailJSはこの検索に出ます。料金はその日見直していません。Web3Forms.comはHTTP 403だったので表にありません。
コンポーネントパッケージ: npm install @formgong/core (npm: @formgong/core)
既存のプロジェクトに追加: npx formgong init (npm: formgong)
fetch、ライブラリ、自分のサーバ
素のJavaScript、小さな部品、または窓ならこのページです。相手はページに残ります。
JavaScriptが切れているかもしれないなら素のHTMLです。上のフォームにはactionがあるので、スクリプトがなくても動きます。
自分のアプリのデータを変えるときだけ、自分のサーバを書きます。EmailJSは自分のスクリプトで送ります。Formgongは1回のPOSTです。
よくある質問
JavaScriptはサーバなしでフォームをメールできますか
ブラウザはSMTPを話しません。項目をPOSTで受け口へ送れます。メールを送るのはその受け口です。このフォームのためにサーバは動かしません。
FormDataとJSONのどちらですか
JSONは文字の項目に向きます。FormDataはフォームが既にあるときと、ファイルを送るときに向きます。どちらも同じ受信箱です。FormDataではContent-Typeを自分で付けません。
JSONではなく転送が返るのはなぜですか
素のフォームのPOSTは転送を返します。JSONにするにはAcceptにapplication/jsonを付けます。そのあとsuccessと文を読みます。
失敗はどう扱いますか
失敗したfetchは例外です。それは通信の失敗です。拒まれた件はsuccessがfalseのJSONです。その文を出し、入力した内容は残します。
EmailJSや別のライブラリは必要ですか
不要です。fetchはブラウザにあります。既に使うライブラリでも同じ項目と同じヘッダを送れば足ります。