WordPressのお問い合わせフォームは、スパムの対象になりやすいです。
それに加え、お問い合わせフォーム用のプラグインには脆弱性がしばしば見つかります。
実際、プラグインの脆弱性を突かれたハッキングもよく発生します。
個人的には、スパムが嫌ですぐにお問い合わせフォームを閉じました。
そのため、X(旧Twitter)を経由して問い合わせが来ることがあります。
ただ、DMは解放していません。
よって、投稿へのリプという形で問い合わせが来るという感じです。
このこと自体、非常にハードルが上がっています。
だから、お問い合わせを復活させたいとはずっと思っていました。
お問い合わせフォームの復活
この度、約3年振りぐらいにお問い合わせフォームを復活させました。
それは、スパム問題は大丈夫と判断したからです。
自作のフォームなら、そうそう簡単にスパムに侵略されないはずなので。
侵略されたら、その都度対応はしていくつもりです。
自作のため、何とでもできますからね。
あとは、SMTPを利用しないで済む方法が見つかったのも大きいです。
GASを使えば、個人でSMTPを用意しないで済みます。
SMTPによるメール送信は、今後ますます厳しくなっていくはずです。
また、求められるセキュリティレベルもどんどんと高くなります。
それなら、メール送信はGoogleさんに任せようということです。
お問い合わせフォームの構成
WordPressの固定ページを利用しています。
WordPressのソースは、できる限りで触りたくありません。
固定ページにHTMLタグを入力しています。
そして、カスタムCSSとカスタムJavaScriptを利用する形になります。
ここまではWordPressの管理画面だけで済みます。
ただ、ここから先がハードルが少しあがります。
JavaScriptから非同期でPHPにアクセスしています。
そのPHP上でGASにアクセスとなります。
セキュリティに問題なければ、JavaScriptからGASへ直接もありなんですけどね。
それはマズイので、PHPを間に入れているということです。
HTML
<form id="contact-form" method="post">
<div>
<label for="name">名前:</label>
<input type="text" id="name" name="name" required>
</div>
<div>
<label for="email">メールアドレス:</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="message">メッセージ:</label>
<textarea id="message" name="message" required></textarea>
</div>
<div>
<button type="submit">送 信</button>
</div>
</form>
<!-- 確認画面のモーダル(初期状態では非表示) -->
<div id="confirmModal" style="display:none;">
<p><strong>名前:</strong> <span id="confirmName"></span></p>
<p><strong>メールアドレス:</strong> <span id="confirmEmail"></span></p>
<p><strong>メッセージ:</strong></p>
<p style="white-space: pre-line;" id="confirmMessage"></p>
<button id="confirmSubmit">確 定</button>
<div id="loadingSpinner" class="spinner"></div>
<button id="goBack">戻 る</button>
</div>
<!-- 成功メッセージ表示用の要素 -->
<div id="successMessage" style="display: none; padding: 20px; background-color: #4CAF50; color: white; text-align: center; border-radius: 5px;">
お問い合わせを受け付けました。
</div>
カスタムCSS
/* ボタンのスタイル */
button {
background-color: #4CAF50; /* 緑色の背景 */
color: white; /* 白色のテキスト */
padding: 15px 32px; /* 上下15px、左右32pxのパディング */
text-align: center; /* テキストを中央揃え */
text-decoration: none; /* テキストの装飾をなしに */
display: inline-block; /* インラインブロック要素として表示 */
font-size: 16px; /* フォントサイズ */
margin: 4px 2px; /* 上下4px、左右2pxのマージン */
cursor: pointer; /* カーソルをポインターに */
border: none; /* 境界線なし */
border-radius: 5px; /* 角を丸くする */
}
/* ボタンのホバー時のスタイル */
button:hover {
background-color: #45a049; /* ホバー時の背景色を少し暗く */
}
/* フェードインエフェクト */
.fade-in {
animation: fadeIn 1s;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 確認画面モーダルのスタイル */
#confirmModal {
background-color: #f5f5f5;
border: 1px solid #ccc;
padding: 20px;
max-width: 90%;
margin: 0 auto;
}
#confirmModal p {
margin: 10px 0;
}
#confirmModal strong {
font-weight: bold;
}
#confirmModal button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
}
#confirmModal button:hover {
background-color: #0056b3;
}
/* 名前とメールアドレス入力フィールドのスタイル */
#name,
#email {
width: 100%;
padding: 10px;
margin-bottom: 10px;
font-size: 1rem;
}
/* ローディングスピナーのスタイル */
.spinner {
border: 4px solid rgba(0, 0, 0, 0.3);
border-radius: 50%;
border-top: 4px solid #007bff;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: none; /* 初期状態では非表示 */
}
@keyframes spin {
0% { transform: translate(-50%, -50%) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg); }
}
カスタムJavaScript
document.getElementById('contact-form').addEventListener('submit', handleFormSubmit);
function handleFormSubmit(event) {
event.preventDefault(); // 通常の送信を阻止
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
const message = document.getElementById('message').value;
if (!validateFormData(name, email, message)) {
return;
}
setConfirmationData(name, email, message);
toggleDisplay('contact-form', false);
toggleDisplay('confirmModal', true);
document.getElementById('confirmSubmit').onclick = handleConfirmSubmit;
document.getElementById('goBack').onclick = handleGoBack;
}
function validateFormData(name, email, message) {
if (name === '') {
alert('名前を入力してください。');
return false;
}
if (!email.match(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/)) {
alert('有効なメールアドレスを入力してください。');
return false;
}
if (message === '') {
alert('メッセージを入力してください。');
return false;
}
return true;
}
function setConfirmationData(name, email, message) {
document.getElementById('confirmName').textContent = name;
document.getElementById('confirmEmail').textContent = email;
document.getElementById('confirmMessage').textContent = message;
}
function toggleDisplay(elementId, show) {
document.getElementById(elementId).style.display = show ? 'block' : 'none';
}
function handleConfirmSubmit() {
const submitButton = document.getElementById('confirmSubmit');
submitButton.disabled = true;
submitButton.textContent = '送信中...';
toggleDisplay('loadingSpinner', true);
const formData = {
name: document.getElementById('confirmName').textContent,
email: document.getElementById('confirmEmail').textContent,
message: document.getElementById('confirmMessage').textContent
};
sendFormData(formData)
.then(response => {
if (response.success) {
toggleDisplay('successMessage', true);
toggleDisplay('confirmModal', false);
window.scrollTo(0, 0);
} else {
alert('エラーが発生しました。\n' + response.error);
}
})
.catch(() => alert('メールの送信に失敗しました。'))
.finally(() => {
submitButton.disabled = false;
submitButton.textContent = '確定';
toggleDisplay('loadingSpinner', false);
});
}
function handleGoBack() {
toggleDisplay('contact-form', true);
toggleDisplay('confirmModal', false);
}
function sendFormData(formData) {
return fetch('/sv/api/send_mail.php', {
method: 'POST',
headers: {'Content-Type': 'application/json;charset=UTF-8'},
body: JSON.stringify(formData)
})
.then(response => {
if (!response.ok) {
throw new Error('ネットワークレスポンスが不正です。');
}
return response.json();
})
.catch(error => {
throw new Error('リクエスト中にエラーが発生しました: ' + error.message);
});
}
PHP(send_mail.php)に関しては、非公開としておきます。
さすがに手の内を晒すのは、マズイと思いますので。
でも、60行前後のソースのため複雑なことはありません。
このPHPから、GASのプログラムにアクセスしています。
GASのプログラムは、上記記事内で紹介したそのままです。
そして、アクセスと言っても単なるHTTPリクエストです。
curlも使っていません。
それでも、send_mail.phpの中身を知りたい場合は下記から問い合わせてください。
メールで情報を返信します。
なお、この自作のお問い合わせフォームは2時間で制作しました。
コードは、ほぼChatGPTに書かせました。
要件入力、検証、レビューを繰り返しただけです。
それだけでお問い合わせフォームが、簡単に作れます。
なお、嘘のような本当の話ですが、早速問い合わせがありました。
復活から24時間も経っていないのに、仕事の依頼です。
復活させた甲斐があると言うもんです。






