最近在html5up上淘了個首頁模板,模板底有一個表單,今天在修改模板的時候,朋友提起可以配置表單實現提交表單時自動發送郵件通知,於是就萌生了這個想法,結果沒想到一搞就是三四個小時(主要是因為網上的某些 “教程” 太坑人了!),所以記錄一下配置過程給後來人參考。
給伺服器安裝 php,php-fpm#
作者使用的是 ubuntu18.04,所以使用
sudo apt-get install php
sudo apt-get install php-fpm
web 伺服器添加 php 支持#
作者使用的是 nginx,為支持 php 需要修改一下配置文件,網上不少教程說要改nginx.conf
,但我發現我這裡的配置文件和他們的有很大差異,後來實測修改/etc/nginx/sites-available/default
有效。將文件與 php 有關部分修改為:
# Add index.php to the list if you are using 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 / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
# 這裡需要把php7.2修改為安裝php時顯示的版本
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
# With php-cgi (or other tcp sockets):
# 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 文件,接下來就需要配置它了。我瀏覽了許多網站,發現網上大體只有兩個模板,即這個和這個。但親身體驗後發現都!不!能!用!第一個是單純的配置文件問題,我把各項修改好後還是不能用。(或許是因為我多刪了點東西?)第二個則使用了 php 的 mail () 函數,不過很不幸的是,正如這篇最後解決我問題的文章中寫的一樣:
PHP 環境下,是提供了發送郵件的函數
mail()
的,不過該函數要求伺服器支持 sendmail 或者必須設置一台不需要中繼的郵件發送伺服器,但現在要找到一台不需要身份驗證的郵件發送中繼幾乎不可能,所以使用 mail 函數往往無法成功發送電子郵件。
mail () 函數確實無法成功發送郵件。這篇文章同樣給出了一個解決辦法,就是使用PHPMailer。
將其git clone
到伺服器並解壓,mail.php 只需按照 README.md 中所給的 Example 進行微量修改,我的大概為:
<?php
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// 修改這三個文件的路徑為伺服器路徑
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'];
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
// 這裡我使用的是qq郵箱,其它郵箱同理
try {
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = 'smtp.qq.com'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = '郵箱的用戶名'; // SMTP username
$mail->Password = '郵箱的密碼'; // SMTP password
// $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
$mail->SMTPSecure = 'ssl';
$mail->Port = 465; // TCP port to connect to
//Recipients
$mail->setFrom('郵箱的用戶名', '隨便填個暱稱');
$mail->addAddress('發送到的郵箱', '隨便填個暱稱'); // Add a recipient
// 後邊的那些我不用,就註釋掉了
// $mail->addAddress('ellen@example.com'); // Name is optional
// $mail->addReplyTo('info@example.com', 'Information');
// $mail->addCC('cc@example.com');
// $mail->addBCC('bcc@example.com');
// Attachments
// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = "來自 $email 的郵件";
$mail->Body = "$name 寫的這封郵件 : $message";
// 我在測試時,AltBody中的內容並不會在郵件中顯示出來,目前暫時不清楚有什麼用
$mail->AltBody = "";
$mail->send();
echo '郵件已發送';
} catch (Exception $e) {
echo "郵件無法發送. 郵件發送錯誤: {$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 文件中的兩個用於輸出提示信息的echo
修改成echo "<script>alert('內容')</script>"
,也就是:
echo '郵件已發送';
// 替換為
echo "<script>alert('郵件已發送')</script>";
echo "郵件無法發送. 郵件發送錯誤: {$mail->ErrorInfo}";
// 替換為
echo "<script>alert('郵件無法發送.')</script>";
這樣的話就可以實現網頁彈窗提示郵件發送結果而不跳轉了。
結語#
總體來說,以上實現方式雖然可以正常使用,但是還有很大改進空間,比如提交不跳轉的實現方式。不過畢竟自己沒有系統學習過 web 方面的知識,也只能得過且過了。等什麼時候能閒下來再考慮改進吧(笑)。也歡迎大家在評論裡給我提建議吖!(話說這篇文章真的有人看嗎?!)