Why is a submission going through without hitting ajax submit/validation function - php

Ever since I made a change to a send file, I am getting around 20 spam submissions a day on a form. Before the change there was never spam.
The subtle modifications to my send file are shown below. The change solely consisted of how I was getting the POST data. The commented code below was my original and non-commented is what it is now.
$to_requester = Communication::mail_api($_POST, null, $template, 1, "{$_SERVER['DOCUMENT_ROOT']}/PDFs/{$pdf_downloaded}.pdf");
//$to_requester = Communication::mail_api($_POST, null, $template, 1, "../PDFs/" . $file_mapping[$_POST['pdf_downloaded']] . ".pdf");
There are several parts to my form. The process goes in this order:
Submission to Salesforce
Information sent to my database (via ajax)
Notification emails are sent to the user and myself (via ajax)
The spam submissions that are occurring are only submitted to salesforce. They never touch my send file (this includes the db submission and email notifications). The change I noted above is in the send file, so I have no idea why this would have any effect.
I have jQuery validation setup on the form itself.
The salesforce id and other information is held in a config file and called in the form file.
The submissions are entering salesforce like this:
The name/company fields are being filled with some sort of id/code. Again, the send file or database are not being reached with these submissions. The send file is reached with AJAX communicating in-between.
What could be causing these spam submissions? Is there anything I can do validation wise to make sure this spam is not submitted?
Form
<form action="<?php echo $config['sf_url']; ?>" method="POST" id="pdfForm">
<input type=hidden name="oid" value="<?php echo $config['oid']; ?>">
<input type=hidden name="retURL" value="<?php echo $config['retUrl']; ?>">
<input type="text" class="input block" id="first_name" maxlength="40" name="first_name"placeholder="First Name *">
<input type="text" class="input block" id="last_name" maxlength="80" name="last_name" placeholder="Last Name *">
<input type="email" class="input block" id="email" maxlength="80" name="email" placeholder="Email *">
<input id="pdfButton" class="button" type="submit" value="Download File">
</form>
Config
<?php
function getConfig($key)
{
$db = [
'username' => 'user',
'pass' => 'password',
'dbname' => 'db',
];
$ar = [
'sf' => [
'oid' => 'real id',
'sf_url' => 'https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8',
'retUrl' => 'https://example.com',
],
'pdo' => new PDO("mysql:host=localhost;dbname={$db['dbname']}", $db['username'], $db['pass'])
];
if(array_key_exists($key, $ar))
return $ar[$key];
}
Send file
ini_set('display_errors', 1);
error_reporting(E_ALL);
require 'classes/Communication.php';
require_once '../config.php';
if ($_SERVER['REQUEST_METHOD'] != 'POST')
exit();
$file_mapping = [
//Index
'Linear Structure' => 'Belt_Driven_Linear_1_3D', //LM Index
'Dynamic Structure' => 'Belt_Driven_Linear_5_3D', //LM MH Index
//LM
'Ball-Screw Application' => 'Belt_Driven_Linear_2_3D',
'Belt-Driven Structure' => 'Belt_Driven_Linear_6_3D',
'Linear Motion Enclosure' => 'Belt_Driven_Linear_7_3D'
];
$first_name = trim(htmlspecialchars($_POST['first_name']));
$last_name = trim(htmlspecialchars($_POST['last_name']));
$email = trim(htmlspecialchars($_POST['email']));
$phone = trim(htmlspecialchars($_POST['phone']));
$company = trim(htmlspecialchars($_POST['company']));
$pdf_downloaded = trim(htmlspecialchars($_POST['pdf_downloaded']));
$page_name = $_POST['page_name'];
$hasError = false;
try {
$config = getConfig('db');
$sent = false;
$con = getConfig('pdo');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$consult_insert = "
INSERT INTO pdf_submissions
(first_name, last_name, email, phone, company, date, pdf_downloaded, page_source)
VALUES(?,?,?,?,?,NOW(),?,?)
";
$consult_stmt = $con->prepare($consult_insert);
$consult_stmt->execute(array($first_name, $last_name, $email, $phone, $company, $pdf_downloaded, $page_name));
if (!array_key_exists($pdf_downloaded, $file_mapping)) {
$date = new DateTime();
$hasError = true;
file_put_contents('error_log', "\n[{$date->format('Y-m-d H:i:s')}]" . "Error adding attachment: The file selected could not be found in the file mapping. {$pdf_downloaded}.", FILE_APPEND);
}
} catch (PDOException $e) {
// echo "Connection failed: " . $e->getMessage();
}
if ($hasError !== true) {
/************************ Start to Requester ******************************/
$placeholders = [
'{first_name}',
'{last_name}',
'{phone}',
'{company}',
'{email}',
'{pdf_downloaded}'
];
$values = [
htmlentities($_POST['first_name']),
htmlentities($_POST['last_name']),
htmlentities($_POST['phone']),
htmlentities($_POST['company']),
htmlentities($_POST['email']),
htmlspecialchars($_POST['pdf_downloaded']),
];
$template = str_replace($placeholders, $values, file_get_contents("templates/pdf_to_requester.html"));
// Mail subject line goes here
$_POST['subject'] = 'Subject';
$_POST['h:Reply-To'] = 'sales#example.com';
$to_requester = Communication::mail_api($_POST, null, $template, 1, "{$_SERVER['DOCUMENT_ROOT']}/PDFs/{$pdf_downloaded}.pdf");
if (!$to_requester) {
$msg = [
'status_code' => 500,
'status_message' => 'Email Failed to send.'
];
echo json_encode($msg);
}
/************************ End to Requester ******************************/
/************************ Start to Domain ******************************/
$placeholders = [
'{first_name}',
'{last_name}',
'{email}',
'{phone}',
'{company}',
'{file_requested}',
'{page_name}'
];
$values = [
$first_name = trim(htmlspecialchars($_POST['first_name'])),
$last_name = trim(htmlspecialchars($_POST['last_name'])),
$email = trim(htmlspecialchars($_POST['email'])),
$phone = trim(htmlspecialchars($_POST['phone'])),
$company = trim(htmlspecialchars($_POST['company'])),
$pdf_downloaded = trim(htmlspecialchars($pdf_downloaded)),
$page_name = $_POST['page_name'],
];
$template = str_replace($placeholders, $values, file_get_contents("templates/pdf_to_domain.html"));
// Mail subject line goes here
$_POST['subject'] = 'Subject';
$_POST['h:Reply-To'] = 'sales#example.com';
$_POST['sendTo'] = "info#example.com";
$to_company = Communication::mail_api($_POST, null, $template, 0);
/************************ End to Domain ******************************/
if (!$to_company) {
$msg = [
'status_code' => 500,
'status_message' => 'Email was not sent.'
];
} else {
$msg = [
'status_code' => 200,
'status_message' => 'Check your Email.'
];
}
echo json_encode($msg);
JS
$("form#pdfForm").submit(function (form, e) {
console.log(send);
if(!send)
{
return false;
console.log("Should never touch this " + send);
}
var formData = new FormData(this);
$.ajax({
url: 'https://example.com/php',
type: 'POST',
data: formData,
success: function (e) {
$.LoadingOverlay("hide");
},
cache: false,
contentType: false,
processData: false
});
});

Related

Checkbox is throwing an error in a PHP form

I've got a script that I downloaded that's a contact form with reCaptcha v3 which emails the filled out form.
The reCaptcha and mail is working, but am having a problem with the checkboxes.
When I fill out the form, my error log says
PHP Warning: Undefined variable $instype in /home1/bluehqwi/public_html/gowithfm/quote/AjaxForm.php on line 121
The code at line 121 is:
'instype[]' => $instype
This is what I have in the AjaxForm.php for checkboxes -
if(!empty($_POST['instype[]'])) {
foreach($_POST['instype[]'] as $instype){
echo "value : ".$instype.'<br/>';
}
}
In my form, my checkboxes are -
<input class="form-check-input shadow-none" type="checkbox" value="Business insurance" name="instype[]" id="instype">
<label class="form-check-label" for="instype">Business insurance</label>
<input class="form-check-input shadow-none" type="checkbox" value="Life insurance" name="instype[]" id="instype">
<label class="form-check-label" for="instype">Life insurance</label>
I need to have multiple checkboxes in the contact form and have those displayed in the email that's sent.
I'm more on the UX/UI Design side, so I'm not really fluent in Ajax and PHP, so any help is appreciated.
Thanks!
NOTE: Here's the complete AjaxForm.php file.
<?php
/**
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
# https://www.php.net/manual/fr/timezones.php
date_default_timezone_set('America/Los_Angeles');
require __DIR__ . '/../PHPMailer/Exception.php';
require __DIR__ . '/../PHPMailer/PHPMailer.php';
require __DIR__ . '/../PHPMailer/SMTP.php';
require __DIR__ . '/../recaptcha/autoload.php';
class Ajax_Form {
# Constants to redefined
# Check this for more configurations: https://blog.mailtrap.io/phpmailer
const HOST = 'xxxxx'; # SMTP server
const USERNAME = 'xxxxx'; # SMTP username
const PASSWORD = 'xxxxx'; # SMTP password
const SECRET_KEY = 'xxxxx'; # GOOGLE secret key
const SMTP_SECURE = PHPMailer::ENCRYPTION_STARTTLS;
const SMTP_AUTH = true;
const PORT = 587;
const SUBJECT = 'xxxxx';
const HANDLER_MSG = [
'success' => '✔️ Your message has been sent !',
'token-error' => '❌ Error recaptcha token.',
'enter_firstname' => '❌ Please enter your first name.',
'enter_lastname' => '❌ Please enter your last name.',
'enter_email' => '❌ Please enter a valid email.',
'enter_phone' => '❌ Please enter a valid phone number.',
'enter_message' => '❌ Please enter your message.',
'enter_instype' => '❌ Please enter instype.',
'bad_ip' => '❌ 56k ?',
'ajax_only' => '❌ Asynchronous anonymous.',
'email_body' => '
<h1>{{subject}}</h1>
<p><b>First name:</b> {{firstname}}</p>
<p><b>Last name:</b> {{lastname}}</p>
<p><b>Email:</b> {{email}}</p>
<p><b>Phone:</b> {{phone}}</p>
<p><b>Address 1:</b> {{address1}}</p>
<p><b>Address 2:</b> {{address2}}</p>
<p><b>City:</b> {{city}}</p>
<p><b>State:</b> {{state}}</p>
<p><b>Zip:</b> {{zip}}</p>
<p><b>Interested in:</b> {{instype}}</p>
'
];
/* <p><b>Date</b>: {{date}}</p>
<p><b>Name</b>: {{name}}</p>
<p><b>E-Mail</b>: {{email}}</p>
<p><b>Message</b>: {{message}}</p>
<p><b>IP</b>: {{ip}}</p>
'
];*/
/**
* Ajax_Form constructor
*/
public function __construct()
{
# Check if request is Ajax request
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
$this->statusHandler('ajax_only');
}
# Check if fields has been entered and valid
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$firstname = $this->secure($_POST['firstname']) ?? $this->statusHandler('enter_name');
$lastname = $this->secure($_POST['firstname']) ?? $this->statusHandler('enter_name');
$email = filter_var($this->secure($_POST['email']), FILTER_SANITIZE_EMAIL) ?? $this->statusHandler('enter_email');
$phone = $this->secure($_POST['phone']) ?? $this->statusHandler('enter_phone');
$address1 = $this->secure($_POST['address1']) ?? $this->statusHandler('enter_address1');
$address2 = $this->secure($_POST['address2']) ?? $this->statusHandler('enter_address2');
$city = $this->secure($_POST['city']) ?? $this->statusHandler('enter_city');
$state = $this->secure($_POST['state']) ?? $this->statusHandler('enter_state');
$zip = $this->secure($_POST['zip']) ?? $this->statusHandler('enter_zip');
# if (!empty($_POST['instype']))
# $instype = $this->secure($_POST['instype']);
# else
# $this->statusHandler('enter_instype');
if(!empty($_POST['instype'])) {
foreach($_POST['instype'] as $instype){
echo "value : ".$instype.'<br/>';
}
}
# $message = $this->secure($_POST['message']) ?? $this->statusHandler('enter_message');
$token = $this->secure($_POST['recaptcha-token']) ?? $this->statusHandler('token-error');
$ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ?? $this->statusHandler('bad_ip');
$date = new DateTime();
}
# Prepare email body
$email_body = self::HANDLER_MSG['email_body'];
$email_body = $this->template($email_body, [
'subject' => self::SUBJECT,
'date' => $date->format('j/m/Y H:i:s'),
'firstname' => $firstname,
'lastname' => $lastname,
'email' => $email,
'phone' => $phone,
'address1' => $address1,
'address2' => $address2,
'city' => $city,
'state' => $state,
'zip' => $zip,
'instype' => $instype
]);
# Verifying the user's response
$recaptcha = new \ReCaptcha\ReCaptcha(self::SECRET_KEY);
$resp = $recaptcha
->setExpectedHostname($_SERVER['SERVER_NAME'])
->verify($token, $_SERVER['REMOTE_ADDR']);
if ($resp->isSuccess()) {
# Instanciation of PHPMailer
$mail = new PHPMailer(true);
$mail->setLanguage('en', __DIR__ . '/vendor/PHPMailer/language/');
try {
# Server settings
$mail->SMTPDebug = SMTP::DEBUG_OFF; # Enable verbose debug output
$mail->isSMTP(); # Set mailer to use SMTP
$mail->Host = self::HOST; # Specify main and backup SMTP servers
$mail->SMTPAuth = self::SMTP_AUTH; # Enable SMTP authentication
$mail->Username = self::USERNAME; # SMTP username
$mail->Password = self::PASSWORD; # SMTP password
$mail->SMTPSecure = self::SMTP_SECURE; # Enable TLS encryption, `ssl` also accepted
$mail->Port = self::PORT; # TCP port
# Recipients
$mail->setFrom(self::USERNAME, $firstname, $lastname);
$mail->addAddress($email, $firstname, $lastname);
$mail->AddCC(self::USERNAME, 'Dev_copy');
$mail->addReplyTo(self::USERNAME, 'Information');
# Content
$mail->isHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = self::SUBJECT;
$mail->Body = $email_body;
$mail->AltBody = strip_tags($email_body);
# Send email
$mail->send();
$this->statusHandler('success');
} catch (Exception $e) {
die(json_encode($mail->ErrorInfo));
}
} else {
die(json_encode($resp->getErrorCodes()));
}
}
/**
* Template string values
*
* #param string $string
* #param array $vars
* #return string
*/
public function template(string $string, array $vars): string
{
foreach ($vars as $name => $val) {
$string = str_replace("{{{$name}}}", $val, $string);
}
return $string;
}
/**
* Secure inputs fields
*
* #param string $post
* #return string
*/
public function secure(string $post): string
{
$post = htmlspecialchars($post, ENT_QUOTES);
$post = stripslashes($post);
$post = trim($post);
return $post;
}
/**
* Error or success message
*
* #param string $message
* #return json
*/
public function statusHandler(string $message): json
{
die(json_encode(self::HANDLER_MSG[$message]));
}
}
# Instance
new Ajax_Form();
Here's the AjaxForm.js code
const publicKey = "XXXXX"; // GOOGLE public key
// Get token from API
function check_grecaptcha() {
grecaptcha.ready(function () {
grecaptcha.execute(publicKey, {
action: "ajaxForm"
}).then(function (token) {
$("[name='recaptcha-token']").val(token);
});
});
}
// Show response in .alert
function alertShowing(response) {
$("#response-alert").html(JSON.parse(response));
$("#response-alert").removeClass("d-none");
$("#response-alert").addClass("d-block");
}
$(function () {
check_grecaptcha();
$("#contactform").validate({
// Form fields rules
rules: {
firstname: {
required: true,
minlength: 3
},
lastname: {
required: true,
minlength: 3
},
email: {
required: true,
email: true
},
message: {
required: false,
minlength: 5
}
},
// Error messages
messages: {
firstname: {
required: "Please enter your first name.",
minlength: "Must be at least 3 characters long."
},
lastname: {
required: "Please enter your last name.",
minlength: "Must be at least 3 characters long."
},
email: "Please enter a valid email.",
message: {
required: "Please enter your message.",
minlength: "Must be at least 5 characters long."
}
},
errorClass: "invalid-feedback",
// Dynamic validation classes
highlight: function (element) {
$(element).addClass("is-invalid").removeClass("is-valid");
},
unhighlight: function (element) {
$(element).addClass("is-valid").removeClass("is-invalid");
},
// Action on submit
submitHandler: function (form) {
$(".spinner-border").removeClass("d-none");
$("#sendtext").addClass("d-none");
$.post(form.action, $(form).serialize())
.done(function (response) {
alertShowing((response));
$(".spinner-border").addClass("d-none");
$("#sendtext").removeClass("d-none");
$("#submit-btn").prop("disabled", true);
check_grecaptcha();
setTimeout(function () {
$("#submit-btn").prop("disabled", false);
$("form").trigger("reset");
$("form").each(function () {
$(this).find(".form-control").removeClass("is-valid")
})
}, 3000);
})
.fail(function (response) {
alertShowing((response));
$(".spinner-border").addClass("d-none");
$("#sendtext").removeClass("d-none");
});
}
});
});
Like already stated in the comments. You never initialized your variable $instype, but you try to access it several times. At least inititialize the variable before any access with an empty value like
$instype = ''
or by uncommenting
$instype = $this->secure($_POST['instype']);
But be aware, this won't solve your problem since you have this line in a comment and also will never be run if the the if-condition does not match.

