thx1138
thx1138

Reputation: 110

PHPmailer and vanilla JavaScript AJAX form prompt

So, I needed a contact form that can send emails with a "success" prompt that appears in my form, WITHOUT reloading. I have found PHPmailer that helps with sending mail to the inbox and not spam (this alone works fine, email sent straight to inbox). I then add the JS validation then AJAX, then the PHP that deals with the JSON response.

The "success" prompt appears when I click "send" (good!) but the problem is that no email has been sent/received. The code without the AJAX works fine on both my local and web hosts perfectly. How do I optimize this so the success prompt appears and the email is sent (inbox, ideally)?

No jQuery or any extra plugins please.

Thanks in advance.

HTML:

<div class="contact-form">
    <form action="mail.php" method="POST" onsubmit="return doRegister()">
        <input id="mail-name" type="text" name="name" placeholder="Your Name">
        <span id="name-alert"></span>
        <input id="mail-email" type="text" name="email" placeholder="Your Email">
        <span id="email-alert"></span>
        <input id="mail-subject" type="text" name="subject" placeholder="Your Subject">
        <span id="subject-alert"></span>
        <textarea id="mail-message" name="message" placeholder="Your Message"></textarea>
        <span id="message-alert"></span>
        <input type="submit" value="Send">
        <input type="reset" value="Clear">
        <span class="contact__form--alert-success" id="success-alert"></span>
    </form>
</div>

JS:

function doRegister() {
  let checks = {
    name : document.getElementById("mail-name"),
    email : document.getElementById("mail-email"),
    subject : document.getElementById("mail-subject"),
    message : document.getElementById("mail-message")
  },
error = "";
  if (checks.name.value=="") {
    error += document.getElementById("name-alert").innerHTML+='<p>A name is required!</p>';
  }
  if (checks.subject.value=="") {
    error += document.getElementById("subject-alert").innerHTML+='<p>A subject is required!</p>';
  }
  if (checks.message.value=="") {
    error += document.getElementById("message-alert").innerHTML+='<p>A message is required!</p>';
  }
  let pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  if (!pattern.test(checks.email.value.toLowerCase())) {
    error += document.getElementById("email-alert").innerHTML+='<p>A valid email is required!</p>';
  }

// Ajax
if (error!="") {
    error="";
} else {
let data = new FormData();
for (let k in checks) {
  data.append(k, checks[k].value);
}
let xhr = new XMLHttpRequest();
xhr.open('POST', "mail.php", true);
xhr.onload = function(){
        let res = JSON.parse(this.response);
        // SUCCESS!
  if (res.status) {
            document.getElementById("success-alert").innerHTML+='<p>Success!</p>';
  } else {
    // ERROR!
    error = "";
    for (let e of res['error']) {
      error += e + "\n";
    }
    alert(error);
  }
};
// SEND
xhr.send(data);
 }
 return false;
}

PHP:

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
$error = [];
$msg = '';
if ( array_key_exists( 'email', $_POST ) ) {
  date_default_timezone_set( 'Etc/UTC' );
  require 'mail/vendor/autoload.php';
  // Call super globals from the contact form names
  $email                        = $_POST['email'];
  $name                         = $_POST['name'];
  $subject          = $_POST['subject'];
  $message          = $_POST['message'];
  $mail             = new PHPMailer;
  $mail->isSMTP();
  $mail->Host       = 'mail.host.com';
  $mail->SMTPAuth   = true;
  $mail->Username   = '[email protected]';
  $mail->Password   = 'password1';
  $mail->SMTPSecure = 'ssl';
  $mail->Port       = 465;
  $mail->setFrom( '[email protected]', 'New Message' );
  $mail->addAddress( '[email protected]' );
  if ($mail->addReplyTo($email, $name)) {
    $mail->Subject = $subject;
    $mail->isHTML(false);
    $mail->Body = <<<EOT
Email: {$email}
Name: {$name}
Message: {$message}
EOT;
  }

// Check inputs
if ($name=="") {
    $error[] = "A name is required.";
}
if ($subject=="") {
    $error[] = "A subject is required.";
}
if ($message=="") {
    $error[] = "A message is required.";
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $error[] = "A valid email is required.";
}

// JSON encode with a response
echo json_encode([
"status" => count($error)==0 ? 1 : 0,
"error" => $error
]);
 }

Solution: the "send()" function was missing

if(empty($error)){
  if(!$mail->send()){
    $error[] = 'There was an error sending the mail. Please try again!';
  }
}

Upvotes: 1

Views: 1465

Answers (1)

SessionCookieMonster
SessionCookieMonster

Reputation: 166

Your PHP script doesn't send the mail because the send() function is not called, so after the validation, you should add something like:

if(empty($error)){
    if(!$mail->send()){
        $error[] = 'There was an error sending the mail. Please try again!';
    }
}

echo json_encode([
"status" => count($error)==0 ? 1 : 0,
"error" => $error
]);

This way you're sending the mail and, if there was a problem(send() returns false), an error is being added to your error array.

Upvotes: 2

Related Questions