When a customer orders a product they send a form to the server side. I validate the form in php, and if there are no errors I send and e-mail to the customer and one e-mail to myself, containing the product informations which is received from the form. I use PHPMailer to send the e-mails, but it is rather slow, it takes like 5 seconds to send the mails and get back the response from the server to javascript. When I take out the code which sends the emails, the response arrives immediately. The PHPMailer slows the response, but I don' know why.
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
}
}
?>
If there are errors in the validation I use echo json_encode($errors);
to send back the errors and show them on the client side. If there are no errors I use echo json_encode([]);
. In javascript I check the fetch response. If it is an empty array there were no errors, and I can redirect to index.html.
This is mostly likely because SMTP is often slow (sometimes deliberately so), especially when talking to remote servers. Sending during page/request processing is not suited to SMTP at all, though that doesn't stop many people doing it.
The best way to make it much faster is to relay via a local mail server. This way there is no network overhead and response times will be very fast – you should have no problem sending hundreds of messages per second. It will also deal with queuing, throttling, retries, etc for you.
The PHPMailer wiki has 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, which embodies this advice. In your case you're creating a second instance of PHPMailer to send a second message. You're better off re-using the same instance for a second message and using keepalive, which reduces connection overhead considerably.