Skip to content

Instantly share code, notes, and snippets.

@idzan
Last active May 18, 2021 14:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save idzan/af5645ac9d85a803a9168af17d53843d to your computer and use it in GitHub Desktop.
Save idzan/af5645ac9d85a803a9168af17d53843d to your computer and use it in GitHub Desktop.
Boostrap 4 Contact form with AJAX, PHP, ReCaptcha v2 and PHPMailer for SMTP
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\OAuth;
use League\OAuth2\Client\Provider\Google;
require 'vendor/autoload.php';
require 'vendor/google/recaptcha/src/autoload.php';
$fromEmail = 'marko@idzan.eu'; //Email for From field
$fromName = 'Marko Idzan'; //Name in From
$sendToEmail = 'marko@idzan.eu'; //Send CF data to this mail
$sendToName = 'Idzan Web Site'; //CF data name
$subject = 'New message from contact form';
$fields = array('name' => 'Name', 'email' => 'Email', 'message' => 'Message');
$okMessage = 'Contact form successfully submitted. Thank you, I will get back to you soon!';
$errorMessage = 'There was an error while submitting the form. Please try again later';
$recaptchaSecret = '***secret***';
error_reporting(E_ALL);
try {
if (!empty($_POST)) {
if (!isset($_POST['g-recaptcha-response'])) {
throw new \Exception('ReCaptcha is not set.');
}
$recaptcha = new \ReCaptcha\ReCaptcha($recaptchaSecret, new \ReCaptcha\RequestMethod\CurlPost());
$response = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
if (!$response->isSuccess()) {
throw new \Exception('ReCaptcha was not validated.');
}
$emailTextHtml = "<h1>You have a new message from your contact form</h1><hr>";
$emailTextHtml .= "<table>";
foreach ($_POST as $key => $value) {
if (isset($fields[$key])) {
$emailTextHtml .= "<tr><th>$fields[$key]</th><td>$value</td></tr>";
}
}
$emailTextHtml .= "</table><hr>";
$mail = new PHPMailer;
$mail->setFrom($fromEmail, $fromName);
$mail->addAddress($sendToEmail, $sendToName);
$mail->addReplyTo($from);
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $emailTextHtml;
$mail->msgHTML($emailTextHtml);
$mail->isSMTP();
$mail->SMTPDebug = 0;
$mail->Debugoutput = 'html';
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
$mail->SMTPAuth = true;
$mail->AuthType = 'XOAUTH2';
$email = 'marko@idzan.eu'; //Email which get validation, learn more at PHPMailer
$clientId = 'myclientId';
$clientSecret = 'myclientSecret';
$refreshToken = 'refreshToken';
$provider = new Google(
[
'clientId' => $clientId,
'clientSecret' => $clientSecret,
]
);
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'refreshToken' => $refreshToken,
'userName' => $email,
]
)
);
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
if (!$mail->send()) {
throw new \Exception('I could not send the email.' . $mail->ErrorInfo);
}
$responseArray = array('type' => 'success', 'message' => $okMessage);
}
} catch (\Exception $e) {
// $responseArray = array('type' => 'danger', 'message' => $errorMessage);
$responseArray = array('type' => 'danger', 'message' => $e->getMessage());
}
// if requested by AJAX request return JSON response
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$encoded = json_encode($responseArray);
header('Content-Type: application/json');
echo $encoded;
}
// else just display the message
else {
echo $responseArray['message'];
}
$(function () {
window.verifyRecaptchaCallback = function (response) {
$('input[data-recaptcha]').val(response).trigger('change')
}
window.expiredRecaptchaCallback = function () {
$('input[data-recaptcha]').val("").trigger('change')
}
$('#contact').on('submit', function (e) {
if (!e.isDefaultPrevented()) {
var url = "contact-validator.php";
$.ajax({
type: "POST",
url: url,
data: $(this).serialize(),
success: function (data) {
var messageAlert = 'alert-' + data.type;
var messageText = data.message;
var alertBox = '<div class="alert ' + messageAlert + ' alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + messageText + '</div>';
if (messageAlert && messageText) {
$('#contact').find('.messages').html(alertBox);
$('#contact')[0].reset();
grecaptcha.reset();
}
}
});
return false;
}
})
});
<form id="contact" method="post" role="form" novalidate="true">
<div class="messages"></div>
<div class="controls">
<div class="row">
<div class="col-md-12">
<div class="form-label-group">
<input id="form_name" type="text" name="name" class="form-control" placeholder="Please enter your name" required autofocus data-error="Name is required.">
<label for="form_name">Your name</label>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-label-group">
<input id="form_email" type="email" name="email" class="form-control" placeholder="Please enter your email" required autofocus data-error="Valid email is required.">
<label for="form_email">Email *</label>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-label-group">
<textarea id="form_message" name="message" class="form-control" placeholder="Enter your message" rows="4" required autofocus data-error="Please, leave us a message."></textarea>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="g-recaptcha" data-sitekey="***sitekey***" data-callback="verifyRecaptchaCallback" data-expired-callback="expiredRecaptchaCallback"></div>
<input class="form-control d-none" data-recaptcha="true" required data-error="Please complete the Captcha">
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="gdprCheck" required>
<label class="form-check-label" for="gdprCheck">
I accept <a href="terms-of-service.html">terms of service</a> and privacy policy of using this contact form.
</label>
</div>
</div>
<div class="row">
<div class="col-md-12">
<input type="submit" class="btn btn-success btn-send" value="Send message">
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><strong>*</strong> These fields are required.</p>
</div>
</div>
</div>
</form>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment