PHP 表单不仅仅从移动设备发送信息


PHP form does not send informations only from mobile devices

请参阅下面的更新

我有这个非常简单的PHP联系表格,它在每个浏览器上都很好用。提交后,该过程将经过formaction.php,您在下面看到,然后验证验证码,发送信息并重定向到所选页面。

我的问题是,我上周意识到,在iPhone 4S,5S和三星SIII上测试的移动设备上使用时,该表单不会发送任何内容。

乍一看,我删除了$recipient变量,这是我对formaction.php所做的最后一次更新,并意识到问题不存在。

由于我是PHP的新手,我有这样的想法,也许某些移动设备可能无法识别头部变量,所以我删除了编写一些核心信息的$POST[blablabla]。这行不通。

我搜索了很多以找到移动和网络发送过程之间的差异,但问题仍然存在。

session_start();
if(isset($_POST["captcha"]) && 
   $_POST["captcha"]!="" && 
   $_SESSION["code"]==$_POST["captcha"])
{
    Header("Location: http://www.mysite.fake/thank" );
    $recipients = array('info' => 'info@mysite.fake', 
                        'ventes' => 'ventes@mysite.fake', 
                       'commandites' => 'commandites@mysite.fake'
                      );
    $to = $recipients[$_POST['sujet']];
    $head .= "From: ".$_POST['nom']." <".$_POST['courriel'].">'r'n";
    $head .= "X-Sender: <info@mysite.fake>'n";
    $head .= "X-Mailer: PHP'n";
    $head .= "Return-Path: <info@mysite.fake>'n";
    $head .= "Content-Type: text/plain; charset=utf-8'n";
    $sujet = "Subject | ".$_POST['nom']." contacted you for ".$_POST['sujet'].".";
    $informations = "
    Hi, you received a new demand. 'r'n
    Name: ".$_POST['nom']." 'r'n
    Mail: ".$_POST['courriel']." 'r'n
    Subject: ".$_POST['sujet']."'r'n
    Message: ".$_POST['texte']." 'r'n";
    mail($to, $sujet ,$informations, $head); 
} else {
    Header("Location: http://www.mysite.fake/error" );
}

更新:与@RiggsFolly交谈后,我验证了Apache日志,请求确实正常到达服务器。所以,一切都在后端工作。有什么想法吗?

[10/Jan/2015:19:58:45 -0700] "GET /fr/contact HTTP/1.1" 200 3997 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"
[10/Jan/2015:19:58:45 -0700] "GET /fr/captcha/captcha.php HTTP/1.1" 200 588 "http://eragraff.com/fr/contact" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"
[10/Jan/2015:19:59:19 -0700] "POST /fr/formaction.php HTTP/1.1" 302 547 "http://eragraff.com/fr/contact" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"
[10/Jan/2015:19:59:22 -0700] "GET /fr/formthank HTTP/1.1" 301 522 "http://eragraff.com/fr/contact" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"
[10/Jan/2015:19:59:23 -0700] "GET /fr/formthank HTTP/1.1" 200 682 "http://eragraff.com/fr/contact" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"
[10/Jan/2015:19:59:26 -0700] "GET /fr/contact HTTP/1.1" 200 3997 "http://eragraff.com/fr/formthank" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"
[10/Jan/2015:19:59:26 -0700] "GET /fr/captcha/captcha.php HTTP/1.1" 200 609 "http://eragraff.com/fr/contact" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"

Chrome 桌面日志

184.xxx.xx.xx - - [10/Jan/2015:20:39:15 -0700] "POST /formaction.php HTTP/1.1" 302 430 "http://mysite.fake/contact" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"

野生动物园移动日志

207.xx.xx.xxx - - [10/Jan/2015:20:28:29 -0700] "POST /formaction.php HTTP/1.1" 302 482 "http://mysite.fake/contact" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B440 Safari/600.1.4"

请求日志,通过*查尔斯代理验证

这是请求;

POST /formaction.php HTTP/1.1
Host: mysite.fake
Content-Length: 141
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,image/webp
Content-Type: application/x-www-form-urlencoded
Origin: http://mysite.fake
Referer: http://mysite.fake/contact
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_1_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/39.0.2171.50 Mobile/12B440 Safari/600.1.4
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: __utma=113777771.1205974649.1111957503.1428078344.1426693544.35; __utmz=113777771.1111957503.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=113777771; PHPSESSID=brmpaudvr2rxxxxxxxxna0000; __utmb=113777771.3.10.1421093598

