I'm trying to use phpmailer to send out emails to each email address found in the database, but as a unique email. For some reason, it's sending duplicate emails, and it sends it out in as many copies as my query returns rows. So, if my query returns 5 rows, each recipient will receive 5 email (total emails sent is 25). I can't use the same email for multiple recipients because the email content is personalized.
What am I doing wrong with my code? Please help...
Here's my code:
$customers_query = "SELECT customer_name, customer_email, customer_id FROM customers";
$customers = mysql_query($customers_query);
if (!$customers) {
$message = 'Error notice: ' . mysql_error() . "\n";
$message .= 'Whole query: ' . $query;
die($message);
}
require_once('class.phpmailer.php');
// create an instance
while ($row = mysql_fetch_array($customers)) {
$email = $row['customer_email'];
$name = $row['customers_name'];
$id = $row['customer_id'];
$mail = new PHPMailer();
// use sendmail for the mailer
$mail->IsSendmail();
$mail->SingleTo = true;
$mail->IsHTML(true);
$mail->From = "noreply#domain.com";
$mail->FromName = "MyWebsite";
$mail->Subject = "Welcome to MyWebsite";
$mail->AddAddress($email);
$mail->Body = "Dear ".$name.", welcome to MyWebsite. Your ID is: ".$id.". Enjoy your stay.";
$mail->Send();
}
So, what am missing here? Why does it send that many emails?
Try this:
$mail->ClearAddresses(); after $mail->Send();
Try something like is below, you need to be counting your rows somehow so that it doesn't re-process them. Also, the AddAddress(); function is used to keep adding email addresses to the TO: field, so you need to call ClearAddresses(); in order to restart with a fresh set of recipients.
$customers_query = "SELECT customer_name, customer_email, customer_id FROM customers";
$customers = mysql_query($customers_query);
$count = mysql_num_rows($customers);
$result = mysql_fetch_array($customers);
$i = 0;
if (!$customers) {
$message = 'Error notice: ' . mysql_error() . "\n";
$message .= 'Whole query: ' . $query;
die($message);
}
require_once('class.phpmailer.php');
// create an instance
while ($i < $count) {
$email = mysql_result($result,$i,"customer_email");
$name = mysql_result($result,$i,"customers_name");
$id = mysql_result($result,$i,"customer_id");
$mail = new PHPMailer();
// use sendmail for the mailer
$mail->IsSendmail();
$mail->SingleTo = true;
$mail->IsHTML(true);
$mail->From = "noreply#domain.com";
$mail->FromName = "MyWebsite";
$mail->Subject = "Welcome to MyWebsite";
$mail->AddAddress($email);
$mail->Body = "Dear ".$name.", welcome to MyWebsite. Your ID is: ".$id.". Enjoy your stay.";
$mail->Send();
$mail->ClearAddresses();
$i++;
}
You can do one more thing, add one more extra field in the customer table, like is_email_sent, yes or no. Once sent email you can update specific row using primary key. so it will not send the same email to multiple time..
Related
I've been trying many different ways to prevent PHP Mailer from appending every email address coming from my DB to every single email.
I feel it doesn't look right for every user to receive an email from my website and being able to see a few other thousand emails appended to that same email as well.
Here's my code, I already tried to many diferent things:
$query_select = "SELECT * FROM users";
$query = mysqli_query($connection, $query_select);
if($select_to == 'all'){
while($row = mysqli_fetch_assoc($query)) {
$user_email = $row['user_email'];
$send_to = $user_email;
$mail->setFrom('example#gmail.com', 'My website');
$mail->addAddress($send_to);
$mail->isHTML(true);
$mail->Subject = $subject_email;
$mail->Body = $content_email;
$mail->AltBody = $content_email;
}
} else {
if($select_to == 'single'){
$send_to = $to_single_email;
}
}
if($mail->send()){
$confirm = 'Sent.';
$send = array(
'confirm'=>$confirm
);
echo json_encode($send);
} else {
$confirm = 'There was en error while sending this email.';
$send = array(
'confirm'=>$confirm
);
echo json_encode($send);
}
$mail->send() will send to all addresses via a single message. Instead you need to send one message per recipient.
The while() loop would be refactored similar to:
while($row = mysqli_fetch_assoc($query)) {
$user_email = $row['user_email'];
$send_to = $user_email;
$mail->setFrom('example#gmail.com', 'My website');
$mail->addAddress($send_to);
$mail->isHTML(true);
$mail->Subject = $subject_email;
$mail->Body = $content_email;
$mail->AltBody = $content_email;
$mail->send();
$mail->clearAllRecipients();
}
The call to clearAllRecipients() will clear out the previous addresses that would otherwise accumulate via addAddress()
You'll also need to add the error checking within the loop for each call of send()
I'm trying to send an email update to users from the candidates_table but the content of the email comes from the jobs_list table. Please see my attempt below, I'm using PHPmailer and I'm getting no errors. The script below is the handling script for a form.
The data from the jobs_list is being displayed, however, the candidates_table data is not.
This is just below the insert statement:
UPDATE:
$vac_last_id = $dbh->lastInsertId();
echo $vac_last_id;
$sql = $dbh->prepare("SELECT * FROM jobs_list WHERE id=:id");
$sql->bindValue(':id', $vac_last_id, PDO::PARAM_INT);
if($sql->execute()) {
$sql->setFetchMode(PDO::FETCH_ASSOC);
}
while($row = $sql->fetch()) {
$mail = new PHPMailer;
$mail->isSMTP();
$mail->Host = '';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->Port =;
$mail->Username = '';
$mail->Password = '';
$mail->setFrom('', '- Vacancies');
$mail->addReplyTo('', '- Vacancies');
$mail->Subject = "";
//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->Body = 'THE 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
$mysql = $dbh->prepare("SELECT * FROM candidates_table WHERE receive_email = 2");
if ($mysql->execute()) {
$mysql->setFetchMode(PDO::FETCH_ASSOC);
}
foreach ($mysql as $row) { //This iterator syntax only works in PHP 5.4+
$mail->addAddress($row['email_address'], $row['full_name']);
if (!$mail->send()) {
echo "Mailer Error (" . str_replace("#", "#", $row["email_address"]) . ') ' . $mail->ErrorInfo . '<br />';
break; //Abandon sending
} else {
echo "Message sent to :" . $row['full_name'] . ' (' . str_replace("#", "#", $row['email_address']) . ')<br />';
//Mark it as sent in the DB
}
// Clear all addresses and attachments for next loop
$mail->clearAddresses();
}
}
Insert Job List in job_listing table. Find, current job_listing table id. Fetch it again and find all candidates to send email.
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
require 'PHPMailer/PHPMailerAutoload.php';
include 'db_connect.php';
$contact_name = $_POST['contact_name'];
$latest_job_id = 0;
$stmt = $dbh->prepare("INSERT INTO jobs_list (jobTitle, company_name, job_details, salary_info, salary_extra, apply_link, company_email, company_phone, TimeStamp) VALUES (:jobTitle, :company_name, :job_details, :salary_info, :salary_extra, :apply_link, :company_email, :company_phone, NOW())");
$stmt->bindParam(':jobTitle', $_POST['jobTitle'], PDO::PARAM_STR);
$stmt->bindParam(':company_name', $_POST['company_name'], PDO::PARAM_STR);
$stmt->bindParam(':job_details', $_POST['job_details'], PDO::PARAM_STR);
$stmt->bindParam(':salary_info', $_POST['salary_info'], PDO::PARAM_STR);
$stmt->bindParam(':salary_extra', $_POST['salary_extra'], PDO::PARAM_STR);
$stmt->bindParam(':apply_link', $_POST['apply_link'], PDO::PARAM_STR);
$stmt->bindParam(':company_email', $_POST['company_email'], PDO::PARAM_STR);
$stmt->bindParam(':company_phone', $_POST['company_phone'], PDO::PARAM_STR);
$stmt->execute();
$latest_job_id = $dbh->lastInsertId(); //#Nana Comments: Get latest Job Listing ID
if($latest_job_id > 0){
/*#Nana Comments: If Inserted Successfully, '$latest_job_id' will be greater than 0.*/
$mail_error_text = ""; //#Nana Comments: If email not sent, then it will store the email address
/*#Nana Comments: Select recent job listing details.*/
$sql = $dbh->prepare("SELECT * FROM jobs_list WHERE id = :id LIMIT 0, 1");
$sql->bindParam(':id', $latest_job_id);
if ($sql->execute()) {
$sql->setFetchMode(PDO::FETCH_ASSOC);
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = ''; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = ''; // SMTP username
$mail->Password = ''; // SMTP password
$mail->SMTPSecure = ''; // Enable TLS encryption, `ssl` also accepted
$mail->Port = ''; // TCP port to connect to
$mail->setFrom('', 'sender');
while ($row = $sql->fetch()) {
$new_company_email = trim($row['company_email']);
$new_company_name = trim($row['company_name']);
/*#Nana Comments: Select all candidates and send email */
$load_candidate = $dbh->prepare("SELECT * FROM candidates_table");
if ($load_candidate->execute()) {
$load_candidate->setFetchMode(PDO::FETCH_ASSOC);
while ($row = $load_candidate->fetch()) {
$mail->addAddress($row['email_address']); // Add a recipient
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'New Vacancy';
$mail->Body = 'mail body in here';
$mail->AltBody = '';
if(!$mail->send()){
$mail_error_text .= "Mailer Error (" . str_replace("#", "#", $row["email_address"]) . ') ' . $mail->ErrorInfo . '<br />';
}
$mail->clearAddresses(); // Clear all addresses for next loop
$mail->clearAttachments(); // Clear all attachments for next loop
}
}
}
}
if($mail_error_text != ""){
echo "<b>Email not sent to:</b><br>".$mail_error_text;
}
} else {
echo "Job Listing Insertion Fails";
}
} else {
echo "access denied";
}?>
I'm using PHPMailer to send an email from a form to all the emails in a MySQL database.
I've managed to get the form to send an email to each email but I'm now trying to use their name in the email sent to them meaning each email woud begin with "Hello, [their-name],".
I'm using an array to loop through the results of my database query and adding each email and name as $mail->addAddress('email#email.com, 'name');
I've tried saving the variable $name = $row['name'}; inside the while loop but it inputs the last name from the database into all the emails.
My question is: Is it possible to access the 'name' part of the function and use it each email. Or is it better to take their name from the database itself? And if so how would I go about doing that?
Also, when the email sends to each recipient, it shows all of the recipients in the "To:" field. This would be pretty bad for privacy. Is there a way to prevent this?
I'm fairly new to PHP and MySQL still so explanatory answers would be greatly appreciated.
Please find my code below.
<?php
// Take message value from form
$message = preg_replace("/\r\n|\r/", "<br />", $_REQUEST['message']);
$message = trim($message);
// Error reporting on
error_reporting(E_STRICT | E_ALL);
date_default_timezone_set('Etc/UTC');
// Require PHPMailer
require 'PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->Port = 587;
$mail->Username = 'my#email.com';
$mail->Password = 'mypassword';
$mail->setFrom('myemail#email.com', 'Me');
$mail->addReplyTo('myemail#email.com', 'Me');
$mail->Subject = "Newsletter";
/* ----- Add address function below ----- */
// Require Database connection
require 'dbcon.php';
// SELECT email and name values from database
$query = "SELECT email, name FROM customers";
// Result = the database query
$result = $con->query($query);
// Get array of users email addresses and names.
while($row = $result->fetch_array())
{
// Add recipients from values found in database
$mail->addAddress($row["email"], $row["name"]);
}
/* ----- Add address function above ----- */
$mail->Body ="Hello, <br> <br> $message";
$mail->AltBody = $message;
if(!$mail->Send())
{
echo "Message could not be sent.";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
print 'Sent!';
?>
You are currently setting up to send a single email with several recipients. For security and etiquette, you should address the email to yourself (outside the loop):
$mail->addAddress('myemail#email.com', 'Me');
...and then add all of the recipients as BCC (inside the loop):
$mail->addBCC($row["email"], $row["name"]);
As for the name field. Add a debug line inside your loop and take a look at your output. Is the name field the same each time?
print "Adding recipient: {$row['email']} {$row['name']}";
If you want to sent several emails, one to each recipient, you need to instantiate a new email inside the loop each time.
[UPDATE]
If you want to send a single message to each recipient, then instantiate a new email each time (inside your loop):
<?php
// Take message value from form
$message = preg_replace("/\r\n|\r/", "<br />", $_REQUEST['message']);
$message = trim($message);
// Error reporting on
error_reporting(E_STRICT | E_ALL);
date_default_timezone_set('Etc/UTC');
// Require PHPMailer
require 'PHPMailer/PHPMailerAutoload.php';
// Require Database connection
require 'dbcon.php';
// SELECT email and name values from database
$query = "SELECT email, name FROM customers";
// Result = the database query
$result = $con->query($query);
// Get array of users email addresses and names.
while($row = $result->fetch_array())
{
// Instantiate a NEW email
$mail = new PHPMailer;
// Set the email settings
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->Port = 587;
$mail->Username = 'my#email.com';
$mail->Password = 'mypassword';
$mail->setFrom('myemail#email.com', 'Me');
$mail->addReplyTo('myemail#email.com', 'Me');
$mail->Subject = "Newsletter";
// Add recipient from values found in database
$mail->addAddress($row["email"], $row["name"]);
$mail->Body ="Hello, <br> <br> $message";
$mail->AltBody = $message;
if(!$mail->Send())
{
echo "Message could not be sent.";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
print "Sent mail to: {$row["email"]}, {$row["name"]}";
}
?>
I'm trying to send an email to multiple recipients using phpmailer and getting the emails list from my table in the database, however, whenever I make a request only one recipient, the first one on the list gets the email. *I know this might be marked as duplicate but I couldn't find a similar example using mysql
<?php
if (isset($_POST['submit'])) {
if (empty($errors)) {
$thisType = mysql_prep($_POST["partner_type"]);
$content = $_POST["content"];
$header = $_POST["header"];
$query = "SELECT * FROM partners_list WHERE partner_type = '$thisType' ";
$result = mysqli_query($connection, $query);
$count = mysqli_num_rows($result);
while($row = mysqli_fetch_assoc($result)){
require_once("phpMailer/class.phpmailer.php");
require_once("phpMailer/class.smtp.php");
require_once("phpMailer/language/phpmailer.lang-uk.php");
$to_name = "Order";
$subject = $header;
$message = $content;
$message = wordwrap($message,70);
$from_name = "thisCompany";
$from = "noreply#thicCompany.com";
$mail = new PHPMailer();
$mail->AddAddress($row['email'], "Test Message"); // add each DB entry to list of recipients
$mail->FromName = $from_name;
$mail->From = $from;
$mail->Subject = $subject;
$mail->Body = $message;
$result = $mail->Send();
// Success
$_SESSION["message"] = "e-mail successfully sent.";
redirect_to("successpage.php");
}
}
} else {
}
?>
I have been using the following to get and email people in my database. The problem is now that the database has over 500+ members the script slows down and SHOWS each member email address in TO: field. I tried a suggestion on another site to use BCC instead but I was wondering isn't there a way to alter this to send the emails individually?
$sql = "SELECT * FROM users WHERE system = '101' AND mailing_list = 'yes'";
$result = mysql_query($sql) or die("Unable to execute<br />$sql<br />".mysql_error());
$row = mysql_fetch_array($result);
var_dump($row);
$to .= $row['email'] . "\r\n";
//send email
php's mail() is very inefficient, I suggest using something like phpmailer
from the manual:
Note:
It is worth noting that the mail() function is not suitable for larger
volumes of email in a loop. This function opens and closes an SMTP
socket for each email, which is not very efficient.
For the sending of large amounts of email, see the » PEAR::Mail, and »
PEAR::Mail_Queue packages.
You need to use PHPMailer as it is meant to be used for just this situation. the trouble with mail() is that it opens and closes a connection after each email. You obviously want to open 1 connection, send all your emails (one by one) and close the connection.
Something like below:
require("class.phpmailer.php");
$mail = new phpmailer();
$mail->From = "list#example.com";
$mail->FromName = "List manager";
$mail->Host = "smtp1.example.com;smtp2.example.com";
$mail->Mailer = "smtp";
#MYSQL_CONNECT("localhost","root","password");
#mysql_select_db("my_company");
$query = "SELECT full_name, email, photo FROM employee WHERE id=$id";
$result = #MYSQL_QUERY($query);
while ($row = mysql_fetch_array ($result))
{
// HTML body
$body = "Hello <font size=\"4\">" . $row["full_name"] . "</font>, <p>";
$body .= "<i>Your</i> personal photograph to this message.<p>";
$body .= "Sincerely, <br>";
$body .= "phpmailer List manager";
// Plain text body (for mail clients that cannot read HTML)
$text_body = "Hello " . $row["full_name"] . ", \n\n";
$text_body .= "Your personal photograph to this message.\n\n";
$text_body .= "Sincerely, \n";
$text_body .= "phpmailer List manager";
$mail->Body = $body;
$mail->AltBody = $text_body;
$mail->AddAddress($row["email"], $row["full_name"]);
$mail->AddStringAttachment($row["photo"], "YourPhoto.jpg");
if(!$mail->Send())
echo "There has been a mail error sending to " . $row["email"] . "<br>";
// Clear all addresses and attachments for next loop
$mail->ClearAddresses();
$mail->ClearAttachments();
}