amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
x
telegram
steam
nintendo switch
email

phpフォームの送信と自動メール送信

最近html5upでホームページのテンプレートを見つけました。テンプレートの下にフォームがあり、今日テンプレートを修正しているときに、友人がフォームを設定して送信時に自動的にメール通知を送ることができると言ったので、このアイデアが浮かびました。結果、思ったよりも時間がかかり、三、四時間もかかってしまいました(主にネット上のいくつかの「チュートリアル」がひどすぎたせいです!)。そのため、設定プロセスを記録して後の人の参考にします。

サーバーに php, php-fpm をインストールする#

著者は ubuntu18.04 を使用しているため、次のコマンドを使用します。

sudo apt-get install php
sudo apt-get install php-fpm

ウェブサーバーに php サポートを追加する#

著者は nginx を使用しており、php をサポートするために設定ファイルを少し変更する必要があります。ネット上の多くのチュートリアルではnginx.confを変更する必要があると言っていますが、私のところの設定ファイルは彼らのものと大きく異なることがわかりました。後で実際に試したところ、/etc/nginx/sites-available/defaultを変更するのが有効でした。ファイルの php に関連する部分を次のように変更します。

        # PHPを使用している場合はindex.phpをリストに追加
        index index.html index.htm index.nginx-debian.html index.php;

        server_name _;
        
		# nginxは静的ファイルがpostリクエストに応答することを許可しないため、405 not allowedのメッセージが表示されます。そのため、以下の内容を追加する必要があります。
		# 8080ポートを開く必要があります。または、現在開いているポートに変更することもできます(おそらく)。
        error_page  405 =200 @405;
        location @405 {
            proxy_method GET;
            proxy_pass http://あなたのアドレス:8080;
        }

        location / {
                # 最初にリクエストをファイルとして提供しようとし、次に
                # ディレクトリとして、最後に404を表示します。
                try_files $uri $uri/ =404;
        }

        # PHPスクリプトをFastCGIサーバーに渡す
        #
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # php-fpm(または他のunixソケット)を使用する場合:
                # ここでphp7.2をインストール時に表示されたバージョンに変更する必要があります。
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
                # php-cgi(または他のtcpソケット)を使用する場合:
                # fastcgi_pass 127.0.0.1:9000;
        }

フォームがある html ファイルを変更する#

次に、フォームがある html ファイルを開き、form タグを変更します。例えば私のものは:

<!--実際にはこれだけ貼り付けたのはformタグにaction="mail.php"を追加する必要があると言いたかっただけです(滑稽)-->
<form method="post" action="mail.php">
    <div class="fields">
        <div class="field half">
            <label for="name">名前</label>
            <input type="text" name="name" id="name" />
        </div>
        <div class="field half">
            <label for="email">メール</label>
            <input type="text" name="email" id="email" />
        </div>
        <div class="field">
            <label for="message">メッセージ</label>
            <textarea name="message" id="message" rows="6"></textarea>
        </div>
    </div>
    <ul class="actions">
        <li><input type="submit" value="メッセージを送信" class="primary" /></li>
        <li><input type="reset" value="クリア" /></li>
    </ul>
</form>

mail.php ファイルを設定する#

form の送信は mail.php ファイルを呼び出します。次に、それを設定する必要があります。私は多くのウェブサイトを見て、ネット上には大体 2 つのテンプレートしかないことに気づきました。つまりこれこれです。しかし、実際に体験してみると、どちらも!使えません!最初のものは単純に設定ファイルの問題で、各項目を修正してもまだ使えませんでした。(もしかしたら、私がいくつかのものを削除しすぎたからかもしれません?)2 つ目は php の mail () 関数を使用していますが、残念ながら、この最後に私の問題を解決した記事に書かれているように:

PHP 環境では、メールを送信する関数mail()が提供されていますが、この関数はサーバーが sendmail をサポートするか、リレーを必要としないメール送信サーバーを設定する必要があります。しかし、現在、認証なしでメール送信のリレーを見つけるのはほぼ不可能なので、mail 関数を使用すると、しばしば電子メールを正常に送信できません。

mail () 関数は確かに正常にメールを送信できません。この文章も解決策を提供しており、それはPHPMailerを使用することです。

それをサーバーにgit cloneして解凍し、mail.php は README.md に記載されている Example に従ってわずかに修正すれば大丈夫です。私のものは次のようになります。

<?php
// PHPMailerクラスをグローバル名前空間にインポートします
// これらはスクリプトの先頭に配置する必要があります。関数内ではありません。
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