这是服务器响应;

HTTP/1.1 302 Moved Temporarily
Date: Mon, 12 Jan 2015 20:34:40 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Location: http://mysite.fake/formthank
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html

您的问题实际上是由巧合引起的,与您提交表单的设备无关。问题在于您的代码将发件人地址设置为用户在表单中提交的任何电子邮件,而您的邮件服务器拒绝该地址,因为发件人地址显然与您的脚本用于登录 SMTP 服务器的凭据不匹配。

与其将发件人

的地址欺骗到客户输入的地址,不如使用您的服务器将接受的发件人地址,例如contactform@yourdomain,并将Reply-To标头设置为客户的电子邮件,因此您仍然保留欺骗发件人地址的所有优势(我假设这是为了能够通过单击邮件客户端中的"回复"直接回复客户),同时让服务器满意,因为您没有欺骗任何东西。下面是一个例子:

$mail->From = "contactform@yourdomain"; // no sender spoofing so server is happy
$mail->addReplyTo("customer's email", "customer's name"); // reply button works
此外,您

当前的代码存在一些问题,没有对数据进行验证(我可以提交空值,您的脚本仍将尝试发送邮件),没有错误检查(您甚至在尝试发送邮件之前立即将用户重定向到成功页面)和电子邮件标头注入(攻击者可以使用您的服务器向任何地址发送垃圾邮件)。

首先,我建议您使用 PHPMailer 而不是 mail(),它更容易使用,您不必手动构建标头字符串,并且可以安全地防止电子邮件注入。

这是我想出的一个基本脚本,它绝对不是我写过的最漂亮的代码,但它在验证值方面做得足够好,如果出现问题,它会抛出有意义的错误:

session_start();
// iterate over all expected values and exit if any are missing or empty
foreach (["captcha", "sujet", "nom", "courriel", "texte"] as $value) {
    if (!isset($_POST[$value]) || empty($_POST[$value])) {
        die("Missing or empty value ".$value);
    }
}
// recipient array, used both for validation and mail sending
$recipients = ["info" => "info@...", "ventes" => "ventes@...", "commandites" => "..."];
// exit if the recipient's identified isn't valid
if (!in_array($_POST["sujet"], array_keys($recipients))) {
    die("Incorrect recipient");
}
// exit if the sender's email address isn't valid
if (!filter_var($_POST["courriel"], FILTER_VALIDATE_EMAIL)) {
    die("Incorrect sender email");
}
// check if the captcha's code was set previously
if (!isset($_SESSION["code"])) {
    // if not, ask the user to go back and see the captcha
    die("Missing code, go back and request the captcha image again");
} elseif ($_SESSION["code"] != $_POST["captcha"]) {
    // otherwise, check if the captcha is correct and exit if not
    die("Incorrect captcha, please try again");
}
// new mailer object
$mail = new PHPMailer;
// configure your SMTP server's details
$mail->isSMTP();
$mail->Host = "smtp.example.com";
$mail->Port = 25; // 587 for tls (STARTTLS), 465 for ssl
// if your server requires auth
$mail->SMTPAuth = true;
$mail->Username = "user@example.com";
$mail->Password = "secret";
$mail->SMTPSecure = "tls";
// here we make the actual email
$mail->From = "contactform@yourdomain";
$mail->FromName = $_POST["nom"];
$mail->addAddress($recipients[$_POST["sujet"]]);
$mail->addReplyTo($_POST["courriel"], $_POST["nom"]);
$mail->Subject = $_POST["sujet"];
$mail->Body = $_POST["texte"];
if ($mail->send()) {
    echo "Success !";
} else {
    echo "Something went wrong";
    echo "Error details :".$mail->ErrorInfo;
    // in production, hide the error details to not reveal potentially sensitive info
}

在对代码进行故障排除后,我意识到$head行实际上是问题所在。

特别是这个..

$head = "From: ".$_POST['nom']." <".$_POST['courriel'].">'n";

当我测试从mail行中删除$head后,我成功地通过移动设备发送邮件。所以我把每一行都一行一行地写了核心信息,它与第一行一起工作,From:,我写了一个核心电子邮件地址。

$head = "From: <info@mysite.fake>'n";
好吧,问题

解决了,另一个问题解决了。在From:中有变量非常酷,因为它加快了对用户的回复。

如果有人知道为什么$head中的这些$_POST没有被移动设备吸收,或者我如何更好地实施它们,我很乐意更多地了解发生了什么。