Reputation: 4221
We are using below code for my PhpMailer Contact Form. and, It is working fine normally. but, I'm still receiving spam even though I have recaptcha v3 enabled.
Screenshot of spam email:
Said this one of my friend:
bots send POST requests to /php/mail.php and the email get sent even if they the request doesn’t come from my domain and didn’t pass reCAPTCHA.
Can you please any help. Is there a mistake in the code below?
HTML Form Code:
<form id="contact-form" class="form-border" action="php/mail.php" method="post">
<div class="form-group mb-4">
<label for="name">What is Your Name:</label>
<input id="name" name="name" type="text" class="form-control py-1" required >
</div>
<div class="form-group mb-4">
<label for="email">Your Email Address:</label>
<input id="email" name="email" type="email" class="form-control py-1" required >
</div>
<div class="form-group mb-4">
<label for="form-message">How can I Help you?:</label>
<textarea id="form-message" name="form-message" class="form-control py-1" rows="4" required ></textarea>
</div>
<p>
<button id="submit-btn" class="btn btn-dark rounded-0 d-inline-flex" type="submit">Send <span class="ml-3"><i class="fas fa-arrow-right"></i></span></button>
</p>
</form>
Bottom of the HTML page:
<script id="google-recaptcha-v3" src="https://www.google.com/recaptcha/api.js?render=xxxxxxxxxxxxxxxxxxxxxx"></script>
JS Code:
var form = $('#contact-form'); // contact form
var submit = $('#submit-btn'); // submit button
// form submit event
form.on('submit', function (e) {
e.preventDefault(); // prevent default form submit
if (typeof $('#google-recaptcha-v3').val() != "undefined") {
grecaptcha.ready(function () {
var site_key = $('#google-recaptcha-v3').attr('src').split("render=")[1];
grecaptcha.execute(site_key, {action: 'contact'}).then(function (token) {
var gdata = form.serialize() + '&g-recaptcha-response=' + token;
$.ajax({
url: 'php/mail.php', // form action url
type: 'POST', // form submit method get/post
dataType: 'json', // request type html/json/xml
data: gdata, // serialize form data
beforeSend: function () {
submit.attr("disabled", "disabled");
var loadingText = '<span role="status" aria-hidden="true" class="spinner-border spinner-border-sm align-self-center mr-2"></span>Sending.....'; // change submit button text
if (submit.html() !== loadingText) {
submit.data('original-text', submit.html());
submit.html(loadingText);
}
},
success: function (data) {
submit.before(data.Message).fadeIn("slow"); // fade in response data
submit.html(submit.data('original-text'));// reset submit button text
submit.removeAttr("disabled", "disabled");
if (data.response == 'success') {
form.trigger('reset'); // reset form
}
setTimeout(function () {
$('.alert-dismissible').fadeOut('slow', function(){
$(this).remove();
});
}, 3000);
},
error: function (e) {
console.log(e)
}
});
});
});
} else {
$.ajax({
url: 'php/mail.php', // form action url
type: 'POST', // form submit method get/post
dataType: 'json', // request type html/json/xml
data: form.serialize(), // serialize form data
beforeSend: function () {
submit.attr("disabled", "disabled");
var loadingText = '<span role="status" aria-hidden="true" class="spinner-border spinner-border-sm align-self-center mr-2"></span>Sending.....'; // change submit button text
if (submit.html() !== loadingText) {
submit.data('original-text', submit.html());
submit.html(loadingText);
}
},
success: function (data) {
submit.before(data.Message).fadeIn("slow"); // fade in response data
submit.html(submit.data('original-text'));// reset submit button text
submit.removeAttr("disabled", "disabled");
if (data.response == 'success') {
form.trigger('reset'); // reset form
}
setTimeout(function () {
$('.alert-dismissible').fadeOut('slow', function(){
$(this).remove();
});
}, 3000);
if (typeof $('#recaptcha-v2').val() != "undefined") {
grecaptcha.reset(); // reset reCaptcha
}
},
error: function (e) {
console.log(e)
}
});
}
});
PHP Code: (mail.php)
<?php
/*--------------------------------------------------
Name: Contact Form
----------------------------------------------------*/
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require './phpmailer/src/Exception.php';
require './phpmailer/src/PHPMailer.php';
require './phpmailer/src/SMTP.php';
/* --------------------------------------------
// Receiver's Email
--------------------------------------------- */
$toEmail = "[email protected]"; // Replace Your Email Address
/* --------------------------------------------
// Sender's Email
--------------------------------------------- */
$fromEmail = "[email protected]"; // Replace Company's Email Address (preferably currently used Domain Name)
$fromName = "Company Name"; // Replace Company Name
/* --------------------------------------------
// reCaptcha Secret
--------------------------------------------- */
// Add this only if you want to use Google reCaptcha with your Contact Forms.
$recaptcha_secret = 'YOUR_RECAPTCHA_SECRET_KEY'; // Your Google reCaptcha Secret
/* --------------------------------------------
// Subject
--------------------------------------------- */
$subject = "Your Website Form Response"; // Your Subject
if (isset($_POST['name'])) {
/*-------------------------------------------------
PHPMailer Initialization
---------------------------------------------------*/
$mail = new PHPMailer(true);
/* Add your SMTP Codes after this Line */
// End of SMTP
if (filter_var($toEmail, FILTER_VALIDATE_EMAIL)) {
$mail->AddAddress($toEmail);
$mail->setFrom($fromEmail, $fromName);
$mail->addReplyTo($_POST['email'], $_POST['name']);
$mail->isHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = $subject . ' [' . $_POST['name'] . ']';
$mail->Body = '<table align="center" border="0" cellpadding="0" cellspacing="20" height="100%" width="100%">
<tr>
<td align="center" valign="top">
<table width="600" bgcolor="#f8f6fe" cellpadding="7" style="font-size:16px; padding:30px; line-height: 28px;">
<tr>
<td style="text-align:right; padding-right: 20px;" width="100" valign="top"><strong>Name:</strong></td>
<td>' . $_POST['name'] . '</td>
</tr>
<tr>
<td style="text-align:right; padding-right: 20px;" width="100" valign="top"><strong>Email:</strong></td>
<td>' . $_POST['email'] . '</td>
</tr>
<tr>
<td style="text-align:right; padding-right: 20px;" width="100" valign="top"><strong>Message:</strong></td>
<td>' . $_POST['form-message'] . '</td>
</tr>
</table>
</td>
</tr>
</table>';
/*-------------------------------------------------
reCaptcha
---------------------------------------------------*/
$message = array(
'recaptcha_invalid' => 'Captcha not Validated! Please Try Again!',
'recaptcha_error' => 'Captcha not Submitted! Please Try Again.'
);
$message_form = !empty($_POST['message']) ? $_POST['message'] : array();
$message['recaptcha_invalid'] = !empty($message_form['recaptcha_invalid']) ? $message_form['recaptcha_invalid'] : $message['recaptcha_invalid'];
$message['recaptcha_error'] = !empty($message_form['recaptcha_error']) ? $message_form['recaptcha_error'] : $message['recaptcha_error'];
if (isset($_POST['g-recaptcha-response'])) {
$recaptcha_data = array(
'secret' => $recaptcha_secret,
'response' => $_POST['g-recaptcha-response']
);
$recap_verify = curl_init();
curl_setopt($recap_verify, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
curl_setopt($recap_verify, CURLOPT_POST, true);
curl_setopt($recap_verify, CURLOPT_POSTFIELDS, http_build_query($recaptcha_data));
curl_setopt($recap_verify, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($recap_verify, CURLOPT_RETURNTRANSFER, true);
$recap_response = curl_exec($recap_verify);
$g_response = json_decode($recap_response);
if ($g_response->success !== true) {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> ' . $message['recaptcha_invalid'] . '<button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
}
}
$forcerecap = (!empty($_POST['force_recaptcha']) && $_POST['force_recaptcha'] != 'false' ) ? true : false;
if (isset($g_response->action) && $g_response->action == 'contact') {
if (isset($g_response->success) && $g_response->success == true && $g_response->action == 'contact') {
} else if ($forcerecap) {
if (!isset($_POST['g-recaptcha-response'])) {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> ' . $message['recaptcha_error'] . '<button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
}
} else {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> ' . $message['recaptcha_error'] . '<button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
}
}
//----- reCaptcha End -----//
$success = "Thank you for contacting us and will be in touch with you very soon."; // Success Message
try {
$resp = $mail->send();
echo json_encode(array('response' => 'success', 'Message' => '<div class="alert alert-success alert-dismissible fade show text-3 text-left"><i class="fa fa-check-circle"></i> ' . $success . ' <button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
} catch (Exception $e) {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> Message could not be sent: ' . $e->errorMessage() . '<button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
} catch (\Exception $e) {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> Message could not be sent: ' . $e->getMessage() . '<button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
}
} else {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> There is a invalid <strong>Receivers Email</strong> address! <button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
}
} else {
echo json_encode(array('response' => 'error', 'Message' => '<div class="alert alert-danger alert-dismissible fade show text-3 text-left"><i class="fa fa-times-circle"></i> There is a problem with the document! <button type="button" class="close font-weight-500 mt-1" data-dismiss="alert">×</button></div>'));
exit;
}
?>
Upvotes: 0
Views: 4127
Reputation: 6740
It seems you are using ReCaptcha v3, but not validating the ReCaptcha score. in v3, if it's spam, ReCaptcha still returns success with a score eg: 0.1 or 0.2, if human, it should be above 0.5. So you should use that to validate instead.
Here's an example code:
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_secret = $secret;
$recaptcha_response = $_POST['recaptcha_response'];
// Make and decode POST request:
$recaptcha_response = url_get_contents( $recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response );
$google_recaptcha_response = json_decode( $recaptcha_response );
if (!$google_recaptcha_response->success || empty($google_recaptcha_response->success)) {
echo "reCAPTCHA verification failed.";
// echo $google_recaptcha_response;
} else {
if ($google_recaptcha_response->score >= 0.5) {
// Verified
// Process form here
Upvotes: 2