I have this contact form but I am confused as to how I can insert PHPMailer (without Composer) into the script?
I am not sure how to properly add it so that way, once it processes and sends the form it alerts the user. I do not have the ability to utilize composer, so I would need to upload PHPMailer into the directory.
<?php
function validateRecaptcha($secret, $clientResponse, $clientIp)
{
$data = http_build_query([
"secret" => $secret,
"response" => $clientResponse,
"remoteip" => $clientIp,
]);
$options = [
"http" => [
"header" =>
"Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: ".strlen($data)."\r\n",
"method" => "POST",
"content" => $data,
],
];
$response = file_get_contents(
"https://www.google.com/recaptcha/api/siteverify",
false,
stream_context_create($options)
);
if($response === false)
{
return false;
}
else if(($arr = json_decode($response, true)) === null)
{
return false;
}
else
{
return $arr["success"];
}
}
$errors = array(); // array to hold validation errors
$data = array(); // array to pass back data
// validate the variables ======================================================
// if any of these variables don't exist, add an error to our $errors array
if (empty($_POST['firstName']))
$errors['firstName'] = 'First Name is required.';
if (empty($_POST['lastName']))
$errors['lastName'] = 'Last Name is required.';
if (empty($_POST['companyName']))
$errors['companyName'] = 'Company Name is required.';
if (empty($_POST['companyAddress']))
$errors['companyAddress'] = 'Company Address is required.';
if (empty($_POST['city']))
$errors['city'] = 'City is required.';
if (empty($_POST['state']))
$errors['state'] = 'State is required.';
if (empty($_POST['emailAddress']))
$errors['emailAddress'] = 'Email Address is required.';
if (empty($_POST['comment']))
$errors['comment'] = 'Comment is required.';
if (empty($_POST['g-recaptcha-response']))
$errors['captcha'] = 'Captcha is required.';
// return a response ===========================================================
// if there are any errors in our errors array, return a success boolean of false
if(!validateRecaptcha($secret, $_POST['g-recaptcha-response'], $_SERVER["REMOTE_ADDR"]))
{
$errors['recaptcha'] = 'Captcha is required.';
}
if ( ! empty($errors)) {
// if there are items in our errors array, return those errors
$data['success'] = false;
$data['errors'] = $errors;
} else {
// if there are no errors process our form, then return a message
// DO ALL YOUR FORM PROCESSING HERE
// THIS CAN BE WHATEVER YOU WANT TO DO (LOGIN, SAVE, UPDATE, WHATEVER)
// show a message of success and provide a true success variable
$data['success'] = true;
$data['message'] = 'Success!';
}
// return all our data to an AJAX call
echo json_encode($data);
Without autoloader:
<?php
//You shall use the following exact namespaces no
//matter in whathever directory you upload your
//phpmailer files.
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
//Now include the following following files based
//on the correct file path. Third file is required only if you want to enable SMTP.
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';
?>
You shall add the following class to initiate the mailer after checking if your query or condition is executed.
<?php
$mail = new PHPMailer(true);
?>
You shall find a nice and simple example at https://github.com/PHPMailer/PHPMailer/blob/master/README.md to start with.
I hope it helps.
Related
I have built a PHP form, but want an email to be sent to whatever country the user chooses on a dropdown.
E.g. If they choose UK on dropdown, send an email to our UK account. If they choose US, send to our US account etc...
The entire form is working perfectly at the moment, I just need this little feature to work then it would be perfect. Thank you for looking, its appreciated!
This is my code so far:-
<?php
// require ReCaptcha class
require('recaptcha-master/src/autoload.php');
// configure
// an email address that will be in the From field of the email.
$from = 'A new client has registered their details <noreply#emailaddress.com>';
// an email address that will receive the email with the output of the form
$sendTo = '<scott#emailaddress.com>';
// subject of the email
$subject = 'New Registered Form:';
// form field names and their translations.
// array variable name => Text to appear in the email
$fields = [
'firstname' => 'First Name', 'lastname' => 'Last Name', 'company' => 'Company', 'email' => 'Email Address', 'jobrole' => 'Job Role',
'postcode' => 'Postcode', 'country' => 'Country',
];
// message that will be displayed when everything is OK :)
$okMessage = 'Thank you for registering.';
// If something goes wrong, we will display this message.
$errorMessage = 'There was an error while submitting the form. Please try again later';
// ReCaptch Secret
$recaptchaSecret = 'AAAA';
// let's do the sending
// if you are not debugging and don't need error reporting, turn this off by error_reporting(0);
error_reporting(E_ALL & ~E_NOTICE);
try
{
if ( ! empty($_POST))
{
// validate the ReCaptcha, if something is wrong, we throw an Exception,
// i.e. code stops executing and goes to catch() block
if ( ! isset($_POST['g-recaptcha-response']))
{
throw new \Exception('ReCaptcha is not set.');
}
// do not forget to enter your secret key from https://www.google.com/recaptcha/admin
$recaptcha = new \ReCaptcha\ReCaptcha($recaptchaSecret, new \ReCaptcha\RequestMethod\CurlPost);
// we validate the ReCaptcha field together with the user's IP address
$response = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
if ( ! $response->isSuccess())
{
throw new \Exception('ReCaptcha was not validated.');
}
// everything went well, we can compose the message, as usually
$emailText = "This person has registered their details \n=============================\n";
foreach ($_POST as $key => $value)
{
// If the field exists in the $fields array, include it in the email
if (isset($fields[$key]))
{
$emailText .= "$fields[$key]: $value\n";
}
}
// All the neccessary headers for the email.
$headers = [
'Content-Type: text/plain; charset="UTF-8";',
'From: ' . $from,
'Reply-To: ' . $from,
'Return-Path: ' . $from,
];
// Send email
mail($sendTo, $subject, $emailText, implode("\n", $headers));
$responseArray = ['type' => 'success', 'message' => $okMessage];
}
}
catch (\Exception $e)
{
$responseArray = ['type' => 'danger', 'message' => $e->getMessage()];
}
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
{
echo $responseArray['message'];
}
?>
Thank you very much in advance!!
Scott Geere
Personally I would do something like this:
switch ($_POST['country']):
case 'UK':
$sendTo = '<UK#emailaddress.com>';
break;
case 'US';
$sendTo = '<US#emailaddress.com>';
break;
default:
$sendTo = '<scott#emailaddress.com>';
endswitch;
Which means you could change:
// an email address that will receive the email with the output of the form
//$sendTo = '<helena#dropbox.com>,<l.stone#emeraldcolour.com>';
$sendTo = '<scott#emailaddress.com>';
To:
// an email address that will receive the email with the output of the form
//$sendTo = '<helena#dropbox.com>,<l.stone#emeraldcolour.com>';
switch ($_POST['send_to']):
case 'UK':
$sendTo = '<UK#emailaddress.com>';
break;
case 'US';
$sendTo = '<US#emailaddress.com>';
break;
default:
$sendTo = '<scott#emailaddress.com>';
endswitch;
Please do not forget: never trust the user. So do not just do stuff on $_POST data, make sure you validate the given input before you use it.
Another side note:
Instead of using this raw code in yours, you could make it a function (so you can reuse it somewhere else as well).
For example:
function getSendToEmail($country)
{
switch ($country):
case 'UK':
return '<UK#emailaddress.com>';
break;
case 'US';
return '<US#emailaddress.com>';
break;
default:
return '<scott#emailaddress.com>';
endswitch;
}
// an email address that will receive the email with the output of the form
//$sendTo = '<helena#dropbox.com>,<l.stone#emeraldcolour.com>';
$sendTo = $this->getSendToEmail($_POST['country']);
Documentation:
http://php.net/manual/en/control-structures.switch.php // Switch
http://php.net/manual/en/functions.user-defined.php // Functions
http://php.net/manual/en/filter.examples.validation.php // Validation
if (isset($_POST['country'])) {
$country = $_POST['country'];
if ($country === 'France') {
$sendTo = 'france#emailadress.com';
} elseif ($country === 'England') {
$sendTo = 'england#emailadress.com';
}
}
You can put it before the mail function.
You can also use an array like that:
$emailList = [
'France' => 'france#emailadress.com',
'England' => 'england#emailadress.com'
];
if (isset($_POST['country'])) {
// Get email from the key
$sendTo = $emailList[$_POST['country']];
}
<?php
$emparray = array();
if($_SERVER['REQUEST_METHOD'] == "POST")
{
$name = urldecode($_POST['name']);
$email = filter_var($_POST["email"],FILTER_SANITIZE_EMAIL);
$subject = urldecode($_POST['subject']);
$message = urldecode($_POST['message']);
$message_final = 'Name :-'.$name."\n".'Email Id :-'.$email."\n".'Message :-'.$message;
$to = 'xyz';
if($name!=NULL && $email!=NULL && $subject!=NULL && $message!=NULL)
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL))
{
$emparray =array(
'status' => 0, 'message' => 'Invalid Email Format');
}
else
{
$emparray= mail($to,$subject,$message_final);
$emparray =array(
'status' => 1, 'message' => 'Thank you for writing us,Email sent successfully');
}
}
else
{
$emparray =array(
'status' => 0, 'message' => 'All fields are required');
}
}
else
{
$emparray = array("status" => 0, "message" => "Request Method Not accepted");
}
echo json_encode($emparray,JSON_PRETTY_PRINT,JSON_FORCE_OBJECT);
?>
I am using postman tool for testing. If I send data using headers with key value it goes like body. How to stop this to send data with headers too.
I want if data will send from body then only it should work. If i send it from headers it should prompt me error of cant send data using headers.
Someone tells me about headers_sent function to overcome this issue. But im unable to implement it. please help me this the same.
You have to select body/raw/JSON (application/json).
Hope it works for you.
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 = {}.
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!!
// Process the forms
if (($this->getRequest()->isPost())
&& ($this->getRequest()->isXmlHttpRequest())) {
// Initiate response
$status = false;
$msg = '';
$zf = null;
// Error test
$form->getElement('no')->addError('This is the error message');
if ($form->isValid($this->getRequest()->getPost())) {
// Everything is good
$status = true;
} else {
// Get the error messages
$zf = $form->getMessages();
}
// Setup the response
$result = json_encode(array('status' => $status,
'msg' => $msg,
'zf' => $zf));
$this->_helper->viewRenderer->setNoRender();
$this->_helper->layout()->disableLayout();
$this->getResponse()->setHeader('Content-Type', 'application/json');
$this->getResponse()->setBody($result);
return;
} else {
// Populate the form
}
As you can see, I've used $form->getElement('no')->addError('This is the error message'); to force error on the form element, but $form->getMessages(); would still return NULL. So, what should I do to force error on the selected form element?
I think you've got the get the ErrorMessages()
$form->getErrorMessages()
I've opened a bug report for this issue: http://framework.zend.com/issues/browse/ZF-11088. I'll update this question if there's any new progress.