【问题标题】:phpmailer failing for certain devices某些设备的phpmailer失败
【发布时间】:2021-01-22 22:12:20
【问题描述】:

您好,我有一个相当大的 PhpMailer 脚本,它可以上传 9 个文件并通过电子邮件发送 HTML 申请表。

它通过一个非常标准的 AJAX 脚本发送。我已经在各种设备和平台上对其进行了测试,一切正常。事实上,无论我试图做什么,我都无法打破它,但我客户的租户似乎已经找到了一种方法来打破它。

他们说他们已经使用了它,并且就他们而言,它已成功发送,但是没有发送或接收电子邮件或上传到服务器的任何文件的记录。

这里是完整的脚本,减去了一些表单字段以及连接到数据库以进行垃圾邮件检查的详细信息。

if ( isset($_POST['email']) && isset($_POST['name']) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) ) {

    // detect & prevent header injections
    $test = "/(content-type|bcc:|cc:|to:)/i";
    foreach ( $_POST as $key => $val ) {
        if ( preg_match( $test, $val ) ) {
            exit;
        }
    }


    $dateKey = date( 'd-m-Y--H-i-s' );




    $my_email = "control@XXXXXXXXXXXX.com";
    ob_start();

    require("smtp/class.phpmailer.php");

    $mail = new PHPMailer();



    $mail->IsSMTP();
    $mail->Host = "mail.XXXXXXXX.com";
    $mail->SMTPAuth = true;
    $mail->Username = $my_email;
    $mail->Password = "XXXXXXXXXXX";



    $mail->From = $mail->Username;

    $mail->FromName = $_POST['name'];
    $mail->Sender = $_POST['email'];



    function clean($string) {
        $string = str_replace(' ', '-', $string);

        return preg_replace('/[^A-Za-z0-9\-]/', '', $string);
    }

    if(isset($_FILES)) {

        $uploadOk = 1;
        $fileString = '';

        $fileMessage = 'FILEERROR(';

        $files = $_FILES;

        $target_dir = $_SERVER['DOCUMENT_ROOT'] . "/XXXXXXXXXX/uploads/";



        foreach ( $_FILES as $key => $file ) {

            $imageFileExt = strtolower( pathinfo( $file["name"], PATHINFO_EXTENSION ) );

            $file['name'] = clean($_POST['name']). "_" . $key . "_" . $dateKey . "." . $imageFileExt;


            $target_file = $target_dir . basename($file["name"]);
            $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));



            $check = getimagesize($file["tmp_name"]);
            if($check === false) {
                $fileMessage .=  $key."=noimage,";
                $uploadOk = 0;
            }

// Allow certain file formats

            else if($imageFileType !== "jpg" && $imageFileType !== "png" && $imageFileType !== "jpeg"
                    && $imageFileType !== "gif" ) {
                $fileMessage .=  $key."=wrongfile,";
                $uploadOk = 0;
            }

// Check if file already exists
            else if (file_exists($target_file)) {
                $fileMessage .=  $key."=fileexists,";
                $uploadOk = 0;
            }


// Check file size
            else if ($file["size"] > 20000000) { //20mb
                $fileMessage .=  $key."=toobig,";
                $uploadOk = 0;
            }

            $fileString .= strtoupper($key).": <a href='http://www.XXXXXXXXXXXX.com/XXXXXXXXX/uploads/".$file['name']."'>".$file['name']."</a><br>";


        }

        $fileMessage .= ')';



    }





    $mail->CharSet = 'utf-8';
    $mail->Encoding = 'quoted-printable';



    $bcc = "xxx@xxxxx.com";
    $mail->AddBCC($bcc);

    $mail->AddReplyTo($_POST['email']);


    $mail->WordWrap = 50;



    $mail->Body     = "<p><strong>APPLICATION<br /></strong></p>

<p>Property ".$_POST['address']."<br />

<div style='background:#f1f1f1;padding:5px 15px; margin-bottom:20px;'><p><strong>APPLICANT DETAILS:<br /></strong></p><p>
Name: ".$_POST['name']."<br />

Email: ".$_POST['email']."<br />

Telephone: ".$_POST['tel']."<br />

Date of birth: ".$_POST['DOB']."<br />

National insurance number: ".$_POST['NI']."<br /></p></div>

<div style='background:#f1f1f1;padding:5px 15px; margin-bottom:20px;'><p><strong>ADDRESS<br /></strong></p><p>

Address: ".$_POST['address']."<br />
Time at address: ".$_POST['addLength']."<br />
Reason to move: ".$_POST['move']."<br />";


    ///more fields added to body here but not necessary to show



    $mail->Body.="<div style='background:#f1f1f1;padding:5px 15px; margin-bottom:20px;'><p><strong>FILE ATTACHMENTS:<br /></strong></p><p>".$fileString."</p></div>";



    $mail->IsHTML(true);

    $mail->Subject = 'Application';



    /* my own validation */
    $formerrors = array();
    $errorstring = "";


    ///connects to database here, details removed but checks against spam keywords and creates an array of $formerrors





    $conn->close();



    if (sizeof($formerrors) > 0){

        $errorstring = "(" ;

        foreach($formerrors as $key=>$value){

            if($y < sizeof($formerrors) ){


                $errorstring .= $value.",";
                $y++;

            } else{

                $errorstring .= $value.")";

            }


        }

        echo $errorstring;


        #### file errors ####

    } else if($uploadOk === 0){

        echo $fileMessage;

    }
    else {


            $mail->AddAddress("XXX@XXXXX.com", 'recipient');

        ///send here
        if ($mail->Send() == true) {

            if ($uploadOk === 1) {

                if(isset($_FILES)) {


                    $uploadfiles = $_FILES;


                    // Compress image
                    function compressImage($source, $destination, $quality) {

                        $info = getimagesize($source);

                        if ($info['mime'] == 'image/jpeg') {
                            $image = imagecreatefromjpeg($source);
                        } elseif ($info['mime'] == 'image/gif') {
                            $image = imagecreatefromgif($source);
                        } elseif ($info['mime'] == 'image/png') {
                            $image = imagecreatefrompng($source);
                        }

                        imagejpeg($image, $destination, $quality);

                    }

                    foreach ( $uploadfiles as $key => $upfile ) {


                        $imageFileType = strtolower( pathinfo( $upfile['name'], PATHINFO_EXTENSION ) );




                        $fileName = clean($_POST['name']). "_" . $key . "_" . $dateKey . "." . $imageFileType;


                        $target_file = $target_dir . basename( $fileName );


                        $img_dir = "img/";

                        compressImage($upfile["tmp_name"], $target_dir . basename( $fileName ), 60);


                    }
                }
            }

            echo 'Message sent successfully';




        }
        else {
            echo "failed";

        }



    }


}

