Javascript 获取 API 和 PHPMailer 响应缓慢

Javascript fetch API and PHPMailer slow response

当客户订购产品时,他们会向服务器端发送一个表单。我验证 php 中的表格,如果没有错误,我会发送电子邮件给客户,并给自己发送一封电子邮件,其中包含从表格中收到的产品信息。我使用 PHPMailer 发送电子邮件,但它相当慢,发送邮件和从服务器返回响应到 javascript 大约需要 5 秒。当我取出发送电子邮件的代码时,回复立即到达。 PHP邮件程序会减慢响应速度,但我不知道为什么。

Javascript:

 const form = document.querySelector("#form");
      form.addEventListener("submit", (e) => {
        e.preventDefault();
        const formData = new FormData(form);
        fetch("index.php", {
          method: 'post',
          body: formData
        }).then((resp) => resp.json())
        .then(function (text) {
          console.log(text); //Do something with the response, which is an array
          if(text !== undefined && text.length > 0) { //The array isn't empty
            //Show errors
            const formdiverror = document.querySelector(".col-100-form-error");
            const colform = document.querySelector(".col-100-form");
            colform.style.display = "block";
            formdiverror.innerHTML = "";
            text.forEach(t => formdiverror.innerHTML += t + "</br>");
          } else {
            //array is empty, no errors
             const colform = document.querySelector(".col-100-form");
             if(colform !== null || colform !== undefined) colform.style.display = "none";
             alert("Success!");
             window.location.replace("index.html"); //if there was no error redirect to index.html
          }
        });
      })

PHP:

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
require 'Exception.php';
require 'PHPMailer.php';
require 'SMTP.php';

$errors = [];

if(isset($_POST["name"]) && isset($_POST["address"]) && isset($_POST["email"]))  {
    $name = $_POST["name"];
    $address = $_POST["address"];
    $email = $_POST["email"];

    //I skipped the validation for shorter code
    if(empty($name)) {
        $errors[] = "Name cannot be empty!";
    }

    if(empty($address)) {
        $errors[] = "Address cannot be empty!";
    }


    if (!empty($errors)) {
        echo json_encode($errors); //Sending back the array of string errors
    } else {
        $mail = new PHPMailer();
        $mail->CharSet = "UTF-8";
        $contentBody = '<html><body><div  style="text-align:center; width: 500px; display:block; margin-left: auto; 
        margin-right: auto;"><p style="text-align:center;"><h2>' . $name . ' ' . $address . '</div></body></html>';

        //Sending to client
        $mail->setFrom("mymail@gmail.com", "MyName"); //Who is sending the message
        $mail->addAddress($email); //Set who the message is to be sent to
        $mail->AddReplyTo("mymail@gmail.com", "MyName");
        $mail->Subject = 'Order';
        $mail->isHTML(TRUE);
        $mail->Body = $contentBody;
        $mail->isSMTP();
        $mail->Host = 'smtp.gmail.com';
        $mail->SMTPAuth = TRUE;
        $mail->SMTPSecure = 'tls';
        $mail->Username = "mymail@gmail.com";
        $mail->Password = 'mypassword';
        $mail->Port = 587;
        if(!$mail->Send())
        {
            echo "Something went wrong!";
        }
        $mail2 = new PHPMailer();
        $mail2->CharSet = "UTF-8";
        //Sending to myself
        $contentBodyForFirm = '<html><body><div  style="text-align:center; width: 500px; display:block; margin-left: auto; 
        margin-right: auto;"><p style="text-align:center;"><h2>' . $name . ' ' . $address . '</div></body></html>';

        $mail2->setFrom($email, $name); //Who is sending the message
        $mail2->addAddress("mymail@gmail.com"); //Set who the message is to be sent to
        $mail2->Subject = 'Order';
        $mail2->isHTML(TRUE);
        $mail2->Body = $contentBodyForFirm;
        $mail2->isSMTP();
        $mail2->charSet = "UTF-8";
        $mail2->Host = 'smtp.gmail.com';
        $mail2->SMTPAuth = TRUE;
        $mail2->SMTPSecure = 'tls';
        $mail2->Username = "mymail@gmail.com";
        $mail2->Password = 'mypassword';
        $mail2->Port = 587;
        if(!$mail2->Send())
        {
            echo "Something went wrong!";
        }
        echo json_encode([]); //Sendning back an empty array

    }
}

?>

如果验证中出现错误,我会使用 echo json_encode($errors); 发回错误并在客户端显示。如果没有错误,我使用 echo json_encode([]);。在 javascript 中,我检查了获取响应。如果它是一个空数组,则没有错误,我可以重定向到 index.html.

这很可能是因为 SMTP 通常很慢(有时是故意如此),尤其是在与远程服务器通信时。在 page/request 处理期间发送根本不适合 SMTP,尽管这并不能阻止很多人这样做。

使其更快的最佳方法是通过本地邮件服务器进行中继。这样就没有网络开销,响应时间也会非常快——每秒发送数百条消息应该没有问题。它还会为您处理排队、节流、重试等问题。

PHPMailer wiki 有 notes on how to send to lists efficiently, which also mostly apply whenever you're sending > 1 message. Take a look at the list sending example,它体现了这个建议。在您的情况下,您正在创建 PHPMailer 的第二个实例来发送第二条消息。您最好 re-using 为第二条消息使用相同的实例并使用 keepalive,这会大大减少连接开销。