We have a site with a form that when submitted, does the following (via the code below);
Sends a test email to myself BEFORE INSERTING INTO MYSQL just so i know php mailer is working, which it always does in all my tests
Then inserts all the data from the form into MYSQL (This always works too)
Send another email via PHP Mailer with all the info they submitted. I want it in plain text (this works only about 80% of the time).
What's happening is, sometimes people submit and it does everything, but sometimes it only does steps 1 and 2. So sometimes, something seems to be breaking somewhere. I feel like it could be issues with certain punctuation, but not sure. Like in the $copy fields, people can enter whatever they want. Not sure if there are certain punctuations that could break the 2nd email process.
NOTE: Every time someone submits, it does take them to the request-success.php page. But it doesn't always send the email from Step 3.
If anyone sees areas of improvement, or things that are just wrong, please share. This is driving me insane.
<?php
session_start();
include_once("config.php");
include_once("includes/functions.php");
require 'phpmailer/PHPMailerAutoload.php';
//database configuration & connection (hiding for privacy purposes, but the database connections work fine so not relevant
if ($_POST['submit']) {
$type=$_POST['type'];
$category= substr($type, 0, strpos($type, ' -'));
$category= strtolower($category);
$category= ucfirst($category);
$need = substr($type, strpos($type, "-") + 1);
$subject="REQUEST for " . $type;
$fullname= $_SESSION['google_data']['name'];
$fromemail=$_SESSION['google_data']['email'];
$brands=$_POST['brand'];
$size=$_POST['size'];
if ($size == "") {
$size="n/a";
}
$bleed=$_POST['bleed'];
if ($bleed =="no") {
$bleedsize="n/a";
} else {
$bleedsize=$_POST['bleedsize'];
}
$filetype=$_POST['filetype'];
if ($filetype=="") {
$filetype="n/a";
}
$footerurl=$_POST['footer-url'];
if ($footerurl=="") {
$footerurl="n/a";
}
$footerphone=$_POST['footer-phone'];
if ($footerphone=="") {
$footerphone="n/a";
}
$copy=mysqli_real_escape_string($con,$_POST['copy']);
$copyforemail=$_POST['copy'];
$approved=$_POST['approved'];
$seo=$_POST['seo'];
$proofread=$_POST['proofread'];
$info=mysqli_real_escape_string($con,$_POST['info']);
$infoforemail=$_POST['info'];
$priority=$_POST['priority'];
$requestdate= date('Y-m-d');
$duedate = date('Y-m-d', strtotime(str_replace('-', '/', $_POST['duedate'])));
if ($duedate =="1969-12-31") {
$duedate="0000-00-00";
}
$timinginfo=mysqli_real_escape_string($con,$_POST['timinginfo']);
$timinginfoforemail=$_POST['timinginfo'];
$communication=mysqli_real_escape_string($con,$_POST['communication']);
$communicationforemail=$_POST['communication'];
//TEST EMAIL BEFORE INSERTING
$mail = new PHPMailer;
//$mail->SMTPDebug = 3; // Enable verbose debug output
/*
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = ''; // SMTP username
$mail->Password = ''; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
*/
$mail->setFrom($fromemail, $fullname);
$mail->addAddress('myemail#myemail.com', 'my name'); // Add recipients
$mail->addReplyTo('myemail#myemail.com', 'my name');
/*$mail->addCC('cc#example.com');
$mail->addBCC('bcc#example.com');
$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name*/
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = "Request coming for Creative Team";
$mail->Body = "Request coming";
$mail->AltBody = "Request coming";
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
//continue to insert
}
$sql = "INSERT INTO requests (firstname, lastname, email, picture, category, type, brand, size, bleed, bleedsize, filetype, footerurl, footerphone, copy, approved, proofread, seo, info, priority, requestdate, duedate, timinginfo, communication ) VALUES ('" . $_SESSION['google_data']['given_name'] . "', '" . $_SESSION['google_data']['family_name'] . "','" . $_SESSION['google_data']['email'] . "', '" . $_SESSION['google_data']['picture'] . "', '$category', '$need', '$brands', '$size', '$bleed', '$bleedsize', '$filetype', '$footerurl', '$footerphone', '$copy', '$approved', '$proofread', '$seo', '$info', '$priority', '$requestdate', '$duedate', '$timinginfo', '$communication')";
$insertinfo = mysqli_query($con, $sql);
if (!$insertinfo) {
die("Database query failed: " . mysqli_error($con));
} else {
//Success, continue to email...
}
$plaintextversion= "
$type
BRAND: $brands
SPECS
SIZE: $size
BLEED: $bleed
BLEED SIZE: $bleedsize
FILE TYPE: $filetype
FOOTER URL: $footerurl
FOOTER PHONE: $footerphone
COPY: $copyforemail
COPY APPROVED? $approved
PROOFREAD? $proofread
ADDITIONAL INFO: $infoforemail
TIMING
PRIORITY: $priority
REQUEST DATE: $requestdate
DESIRED DUE DATE: $duedate
TIMING INFO: $timinginfoforemail
COMMUNICATION
ADDITIONAL PEOPLE TO INCLUDE: $communicationforemail";
} else {
header("Location:index.php");
}
$mail = new PHPMailer;
//$mail->SMTPDebug = 3; // Enable verbose debug output
/*
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = ''; // SMTP username
$mail->Password = ''; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
*/
$mail->setFrom($fromemail, $fullname);
$mail->addAddress('someone#someone.com', 'someone'); // Add recipients
$mail->addReplyTo('myemail#myemail.com', 'my name');
/*$mail->addCC('cc#example.com');
$mail->addBCC('bcc#example.com');
$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name*/
$mail->isHTML(false); // Set email format to plain text since that is what Salesforce needs
$mail->Subject = $subject;
$mail->Body = $plaintextversion;
$mail->AltBody = $plaintextversion;
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
header("Location:request-success.php");
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<title>Untitled Document</title>
</head>
<body>
</body>
</html>
If you want plain-text only, call isHTML(false) and set only Body - don't put anything in AltBody.
There's no need to start from scratch every time - you can re-use the same PHPMailer instance and just change properties before sending for the second time.
You're using the submitters address as the From address - that's forgery, and will result in bounces from SPF failures, so put your address in From and theirs in reply-to.
As Jon says, validate, sanitize and escape anything going into SQL - it's quite likely that your failures are from submissions that contain a ', which will break your SQL.
Related
I'm using the example mailing list and trying to tailor it to work with my DB. The problem I'm having is it's only sending to one email from the list of users in the Table (the example table only has 5 users). The email is being sent to the last user listed in the table
//Passing `true` enables PHPMailer exceptions
//$mail = new PHPMailer(true);
$mail = new PHPMailer();
$body = file_get_contents('contents.html');
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->isSMTP();
$mail->Host = '####';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; //SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
$mail->Username = '###';
$mail->Password = '###';
$mail->setFrom('###', 'List manager');
$mail->addReplyTo('###', 'List manager');
$mail->Subject = 'PHPMailer Simple database mailing list test';
//Same body for all messages, so set this before the sending loop
//If you generate a different body for each recipient (e.g. you're using a templating system),
//set it inside the loop
$mail->msgHTML($body);
//msgHTML also sets AltBody, but if you want a custom one, set it afterwards
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!';
//Connect to the database and select the recipients from your mailing list that have not yet been sent to
//You'll need to alter this to match your database
$connection = mysqli_connect($server, $loginsql, $passsql, "database_name")
or die("Could not connect to database");
$result = mysqli_query($connection, 'SELECT user_login, user_email, db_prefix FROM userstest');
foreach ($result as $row) {
try {
$mail->addAddress($row['user_email'], $row['user_login']);
} catch (Exception $e) {
echo 'Invalid address skipped: ' . htmlspecialchars($row['user_email']) . '<br>';
continue;
}
try {
$mail->send();
echo 'Message sent to :' . htmlspecialchars($row['user_email']) . ' (' .
htmlspecialchars($row['user_email']) . ')<br>';
} catch (Exception $e) {
echo 'Mailer Error (' . htmlspecialchars($row['user_email']) . ') ' . $mail->ErrorInfo . '<br>';
//Reset the connection to abort sending this message
//The loop will continue trying to send to the rest of the list
$mail->getSMTPInstance()->reset();
}
//Clear all addresses and attachments for the next iteration
$mail->clearAddresses();
$mail->clearAttachments();
}
All - thanks for the help. I actually figured it out. The email address for setFrom was not the same as the account that was sending it out so it wouldn't work sending out to external domains.
I am trying to send bulk mail. And It worked but the problem is when I am checking on Gmail this shows. I can use Bcc and solve this issue but I want to for learning purposes.
------------------------------------------
from: example <example#gmail.com>
to: example1#gmail.com,
example2#gmail.com,
example2#gmail.com
date: Dec 19, 2021, 1:18 AM
subject: Testing Mail
mailed-by: example
signed-by: example
security: Standard encryption (TLS) Learn more
---------------------------------------------
In the recipient why all subscriber's mail is showing in "to". Please help me to fix it. I want to show specific subscriber mail.
Here is my code
<?php
if(isset($_POST['sendmail'])) {
$status=1;
$sql = "SELECT * FROM subscribers WHERE status=? ORDER BY id ";
$stmt = $conn2->prepare($sql);
$stmt->bind_param("s", $status);
$stmt->execute();
$result15 = $stmt->get_result();
$mail = new PHPMailer;
//$mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.example.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = EMAIL; // SMTP username
$mail->Password = PASS; // SMTP password
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465; // TCP port to connect to
if (mysqli_num_rows($result15)>0) {
while ($row = mysqli_fetch_array($result15)) {
$mail->AddAddress($row['email']); // Add a recipient
}
}
$mail->setFrom(EMAIL, 'example');
//$mail->addReplyTo(NOREPLY);
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $_POST['subject'];
$mail->Body = '<div style="border:2px solid red;">This is the HTML message body <b>in bold!</b></div>';
$mail->AltBody = $_POST['message'];
if (!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}
}
?>
When I try to submit the completed form it must redirect me to a success page to indicate that the email has been sent successfully. But unfortunately, this appears and the email doesn't come
image site
This is the code
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailer-master/src/Exception.php';
require 'PHPMailer-master/src/PHPMailer.php';
require 'PHPMailer-master/src/SMTP.php';
// Instantiation and passing [ICODE]true[/ICODE] enables exceptions
$mail = new PHPMailer(true);
try {
function get_ip() {
if(isset($_SERVER['HTTP_CLIENT_IP'])) {
return $_SERVER['HTTP_CLIENT_IP'];
}
elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
else {
return (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
}
}
//Server settings
$ip=get_ip();
$query=#unserialize(file_get_contents('http://ip-api.com/php/'.$ip));
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isMail(); // Set mailer to use SMTP
$mail->Host = 'smtp.office365.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = '//'; // SMTP username
$mail->Password = '///'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, [ICODE]ssl[/ICODE] also accepted
$mail->Port = 587; // TCP port to connect to
$ips=$_SERVER['REMOTE_ADDR'];
$name = $_POST['name'];
$email = $_POST['email'];
$mobile = $_POST['mobile'];
$landline = $_POST['landline'];
$date = $_POST['date'];
$people = $_POST['people'];
$lunch = $_POST['lunch'];
$enquiry = $_POST['enquiry'];
$questions = $_POST['questions'];
//Recipients
$mail->setFrom($email, $name);
$mail->addAddress('bookings#rios.com.au', 'Rios bookings'); // Name is optional
$mail->addAddress($email, $name); // Add a recipient
$mail->addReplyTo('bookings#rios.com.au', 'Information from customer');
// $mail->addCC('cc#example.com');
// $mail->addBCC('bcc#example.com');
// // Attachments
// $mail->addAttachment('/home/cpanelusername/attachment.txt'); // Add attachments
// $mail->addAttachment('/home/cpanelusername/image.jpg', 'new.jpg'); // Optional name
// Content
// $mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Rio E-mail from Website / Contact Us Form';
$mail->Body = "
New Message from Rio Contact Form
Name: {$name}
Email: {$email}
Mobile: {$mobile}
Landline: {$landline}
Date: {$date}
People: {$people}
Lunch or Dinner: {$lunch}
Enquiry or booking: {$enquiry}
Questions: {$questions}
{$ips} {$query['city']} {$query['regionName']} {$query['zip']} {$query['timezone']}
";
header('location:success.html');
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
This is how I have organized the files
files
....................................................................................
This is not a good pattern:
header('location:success.html');
$mail->send();
echo 'Message has been sent';
You don't know that sending has succeeded until after calling send(), and any content you output after setting the header will either be lost (because it redirects away before it can be seen), or it will prevent the redirect from happening (because content is already sent). This should be enough, in this order:
$mail->send();
header('location:success.html');
exit; //Do nothing else after issuing the redirect
Strictly speaking, redirects should use absolute URLs, so perhaps add that into the destination address.
You're also doing this:
$email = $_POST['email'];
...
$mail->setFrom($email, $name);
That's forgery and will probably end up getting your message blocked, bounced, or spam filtered. Do this instead:
$mail->setFrom('bookings#rios.com.au', $name);
$mail->addAddress('bookings#rios.com.au', 'Rios bookings');
$mail->addReplyTo($email, $name);
This way the message is sent from you, to you, but replies will go to the submitter's address.
One other tip — learn how to use composer.
I am having issues with mail NOT going to all email addresses sometimes. I have been testing from a web-app I built and it is hosted with GoDaddy with "Deluxe" shared hosting level.
Is it possible that I have upset the GoDaddy Email Server gods by submitting too many test email sends??
Is it possible that my emails are being blocked because the servers think my multiple tests are spam? I do receive SOME of the emails....
// Import PHPMailer classes into the global namespace
// These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader
require 'vendor/autoload.php';
$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
// Server settings
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'xxxxxxxxxxxx.prod.phx3.secureserver.net'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'cpanelusername'; // SMTP username
$mail->Password = 'cpanelpassword'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
// Recipients - Names are optional - $mail->setFrom('xxxxxxxxxx#cox.net', 'Peter Henry Lee');
$mail->setFrom('xxxxxxxxxx#cox.net'); // From Address
$mail->addAddress('xxxxxxxxxx#cox.net'); // Recipient 1
$mail->addAddress('xxxxx#cox.net'); // Recipient 2
$mail->addCC('xxxxxxx#cox.net'); // Cc 1 Address
$mail->addCC('xxxxxxxx#cox.net'); // Cc 2 Address
$mail->addBCC('xxxxxxxxx#xxxxesigns.com'); // Bcc Address
// $mail->addReplyTo('xxxxxxxxx#xxxxesigns.com'); // Reply-To Address
// Attachments
include 'retrieve_order.php'; // Retrieves PDF
$mail->addAttachment('receipts/' . $newname); // Adds PDF attachment
// $mail->addAttachment('img/puppy2.png', 'Puppy is cute!'); // Adds Image attachment with optional name
// Content
$newname = substr($newname, 0, 11);
$l = $newname;
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the TEST ' . $l . ' subject line';
$mail->Body = 'This is the TEST ' . $l . ' HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the TEST ' . $l . ' body in plain text for non-HTML mail clients';
// Send mail
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
}
I have a foreach loop from which i am sending emails for my customers.
I have 4 customers in my db 1,2,3,4
So according to foreach loop the loop will run for 4 times to send an email to every customer
But in 1st run it sends email to customer 1.
In 2nd run It is sending email to customer 1 and 2.
In thirdd run it is sending email to customer 1,2,3 and so on.
How can i make to send one email to one customer.
here is my code.
$list=$tmp_con->query("SELECT name,email FROM users WHERE user_type='$tp' AND subscribed='yes' AND verified='1'") or die($tmp_con->error);
$lis=array();
while($row=$list->fetch_array()){
$lis[] = $row;
}
foreach($lis as $lst){
$content = str_replace("{name}", $lst['name'], $mail_content);
$content=$content."".$append_unsub;
/**************************************************phpmailer class***********************/
//$mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = $mail_smtp_host; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = $mail_smtp_username; // SMTP username
$mail->Password = $mail_smtp_password; // SMTP password
$mail->SMTPSecure = $mail_smtp_enc; // Enable TLS encryption, `ssl` also accepted
$mail->Port = $mail_smtp_port; // TCP port to connect to
$mail->setFrom($mail_smtp_from_email, $mail_smtp_from_name);
$mail->addAddress($lst['email']); // Add a recipient
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $mail_subject;
$mail->Body = $content;
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}
$lst['email']='';
/*************************************************php mailer ends here*************************************/
} ///foreach ends here
Create a new $mail object in the loop or even better reset the addresses in the loop. You've (probably) declared the $mail object outside the for loop.
So every time you call addAddress you're adding the email address of the user. The first time you're setting the email address of the first user, then the second time you're adding the email address to the list, so two email addresses. Third round the same, fourth round etc..
Edit: Creating $mail inside the loop fixes the problem, but isn't efficient. See Synchro's comment for a better way to create and send the email.
No need of creating an instance of PHPMailer in each and every loop. Use $mail->clearAddresses(); at the end of foreach loop to clear all the addresses.
Updated Code
$list = $tmp_con->query("SELECT name,email FROM users WHERE user_type='$tp' AND subscribed='yes' AND verified='1'") or die($tmp_con->error);
$lis = array();
while ($row = $list->fetch_array()) {
$lis[] = $row;
}
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = $mail_smtp_host; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = $mail_smtp_username; // SMTP username
$mail->Password = $mail_smtp_password; // SMTP password
$mail->SMTPSecure = $mail_smtp_enc; // Enable TLS encryption, `ssl` also accepted
$mail->Port = $mail_smtp_port; // TCP port to connect to
$mail->setFrom($mail_smtp_from_email, $mail_smtp_from_name);
foreach ($lis as $lst) {
$content = str_replace("{name}", $lst['name'], $mail_content);
$content = $content . "" . $append_unsub;
//$mail->SMTPDebug = 3;
$mail->addAddress($lst['email']); // Add a recipient
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $mail_subject;
$mail->Body = $content;
if (!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}
$mail->clearAddresses(); // Clear all addresses for next loop
}
References:
PHPMailer