ForEach loop values keeping previous values - php

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

Related

phpmailer loop duplicated email addresses (and possible message) in loop

I have the following code sending email shipping confirmations to my customers:
while ($i < count($tracked) ) {
try {
//Server settings
//$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = 'smtp.office365.com'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'support#mycompany.com'; // SMTP username
$mail->Password = 'password'; // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
$mail->Port = 587; // TCP port to connect to
//Recipients
$mail->setFrom('support#mycompany.com', 'mycompany');
$mail->addAddress($tracked[$i]['customers_email_address'], $tracked[$i]['customers_name']); // Add a recipient
$mail->addReplyTo('support#mycompany.com', 'mycompany');
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = EMAIL_TEXT_SUBJECT;
$mail->Body = $html;
$mail->AltBody = 'Your order with mycompany.com has shipped';
$mail->send();
echo 'order confirmation sent to order#:'.$tracked[$i]['orders_id'].'<br/>';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
$i++;
}
It appears to be sending to multiple emails. What I believe is happening is that in the while loop each new customers address is added to the list without clearing it. What doesnt seem to be happening though is the message does not seem to be duplicated? Wouldn't that duplicate at as well with each pass in the loop?
In any case I think the best thing to do before the try is:
$mail = new PHPMailer(true);
so that with each pass of the while loop the $mail object would be instantiated again. Is that proper? I know that the clearAllRecipients() function exists but i also want to be sure the body is cleaned as well.
it looks like your looping through an array of $tracked. Why not use a foreach loop? Then you don't need to use a counter.
foreach ($tracked as $track ) {
try {
//Server settings
//$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = 'smtp.office365.com'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'support#mycompany.com'; // SMTP username
$mail->Password = 'password'; // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
$mail->Port = 587; // TCP port to connect to
//Recipients
$mail->setFrom('support#mycompany.com', 'mycompany');
$mail->addAddress($track['customers_email_address'], $track['customers_name']); // Add a recipient
$mail->addReplyTo('support#mycompany.com', 'mycompany');
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = EMAIL_TEXT_SUBJECT;
$mail->Body = $html;
$mail->AltBody = 'Your order with mycompany.com has shipped';
$mail->send();
echo 'order confirmation sent to order#:'.$track['orders_id'].'<br/>';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}
It's because addAddress() does exactly what its name suggests; it adds an address that a message will be sent to. It doesn't set the addresses a message will be sent to.
Unsurprisingly there is a method that allows you to clear the list of addresses, called clearAddresses(), so just call that at the end of your sending loop after send() and your issue will be solved.
I'd also recommend that you base your code on the mailing list example provided with PHPMailer as it will be much faster than the code you have here. Also read the docs on sending to listshttps://github.com/PHPMailer/PHPMailer/wiki/Sending-to-lists) for furtehr advice.

php auto mailer addAddress

I want to send otp mail to user by fetching email value from database . I am using php auto mailer . It works when i use mail address directly but when i retrieve it from database i cant send it . Can anyone please help me with sending it .
function mailit()
{
$rand=rand(100000,999999);
$user=$_SESSION['user'];
$sql=mysqli_query($db,"UPDATE `doctor_login` SET `otp`='$rand' WHERE `doctor_id`='1'");
$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 = 'myusername '; // SMTP username
$mail->Password = 'mypassword'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587 ; // TCP port to connect to
$mail->setFrom('dont_reply_back#example.xyz');
$mail->addAddress('$row'); // Add a recipient
$mail->addReplyTo('dont_reply_back#example.xyz');
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'THis is your OTP';
$mail->Body = 'Your otp is '.$rand;
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
}
}
Code for retrieving and displaying of email
$mailadd=mysqli_query($db,"SELECT `doctor_email` FROM `doctor_login` WHERE `doctor_id`='1'");
$row = mysqli_fetch_array($mailadd,MYSQLI_ASSOC);
echo $row['doctor_email'];
$row2=$rowa['doctor_email'];
echo $row2;
i have used both $row and $row2 in $mail->addAddress but doesnt seem to work . What changes can i do . it works whwn i give a specific address
I think this is a scope issue. If you are calling this code in the main body of the code
$mailadd=mysqli_query($db,"SELECT `doctor_email`
FROM `doctor_login`
WHERE `doctor_id`='1'");
$row = mysqli_fetch_array($mailadd,MYSQLI_ASSOC);
Then I assume you call mailit() after this, so pass the data you want to use as a parameter to the mailit() function so it is available inside the function scope.
function mailit($row)
{
$rand=rand(100000,999999);
$user=$_SESSION['user'];
$sql=mysqli_query($db,"UPDATE `doctor_login` SET `otp`='$rand' WHERE `doctor_id`='1'");
$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 = 'myusername '; // SMTP username
$mail->Password = 'mypassword'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587 ; // TCP port to connect to
$mail->setFrom('dont_reply_back#example.xyz');
$mail->addAddress($row['doctor_email']); // Add a recipient
$mail->addReplyTo('dont_reply_back#example.xyz');
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'THis is your OTP';
$mail->Body = 'Your otp is '.$rand;
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
}
}
$mailadd=mysqli_query($db,"SELECT `doctor_email`
FROM `doctor_login`
WHERE `doctor_id`='1'");
$row = mysqli_fetch_array($mailadd,MYSQLI_ASSOC);
mailit($row);
You should have been getting errors from your original code so in future add the following:
ini_set('display_errors', 1);
ini_set('log_errors',1);
error_reporting(E_ALL);
// if you are using the `mysqli` API
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
to the top of your script. This will force any mysqli_ errors to generate an Exception that you can see on the browser as well as normal PHP errors.

PHPMailer does not return error but only sends 6 emails instead of 24

My PHPMailer seems to work, but loops through the mailer only 6 times instead of 24 times. if loop used without mailer, it does return 24 addresses. I'm connected to an internal network with access from outside. can anyone clear up what is going on. ($link -> close()) is done at a later stage. also the 24 emails sent two 2 different email accounts(for testing purposes), both receive 3 emails from this phpMailer. found many posts regarding phpMailer, I haven't encountered this one so far.
if ($result = $link->query("SELECT Adres FROM Emails")) {
//Alle variabelen voor de mail
$mail = new PHPMailer;
//$mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->SMTPKeepAlive = true;
$mail->Host = 'smtp-mail.outlook.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = '**********#outlook.com'; // 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('**********#outlook.com');
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'APP';
$mail->Body = 'is this working??';
$mail->AltBody = 'is this working??';
while($row = mysqli_fetch_row($result)) {
$variable = $row[0];
$mail->addAddress($variable);
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}
$mail->ClearAllRecipients( );
}
$result->close();
}
You're not checking that addAddress succeeds, for example if the email addresses are invalid. If you set SMTPDebug = 2, you can watch the SMTP conversation.
Check addresses like this:
$variable = $row[0];
if (!$mail->addAddress($variable)) {
echo "skipping invalid address $variable";
continue;
}

PhpMailer, ClearAddresses() won't work, message get sent to everyone

I am trying to send different messages to different users. I made an array of email addresses and while iterating through it, I want to send message2 to user2.
While reusing the same mail instance, at the beginning of each iteration I declare $mail -> ClearAddresses(), but now user2 gets the message of user1, and user2... and so one.
What am I missing that the Address won't get cleared at the beginning of the iteration?
Thanks!
// settings
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'xxx'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'xxx'; // SMTP username
$mail->Password = 'xxx'; // SMTP password
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465;
$mail->CharSet = "UTF-8"; // TCP port to connect to
function sendInvoice($mail, $addresses) {
foreach($addresses as $recipient) {
$mail->ClearAddresses();
$mail->setFrom('mail#domain.eu', 'My Server');
$mail->addAddress($recipient['email'], $recipient['name']); // Add a recipient
$mail->addReplyTo('mail#domain.eu', 'My Server');
$mail->isHTML(true);
$mail->Subject = $recipient[subject];
//$mail->Body = $message;
$mail->MsgHTML($recipient[message]);
if (! $mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
//echo 'Message has been sent';
}
}
}
In your code, change:
$mail->ClearAddresses();
to:
$mail->ClearAllRecipients();
This should fix the problem.

PHPMailer: Mass Emails - Send all variable messages at once, instead of individually

i'm currently trying to figure out the best way to do this.
The current system i've made sends email one by one and fills in the information for each entry as in the array, such as email, first name and last name.
The problem here is if i send alot of messages it takes forever to run through as it's calling a function everytime, instead i want it to send them all at once through one single function.
I know you can add multiple to's but then the body of the email won't send the correct information relative to each email. If anyone can help me with this i'd really appreciate it, as i've searched all over for a solution.
<?php
require '../phpmailer/PHPMailerAutoload.php';?>
<?php
/* Block List */
$blocklist = array('emailblocked#gmail.com', 'emailblocked2#gmail.com');
$emaillist = array(
array(
'Email'=>'example#gmail.com',
'First Name'=>'John',
'Last Name'=>'Doe'
),
array(
'Email'=>'example2#gmail.com',
'First Name'=>'Joe',
'Last Name'=>'Doe'
),
array(
'Email'=>'example3#gmail.com',
'First Name'=>'Jane',
'Last Name'=>'Doe'
),
);
foreach($emaillist as $emailkey){
if (in_array($emailkey['Email'], $blocklist)) {
echo 'Message has been been blocked for '.$emailkey['Email'].'<br>';
}else{
$mail = new PHPMailer;
// $mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.mandrillapp.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'username#example.com'; // SMTP username
$mail->Password = 'passwordgoeshere'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
$mail->From = 'noreply#example.com';
$mail->FromName = 'Example';
$mail->addAddress($emailkey['Email'], $emailkey['First Name'].' '.$emailkey['Last Name']); // Add a recipient
$mail->addReplyTo('info#example.com', 'Information');
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $emailkey['First Name'].' '.$emailkey['Last Name'];
$emailtemp = file_get_contents('templates/temp-1.html');
$emailtempfilteremail = str_replace("[[email]]", $emailkey['Email'], $emailtemp);
$emailtempfilterfirstname = str_replace("[[firstname]]", $emailkey['First Name'], $emailtempfilteremail);
$emailtempfilterlastname = str_replace("[[lastname]]", $emailkey['Last Name'], $emailtempfilterfirstname);
$mail->Body = $emailtempfilterlastname;
$mail->AltBody = 'This is a spicy email!';
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent to '.$emailkey['Email'].'<br>';
}
$mail->ClearAllRecipients();
}
}
?>
Thank you
There's an example of how to send to a list from a database efficiently in the examples bundled with PHPMailer. There's nothing inherently likely to get you blacklisted by using PHPMailer for sending large volumes, but you do need to tread carefully. Mandrill isn't magic - it's as vulnerable as anything else to being blocked if you send spam through it.
If you want to send 50 simultaneously from PHP, fire up multiple processes with the pcntl extension, but it won't actually help you very much as you'll be increasing overhead enormously. You can set SMTPKeepAlive = true in PHPMailer which will reduce overhead a lot (it avoids making a new connection for every message), but it still won't send simultaneous messages - nothing will. There isn't an option in SMTP to send multiple messages with different bodies simultaneously on the same connection.
Sending to a big list during a page load in a browser is very unreliable; use a cron script or background process to do your actual sending and just set it up through your web interface. One tip if you are waiting for a page load - call ignore_user_abort() early on so that it won't stop sending if your browser closes the connection - and beware the page refresh! If you want to send much faster, install a local mail server like postfix and use that to relay - it will be far faster and more reliable than sending directly.
Yes, it is possible with a modification of your code, the problem is not with the PHPMailer itself, but with your approach. You should avoid using an new instance of the class inside a loop (this leads to memory exhaustion with large lists), instead, only invoke $mail->addAddress(...) or $mail->Subject(...) inside the foreach loop.
If you read the source code of the PHPMailer, you will notice how exactly the functions addAddress(), Subject() or Body() works.
Your code should look something like this:
<?php
/*Move your "generic" initialization outside the loop*/
$mail = new PHPMailer;
// $mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.mandrillapp.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'username#example.com'; // SMTP username
$mail->Password = 'passwordgoeshere'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
$mail->From = 'noreply#example.com';
$mail->FromName = 'Bet Monkey';
$mail->isHTML(true); // Set email format to HTML
$mail->addReplyTo('info#example.com', 'Information');
$emailtemp = file_get_contents('templates/temp-1.html');
$mail->AltBody = 'This is a spicy email!';
/*Start the loop by adding email addresses*/
foreach($emaillist as $emailkey){
if (in_array($emailkey['Email'], $blocklist)) {
echo 'Message has been been blocked for '.$emailkey['Email'].'<br>';
}else{
$mail->addAddress($emailkey['Email'], $emailkey['First Name'].' '.$emailkey['Last Name']); // Add a recipient
$mail->Subject = $emailkey['First Name'].' '.$emailkey['Last Name'];
$emailtempfilteremail = str_replace("[[email]]", $emailkey['Email'], $emailtemp);
$emailtempfilterfirstname = str_replace("[[firstname]]", $emailkey['First Name'], $emailtempfilteremail);
$emailtempfilterlastname = str_replace("[[lastname]]", $emailkey['Last Name'], $emailtempfilterfirstname);
$mail->Body = $emailtempfilterlastname;
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent to '.$emailkey['Email'].'<br>';
}
$mail->ClearAllRecipients();
}
}
Using the above approach I personally have send hundreds of thousands emails, but, as they say in the comments - you'll risking to be blacklisted (you can check here or here for details).

Categories