Jquery send the email with attachments

I am working on the jquery to upload the attachments so I can post the files name via ajax. I have got a problem with storing the files name in the array and display each file name in the loop, because it will store 2 files name in the array in one index using this code:
$(".file-list_yhs").each(function() {
attachments[i++] = $(this).find('.vI').text();
});
Output:
Array
{
[0] => uploads/add email.txtemail.zip
}
Array
It should be:
Array
{
[0] => uploads/add email.txt
}
Array
{
[1] => uploads/email.zip
}
Here is the full code:
$(document).on('click','#domodal_send', function(e) {
if ($(".notify-outer").css('display') == 'none') {
var email = $("#domodal_email_receipt").val();
var subject = $("#domodal_subject").val();
var from_name = $("#avater_name").text();
var from_email = $('#avater_email').text();
var emailbody = $("#domodal_message").html();
var attachments = [];
var i = 0;
$(".file-list_yhs").each(function() {
attachments[i++] = $(this).find('.vI').text();
});
$.ajax({
url: 'sendMail.php',
type: 'POST',
data : {
send_to: email,
from: from_name,
from_email: from_email,
emailsubject: subject,
emailbody: emailbody,
emailattachment: attachments
},
success: function(result)
{
alert(result);
}
});
}
});
SendMail.php:
<?php
require_once "Mail.php";
require_once "Mail/mime.php";
require_once('Mail/IMAPv2.php');
//Connect to the database
include('config.php');
$inbox = '{imap.example.com:993/imap/ssl/novalidate-cert}INBOX';
$mailserver = '{imap.example.com:993/imap/ssl/novalidate-cert}INBOX.Sent';
if (isset($_POST['send_to']))
{
$from = "Robert <rob#example.com>";
$to_email = $_POST['send_to'];
$to = $firstname . " <$to_email>";
$subject = $_POST['emailsubject'];
$message = $_POST['emailbody'];
$message_without_image = $_POST['emailbody'];
$filenames = $_POST['emailattachment'];
$files = [];
foreach ($filenames as $filename) {
$files[] = 'uploads/' . $filename;
}
print_r($files);
$username = 'username';
$password = 'password';
$smtp_hostname = "smtp.example.com";
$port = "587";
echo $files;
/*$messageID = sprintf("<%s.%s#%s>",
base_convert(microtime(), 10, 36),
base_convert(bin2hex(openssl_random_pseudo_bytes(8)), 16, 36),
'example.com');
$date = date('Y-m-d H:i:s');
$emailID = '';
$sent_db = "SELECT email_id FROM sent WHERE email_id = '$messageID'";
$sent_result = mysqli_query($link, $sent_db) or die($link->error);
if(mysqli_num_rows($sent_result) == 0)
{
$sent_db1 = "INSERT INTO sent (id, email_id, email, sendDateTime, isRead, readDateTIme) VALUES ('', '$messageID', '$to', '$date', '0', '0000-00-00 00:00:00')";
if (mysqli_query($link, $sent_db1)) {
$emailID = mysqli_insert_id($link);
}
}
$message .= "<img src=\"http://test.example.com/project/track/Images/signature.gif?id=".$emailID."&etc=".time()." \" style=\"width: 0; max-height:0; overflow:hidden; \">";
$headers = array ('From' => $from,
'To' => $to, 'Subject' => $subject,
'Reply-To' => $from,
'Content-Type' => 'Content-Type: text/plain; charset=UTF-8',
'MIME-Version' => '1.0',
'Received' => 'from smtp.example.com',
'Date' => date("r"),
'Message-ID' => sprintf("<%s.%s#%s>",
base_convert(microtime(), 10, 36),
base_convert(bin2hex(openssl_random_pseudo_bytes(8)), 16, 36),
'example.com'));
$params = array ('host' => $smtp_hostname,
'port' => $port,
'auth' => 'PLAIN', // Note 1
'socket_options' => array('ssl' => array('verify_peer_name' => false, 'verify_peer' => false)), // Note 2
'username' => $username,
'password' => $password);
$mime_params = array(
'text_encoding' => '7bit',
'text_charset' => 'UTF-8',
'html_charset' => 'UTF-8',
'head_charset' => 'UTF-8'
);
$crlf = "\r\n";
$mime = new Mail_mime(array('eol' => $crlf));
$body = $message;
$mime->setTXTBody($body);
$mime->setHTMLBody($body);
if(!empty($files)) {
$mime->addAttachment($files);
}
$body = $mime->get($mime_params);
$headers = $mime->headers($headers);
$smtp = Mail::factory ('smtp', $params);
$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail))
{
echo("<p>" . $mail->getMessage() . "</p>");
}
else
{
echo("<p>Email has been sent!</p>");
}
}
?>
What I am trying to do is to store the files name in the array and post it via ajax after I have uploaded the files on my server. When the files is upload on the server, I can be able to output each files name to add the files location on the server and send the email with the attachments.
Can you please show me an example how I could store each file name in the loop where I could use it to post it with ajax to output each file name?
Thank you.
EDIT: Here is the html:
<div style="width: 70%; margin-left: 10px; position:relative;" class="file-list_yhs">
<div class="dL" tabindex="-1" id=":vw" aria-label="Attachment: edit_link1.png. Press enter to view the attachment and delete to remove it" style="position:relative;">
<input id=":vp" name="attach" type="hidden" value="#msg-a:r-6685135251679589431_#msg-a:r-6685135251679589431_null_-1" checked="">
<div style="display:flex">
<a class="dO" id=":vq" style="display:flex;">
<div id="domodal_attachment" class="vI">addd her email.txt</div>
<div class="vJ">(0K)</div>
</a>
<div id=":vn" role="button" aria-label="Remove attachment" class="vq" tabindex="-1" data-tooltip="Remove attachment" style="position:absolute; right:5px; top:5px;"></div>
</div>
</div>
<div class="dL" tabindex="-1" id=":vw" aria-label="Attachment: edit_link1.png. Press enter to view the attachment and delete to remove it" style="position:relative;">
<input id=":vp" name="attach" type="hidden" value="#msg-a:r-6685135251679589431_#msg-a:r-6685135251679589431_null_-1" checked="">
<div style="display:flex">
<a class="dO" id=":vq" style="display:flex;">
<div id="domodal_attachment" class="vI">email.zip</div>
<div class="vJ">(183K)</div>
</a>
<div id=":vn" role="button" aria-label="Remove attachment" class="vq" tabindex="-1" data-tooltip="Remove attachment" style="position:absolute; right:5px; top:5px;"></div>
</div>
</div>
</div>
You're creating an array element for each .file-list_yhs DIV, not for each .vI DIV. $(this).find('.vI').text() will concatenate the texts of all the .vI elements that it finds in each .file-list_yhs.
Change your loop to
$(".file-list_yhs .vI").each(function() {
attachments.push($(this).text());
}
You can also use .map:
attachments = $(".file-list_yhs .vI").map(function() {
return $(this).text();
}).get();
.get() is needed at the end to convert the jQuery object that .map() returns to an array.

Sending email using mailgun PHP API

I am trying to send an email with mailguns PHP api:
define('MAILGUN_KEY', 'key-ExamPle3xAMPle');
define('MAILGUN_DOMAIN', 'example.com');
$mailgun = new Mailgun\Mailgun(MAILGUN_KEY);
$mailgun->sendMessage(MAILGUN_DOMAIN, [
'from' => 'noreply#signstoptt.com',
'to' => $email,
'subject' => 'Sign Stop mailing list confirmation.',
'html' => "
Hello{$name},</br></br>
This is a test."
]);
I have even tried to use array() instead of [ ].
I receive the following error in my php error log:
MissingRequiredParameters
It implies that what I am passing to the post function is incomplete or incorrect. upon inspecting the post function in the RestClient, I see that the function requires 2 arrays and not 1, so I tried adding a 2nd array with message attachments and it just got more errors, this time with guzzle (a dependency for mailgun)
[26-Jan-2015 14:32:50 UTC] PHP Fatal error: Uncaught exception 'Mailgun\Connection\Exceptions\MissingRequiredParameters' with message 'The parameters passed to the API were invalid. Check your inputs!' in C:\Users\Zachary\Documents\NetBeansProjects\SS_MailingList\vendor\mailgun\mailgun-php\src\Mailgun\Connection\RestClient.php:187
Stack trace:
#0 C:\Users\Zachary\Documents\NetBeansProjects\SS_MailingList\vendor\mailgun\mailgun-php\src\Mailgun\Connection\RestClient.php(116): Mailgun\Connection\RestClient->responseHandler(Object(Guzzle\Http\Message\Response))
#1 C:\Users\Zachary\Documents\NetBeansProjects\SS_MailingList\vendor\mailgun\mailgun-php\src\Mailgun\Mailgun.php(106): Mailgun\Connection\RestClient->post('signstoptt.com/...', Array, Array)
#2 C:\Users\Zachary\Documents\NetBeansProjects\SS_MailingList\vendor\mailgun\mailgun-php\src\Mailgun\Mailgun.php(53): Mailgun\Mailgun->post('signstoptt.com/...', Array, Array)
#3 C:\Users\Zachary\Documents\NetBeansProjects\SS_MailingList\subscribe.php(26): Mailgun\Mailgun->sendMessage('signstoptt.com', Array)
#4 in C:\Users\Zachary\Documents\NetBeansProjects\SS_MailingList\vendor\mailgun\mailgun-php\src\Mailgun\Connection\RestClient.php on line 187
Has anyone else had this problem. I am running the site on a glassfish server setup by netbeans. I also used composer to install mailgun and its dependencies.
EDIT: Added more information.
init.php
<?php
require_once 'vendor/autoload.php';
define('MAILGUN_KEY', 'key-854743a7e');
define('MAILGUN_PUBKEY', 'pubkey-b00e47d7');
define('MAILGUN_DOMAIN', 'example.com');
define('MAILGUN_LIST', 'customers#example.com');
define('MAILGUN_SECRET','xjhbJH7');
$mailgun = new Mailgun\Mailgun(MAILGUN_KEY);
$mailgunValidate = new Mailgun\Mailgun(MAILGUN_PUBKEY);
$mailgunOptIn = $mailgun->OptInHandler();
subscribe.php
<?php
require_once 'init.php';
if(isset($_POST['name'], $_POST['email']))
{
$name = $_POST['name'];
$email = $_POST['email'];
$validate = $mailgunValidate->get('address/validate', [
'address' => $email
])->http_response_body;
if($validate->is_valid)
{
$hash = $mailgunOptIn->generateHash(MAILGUN_LIST, MAILGUN_SECRET, $email);
$result = $mailgun->sendMessage(MAILGUN_DOMAIN, [
'from' => 'noreply#example.com',
'to' => $email,
'subject' => 'example mailing list confirmation.',
'html' => "
Hello{$name},</br></br>
You submitted a request to join our mailing list, to confirm this subscription please click on the link provided below.</br></br>
http://localhost:8000/confirm.php?hash={$hash}"
]);
$mailgun->post('lists/' . MAILGUN_LIST . '/members', [
'name' => $name,
'address' => $email,
'subscribed' => 'no'
]);
header('Location: ./');
}
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Subscribe | Mailing list</title>
</head>
<body>
<div class="container">
<form action="subscribe.php" method="post">
<div class="field">
<label>
Name
<input type="text" name="name" autocomplete="off">
</label>
</div>
<div class="field">
<label>
Email
<input type="text" name="email" autocomplete="off">
</label>
</div>
<input type="submit" value="Subscribe" class="button">
</form>
</div>
</body>
</html>
You forgot the text key which is used when html isn't available by the mail client.
Your code will look like
define('MAILGUN_KEY', 'key-ExamPle3xAMPle');
define('MAILGUN_DOMAIN', 'example.com');
$mailgun = new Mailgun\Mailgun(MAILGUN_KEY);
$mailgun->sendMessage(MAILGUN_DOMAIN, [
'from' => 'noreply#signstoptt.com',
'to' => $email,
'subject' => 'Sign Stop mailing list confirmation.',
'text' => 'Hello ' . $name . ', this is a test.',
'html' => '
Hello ' . $name . ',</br></br>
This is a test.'
]);
By the way; I recommend always using single quotes or double quotes for readability.

Contact form doesn't transfer data from AngularJS to PHP

I am trying to retrieve data from AngularJS file to PHP file, but I get the error that it's empty.
I can't find any good examples that are dealing with posting data from angularJS to php file and so I need help.
Angularjs file:
angular.module('myApp', ['ajoslin.promise-tracker'])
.controller('help', function ($scope, $http, $log, promiseTracker, $timeout) {
$scope.ph_numbr =/[0-9]+/;
// Form submit handler.
$scope.submit = function(form) {
// Trigger validation flag.
$scope.submitted = true;
// If form is invalid, return and let AngularJS show validation errors.
if (!$scope.toggle || $scope.toggle.length <= 0 || form.$invalid) {
return;
}
// Default values for the request.
$scope.progress = promiseTracker('progress');
var config = {
params : {
//'callback' : 'JSON_CALLBACK',
'name' : $scope.name,
'email' : $scope.email,
'toggle' : $scope.toggle,
'phone' : $scope.phone,
'comments' : $scope.comments
},
tracker : 'progress'
};
$http({
method : 'POST',
url : 'js/contact.php',
data: config,
headers : {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})
.success(function(data, status, headers, config) {
if (data.success) {
$scope.name = null;
$scope.email = null;
$scope.toggle = null;
$scope.phone = null;
$scope.comments = null;
$scope.messages = 'Your form has been sent!';
$scope.submitted = false;
} else {
$scope.messages = 'Oops, we received your request, but there was an error processing it.';
$log.error(data);
}
})
.error(function(data, status, headers, config) {
$scope.progress = data;
$scope.messages = 'There was a network error. Try again later.';
$log.error(data);
});
// Hide the status message which was set above after 3 seconds.
var promise = $timeout(function() {
$scope.messages = null;
}, 3000);
$scope.progress.addPromise(promise);
};
});
php file:
<?php
/*error_reporting(E_ALL);
ini_set('display_errors', '1');
require_once 'js/PHPMailerAutoload.php';*/
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);
$data = file_get_contents("php://input");
$postData = json_decode($data);
if (isset($_POST['name']) && isset($_POST['email']) && isset($_POST['toggle']) && isset($_POST['comments'])) {
//check if any of the inputs are empty
if (empty($_POST['name']) || empty($_POST['email']) || empty($_POST['toggle']) || empty($_POST['comments'])) {
$data = array('success' => false, 'message' => 'Please fill out the form completely.');
echo json_encode($data);
exit;
}
$email = trim($_POST['email']);
$subject = trim($_POST['toggle']);
//email address settings
$my_address = "*#yahoo.com";
$headers = "From: ".$email;
$message = "Name: " . $_POST['name'] . "\r\n\r\nMessage: " . $_POST["phone"] . "\r\n\r\nMessage: " . stripslashes($_POST['comments']);
$to = $my_address;
if (isset($_POST['ref'])) {
$mail->Body .= "\r\n\r\nRef: " . $_POST['ref'];
}
if(!$mail->send()) {
$data = array('success' => false, 'message' => 'Message could not be sent. Mailer Error: ' . $mail->ErrorInfo);
echo json_encode($data);
exit;
}
mail($to, $subject, $message, $headers);
$data = array('success' => true, 'message' => 'Thanks! We have received your message.');
echo json_encode($data);
} else {
$data = array('success' => false, 'message' => 'Please fill out the form completely.');
echo json_encode($data);
}
?>
The error message that I get is: "Please fill out the form completely" - which means it doesn't get the values.
My other question is how in the AngularJS do I retrieve the data.success value from the php file?
You seem to be getting the data here:
$data = file_get_contents("php://input");
$postData = json_decode($data);
but then you're using $_POST instead. Perhaps this would work:
if (empty($postData['name']) //etc
It looks like you're accessing data.success appropriately and the value should be set to false as your code currently is.
Additional code review:
If there are errors on the server, it's best to return a status code that indicates that. As is, the server is returning 200 (default), which means everything is OK, even though the request is actually failing. That would eliminate the need for data.success. If the server sends status 200, your .success function will fire. If it returns an error status, like 404, then your .error function would fire instead.
I have doubts about your need of the Content-Type header. You might want to reconsider if that's necessary.
On your Angular form, you ought to nest those $scope properties in an object:
$scope.formData = {
name: '',
email: '',
//etc
}
Then, you can simply pass that directly to your $http call and to reset the values you can simply do $scope.formData = {}.

Slow Form Processing in PHP - Need Queue?

I have a web form which I want to validate the inputs, and if it passes validation, send the info to a web service, and save to mySQL as a backup. If there is an error either sending to the web service, or with sql, I want to email myself an alert to let me know. When there are no errors, everything runs fine. To test what would happen if there is an error, I have put in the wrong mysql credentials. When this happens, the whole script takes about 30 seconds to process. I'm wondering if there is a way to run the validation part and return the response, before finishing the script. I want to call the web service and save to mysql in the background, after the response to the server has been sent. Is this possible? Would I need to implement something like gearman?
Also, this would be a fairly high volume form. If two people tried to submit at the same time, would there be a mysql issue? Are there any ways to better improve security? I'm a beginner so any extra advice would be great.
Thanks!
<?php
if( isset($_POST) ){
//form validation vars
$formok = true;
$errors = array();
//sumbission data
$ipaddress = $_SERVER['REMOTE_ADDR'];
//
//form data
//
//Services
if(isset($_POST['services'])) {
$services = $_POST['services'];
} else {
$services = array(
'Neck' => NULL,
'Back' => NULL,
'Other' => NULL,
);
}
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$TelephoneSanitized = preg_replace("/[^0-9]/", "", $telephone); //format phone as number only
//if phone number does not start with 1, and the length is less than 11 characters, add the 1 to the beginning
if ((substr($TelephoneSanitized, 0, 1) != '1') && (strlen($TelephoneSanitized) < 11)) {
$TelephoneSanitized = "1".$TelephoneSanitized;
}
//$state = strip_tags($_POST['state']);
$location = $_POST['location'];
$message = $_POST['message'];
$leadsource = $_POST['leadsource'];
$refId = $_POST['refId'];
$isconsult = $_POST['isconsult'];
//Third Party Emails
if(isset($_POST['receiveThirdPtyEmails'])) {
$receiveThirdPtyEmails = strip_tags($_POST['receiveThirdPtyEmails']);
} else {
$receiveThirdPtyEmails = NULL;
}
//
//validation
//
//validate location has been set
if($location == 0){
$formok = false;
$errors[] = "Please select your nearest location";
}
//validate name is not empty
if(empty($firstname)){
$formok = false;
$errors[] = "Please enter your first name";
}
if(empty($lastname)){
$formok = false;
$errors[] = "Please enter your last name";
}
//validate email address is not empty
if(empty($email)){
$formok = false;
$errors[] = "Please enter your email address";
//validate email address is valid
}elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)){
$formok = false;
$errors[] = "You have not entered a valid email address";
}
//validate phone is not empty
if(empty($telephone)){
$formok = false;
$errors[] = "Please enter your phone number";
}
//validate phone is at least 10 characters
elseif(strlen($TelephoneSanitized) < 10){
$formok = false;
$errors[] = "Your phone number must be at least 10 characters";
}
//what we need to return back to our form
$returndata = array(
'posted_form_data' => array(
'services' => $services,
'firstname' => $firstname,
'lastname' => $lastname,
'email' => $email,
'telephone' => $telephone,
//'state' => $state,
'location' => $location,
'message' => $message
),
'form_ok' => $formok,
'errors' => $errors,
);
//if this is not an ajax request
if(empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest'){
//set session variables
session_start();
$_SESSION['cf_returndata'] = $returndata;
//redirect back to form
header('location: ' . $_SERVER['HTTP_REFERER']);
}
//
//send to web service if all is ok
//
if($formok){
//build query string
$fields = array('services' => $services,
'location' => $location,
'firstname' => $firstname,
'lastname' => $lastname,
'email' => $email,
'emailconfirm' => $email,
'phone' => $TelephoneSanitized,
'comments' => $message,
'refid' => $refId,
'leadsource' => $leadsource,
'isconsult' => $isconsult,
'receiveThirdPtyEmails' => $receiveThirdPtyEmails);
$url = "http://fake.aspx?" . http_build_query($fields, '', "&");
$url = preg_replace('/%5B[a-zA-Z]+%5D/', '', $url);
$curl_handle = curl_init($url);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
$results = curl_exec($curl_handle);
curl_close($curl_handle);
}
//
//save data to mysql if all is ok PDO
//
if($formok){
// Connecting to the MySQL server
$host="fakehost-on the same server as form";
$user_name="fakeuser";
$pwd="fakepass";
$database_name="fakedb";
$services = implode(',',array_filter($services)); // change array to string
date_default_timezone_set('America/New_York');
$date = date('m/d/Y h:i:s a', time());
$date = date("Y-m-d H:i:s",strtotime($date));
// mysql
try {
//connect to db
$conn = new PDO("mysql:host=$host;dbname=$database_name", $user_name, $pwd);
//set error handling
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//prepare statement
$q = $conn->prepare("INSERT INTO leads
(ip_address, lead_time, location, first_name, last_name, email_address, telephone, comments, services, receiveThirdPtyEmails, leadsource, refid)
VALUES
(:ip_address, :lead_time, :location, :first_name, :last_name, :email_address, :telephone, :comments, :services, :receiveThirdPtyEmails, :leadsource, :refid)");
//execute statement
$q->execute(array(
':ip_address'=>$ipaddress,
':lead_time'=>$date,
':location'=>$location,
':first_name'=>$firstname,
':last_name'=>$lastname,
':email_address'=>$email,
':telephone'=>$TelephoneSanitized,
':comments'=>$message,
':services'=>$services,
':receiveThirdPtyEmails'=>$receiveThirdPtyEmails,
':leadsource'=>$leadsource,
':refid'=>$refId));
}
catch(PDOException $e) {
$error_code = $e->getMessage(); // Specify the error code
$error_type = "SQL Insert Failed";
require_once("resources/error-mailer.php"); // Include the error mailer script
}
# close the connection
$conn = null;
}
}
Javascript/jQuery using JSON and AJAX is your best bet. There's a great example here:
Send JSON data via POST (ajax) and receive json response from Controller (MVC)
Also security wise, you'll want to use the mysqli_real_escape_string():
http://php.net/manual/en/mysqli.real-escape-string.php
on strings values you accept via POST or GET before you put the value into your query. It avoids SQL injection. For integers use abs(intval($_POST['posted_integer'])) or ctype_digit, whatever floats your needs, or preg_replace() / preg_match() regular expressions.
DO NOT let POST or GET values go untouched into your database!!

Categories