// これらの3つのファイルのパスをサーバーパスに変更します。
require './PHPMailer/src/Exception.php';
require './PHPMailer/src/PHPMailer.php';
require './PHPMailer/src/SMTP.php';

// ここで内容をformタグの各項目の名前に対応させます。
$email=$_POST['email'];
$name=$_POST['name'];
$message=$_POST['message'];

// インスタンス化し、`true`を渡すことで例外を有効にします。
$mail = new PHPMailer(true);

// ここではqqメールを使用しています。他のメールも同様です。
try {
    //サーバー設定
    $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      // 詳細なデバッグ出力を有効にします。
    $mail->isSMTP();                                            // SMTPを使用して送信します。
    $mail->Host       = 'smtp.qq.com';                    // 送信に使用するSMTPサーバーを設定します。
    $mail->SMTPAuth   = true;                                   // SMTP認証を有効にします。
    $mail->Username   = 'メールのユーザー名';                     // SMTPユーザー名
    $mail->Password   = 'メールのパスワード';                               // SMTPパスワード
//    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;         // TLS暗号化を有効にします。`PHPMailer::ENCRYPTION_SMTPS`も受け入れられます。
    $mail->SMTPSecure = 'ssl';
    $mail->Port       = 465;                                    // 接続するTCPポート

    //受信者
    $mail->setFrom('メールのユーザー名', '適当なニックネーム');
    $mail->addAddress('送信先のメール', '適当なニックネーム');     // 受信者を追加します。
    
//	後ろのものは使わないので、コメントアウトしました。
//    $mail->addAddress('ellen@example.com');               // 名前はオプションです。
//    $mail->addReplyTo('info@example.com', '情報');
//    $mail->addCC('cc@example.com');
//    $mail->addBCC('bcc@example.com');

    // 添付ファイル
//    $mail->addAttachment('/var/tmp/file.tar.gz');         // 添付ファイルを追加します。
//    $mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // オプションの名前

    // コンテンツ
    $mail->isHTML(true);                                  // メール形式をHTMLに設定します。
    $mail->Subject = "An E-mail from $email";
    $mail->Body = "このメールは$nameによって書かれました: $message";
    
    // テスト中、AltBodyの内容はメールに表示されませんでした。現在、何のためにあるのかは不明です。
    $mail->AltBody = "";

    $mail->send();
    echo 'メッセージが送信されました';
} catch (Exception $e) {
    echo "メッセージを送信できませんでした。Mailer Error: {$mail->ErrorInfo}";
}

送信後にリダイレクトしない方法#

以上の設定を行った後、フォームは正常にメールを送信できるはずですが、唯一の欠点は、送信ボタンをクリックするとリダイレクトされ、一連のメッセージが表示され、見栄えが悪くなることです。この記事では、formタグに target 属性を追加し、iframeタグを追加する方法が示されています。私のフォームの例では、form タグを次のように変更する必要があります。

<form method="post" action="mail.php" target="id_iframe">

その後に追加します:

<iframe id="id_iframe" name="id_iframe" style=""></iframe>

このように変更すると有効ですが、送信ボタンをクリックすると簡素なフレームが表示され、その中に以前のリダイレクト後のメッセージが表示されます。これでは目的を達成できないため、iframe タグを隠すことを考えました。つまり、高さと幅を 0 に設定します:

<iframe id="id_iframe" name="id_iframe" style="" width="0" height="0"></iframe>

しかし、こうするともう一つの問題が発生します。ボタンをクリックした後、メールが正常に送信されたかどうかは不明です。どうすればいいのでしょうか?私は、元の php ファイルの 2 つの出力メッセージのechoecho "<script>alert('内容')</script>"に変更することを考えました。つまり:

echo 'メッセージが送信されました';
// 置き換え
echo "<script>alert('メッセージが送信されました')</script>";

echo "メッセージを送信できませんでした。Mailer Error: {$mail->ErrorInfo}";
// 置き換え
echo "<script>alert('メッセージを送信できませんでした。')</script>";

こうすれば、リダイレクトせずにウェブページのポップアップでメール送信結果を表示できるようになります。

結論#

全体的に見て、上記の実装方法は正常に機能しますが、改善の余地が大いにあります。例えば、リダイレクトしない実装方法など。しかし、結局のところ、私はウェブに関する知識を体系的に学んだことがないので、どうにかこうにかやっているだけです。いつか時間ができたら改善を考えたいと思います(笑)。皆さんもコメントでアドバイスをいただければ嬉しいです!(ところで、この文章を本当に誰かが読んでいるのでしょうか?!)

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。