【问题讨论】:

  • 这看起来你可能没有关注PHP docs on handling uploads safely。看看the PHPMailer "send file upload" example。这是您之前提出的问题的延伸——分解您的问题并一次解决一个问题;你试图一次完成整个事情,但你需要先检查每个部分是否单独工作。添加更多日志记录!
  • 对不起,我不明白哪个位不安全?我最初确实使用了 move_uploaded_file() 但发现我需要将它与 compressImage() 交换,以便我可以存储压缩图像。是这样还是因为我正在发送电子邮件然后在您的示例脚本以相反方式执行时存储文件?
  • 我已经编辑了帖子以显示完整的 phpmailer 脚本。
  • 感谢 Martin,问题是当我将其设置为 tmp_name 时,我的脚本将其标记为错误的文件类型。
  • 在您的原始问题中,您没有显示您对move_uploaded_file 的使用,只是您直接访问$_FILES,因此我怀疑。您需要在使用它包含的 anything 之前验证$_FILES - 所以我看不出在安全处理上传的文件之前如何选择压缩图像:处理上传,然后压缩图像,而不是相反,而不是一个而不是另一个。发送电子邮件时是否不涉及图像文件是完全独立的决定。

标签: php ajax file-upload phpmailer


【解决方案1】:

您的代码中有一些经典错误。

问题不在于 PhpMailer。

这里总结了如何解决最明显的问题:

  • 确保您拥有most up to date 版本的 PhpMailer。

  • 您的 Phpmailer 上似乎没有任何错误检测...使用 PhpMailer Exceptions 找出 PhpMailer 中是否存在发送问题。

  • 使用 PhpMailer 广泛的内置错误日志记录以及 -&gt;debugOutoput-&gt;SMTPDebug 来检测电子邮件错误。

  • 打开您的 PHP 错误日志以跟踪错误、问题和通知,并定期检查您的错误日志。

  • 您需要使用PHP Error Logging!我复制并运行了您的脚本,并立即提出了您应该从一开始就发现的各种通知和问题。

  • 如果您的主机不是localhost,您可能需要检查并确认您使用的是正确的端口,例如使用$mail-&gt;Port = 587; 而不是$mail->Port = 25(我相信默认值)。

  • 如果您的发送域是同一服务器上的另一个域(因为它看起来像一个邮件子域),那么简单地使用“localhost”并避免整个身份验证工作量会容易得多。

  • 您似乎误解了PHP handled multiple file uploads 的含义,您似乎期待$_FILES[x]['name'],但实际上给您的是$_FILES['name'][x]。为此,您需要重新组织您的 $_FILES 代码。

  • 还有一个PHPMailer example for handling multiple uploads

  • 在您的pathinfo 调用中,您应该测试实际文件的tmp_name 的路径,而不是给定的原始名称。 这是一个严重的安全漏洞。

  • 建议清理$_POSTed 数据。你的$_POST['email']至少应该贯穿FILTER_SANITIZE_EMAIL

  • 开启 PHP 错误记录

  • 不要相信compressImage 中的机制可以检测到正确的图像类型。您应该在 源文件 上使用fileinfo,而不是简单地信任 $_FILES 数组中给定的 type 数据,因为卸载者可以很容易地对其进行操作。

  • 如果您完成了上述所有操作并且没有 PhpMailer 存在发送问题,那么请使用您的服务器日志检查电子邮件发送程序(sendmail 或类似程序)是否确实收到了发送来自 PHP 的请求以及它用它做了什么。

  • 您的服务器日志还将概述来自服务器端的发送问题(一旦 PHP 将数据传递给您的发送程序)。

  • 您必须记住,发送绝对不能保证送达,您应该运行第 3 方检查以确保您的服务器已正确设置以发送电子邮件,并包括基本的垃圾邮件标签避免技术,例如 SPFDKIMDMARC

  • 检查您的 PHP 错误日志

【讨论】:

  • @Synchro 非常好。我这里的要点比 M16 :-)
  • 感谢@Martin 提供一些非常详细的反馈。它看起来像是回到了绘图板上,前方有一条陡峭的曲线。我将从更新 phpMailer 开始,尽管我对 composer 和 git 一直没有信心。就错误日志而言,它们标记了许多使用 class.phpmailer.php 贬值的东西 - 当你说你运行我的代码时,这些问题是你提到的吗?我将了解 $_FILES 实际发生的情况。然后尝试其余的要点。
  • 也感谢@Synchro 的多次上传示例。
  • @cannon303 我不使用作曲家。只需从 github 下载当前的 master 并手动安装,同样可以使用 :-)。祝你好运。如果此答案解决了您的问题,请随时打勾并 +1 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-30
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
相关资源
最近更新 更多