PhpMailer ~30 seconds delay on send - php

Ok so I have few problems with PhpMailer.
There is a delay of about 30 seconds before $mail->send is being executed.
2019-07-23 13:43:55 Connection: opening to
smtp.gmail.com:587, timeout=300, options=array() 2019-07-23
13:44:16 Connection: opened 2019-07-23 13:44:16 SERVER
etc...(some list of parameters).
The code being used for registering users. I instantiated Mail class inside model method and then called that method inside Controller following by function that redirects after successful login. I also get headers already sent error.
2019-07-23 13:44:17 Connection: closed Message has
been sent Warning: Cannot modify header information - headers
already sent by (output started at
C:\xampp\htdocs\log\vendor\phpmailer\phpmailer\src\SMTP.php:257) in
C:\xampp\htdocs\log\App\Core\Controller.php on line 43
My code:
Mail class:
class Mail
{
public function sendMail($to, $subject, $text, $html)
{
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = 3;
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'wuwu5431#gmail.com';
$mail->Password = 'Password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
//Recipients
$mail->setFrom('wuwu5431#gmail.com', 'John Smith');
$mail->addAddress($to, '');
$mail->addReplyTo('wuwu5431#gmail.com', 'Information($mail->addReplyTo)');
//Content
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $text;
$mail->AltBody = $html . ' $html . This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
}
}//end of method
}// end of class
Model(method):
public function sendActivationEmail($email)
{
$url = 'url';
$text = 'text';
$html = 'html';
$mail = new \App\Mail;
$mail->sendMail($email, 'Account activation', $text, $html);
}
Controller(method):
public function register()
{
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
foreach($_POST as $key => $value){
$data[$key] = htmlspecialchars(strip_tags(trim($value)));
}
$this->userModel = new \App\Models\UserM;
if ($this->userModel->Register($data)) {
Flash::addMessage('Thank you for Registering with us');
$this->userModel->sendActivationEmail($data['email']);
$this->redirect('User/UserC/success');
}
}
}
Enviroment: win 7, xampp, localhost.

This is entirely normal - welcome to the world of SMTP.
SMTP can impose delays of up to 10 minutes at multiple points within a transaction, and for that reason it's not well suited use during page submission processing, though it's still very common to do that.
The way to handle it is to make it asynchronous (as far as your page is concerned), and there are multiple ways of doing that, for example stash your message in a queue that's picked up and sent by a separate process later (i.e. not holding up your page submission processing), or submit it directly to a local mail server, which will typically accept a submission in a few milliseconds, and deal with onward delivery for you.
Separate from this, these lines are probably wrong:
$mail->setFrom('wuwu5431#gmail.com', 'John Smith');
$mail->addAddress($to, '');
$mail->addReplyTo('wuwu5431#gmail.com', 'Information($mail->addReplyTo)');
If your from and reply-to address are the same, the reply-to will be ignored. If you don't have a name to go with the to address, just leave it off. Single-quoted strings do not do variable interpolation in PHP. You probably want just:
$mail->setFrom('wuwu5431#gmail.com', 'John Smith');
$mail->addAddress($to);

Related

MVC PHPMailer flow

I would like to use PHPMailer in my MVC site but the view content doesn't come for the $emailTemplate variable. This is my own MVC. The problem starts here:
$emailTemplate = $this->view('emails/expirityRemainder'); Could somebody tell me how to manage that change?
If I will do that everything works fine, but I need to load different views:
$emailTemplate = 'The email body';
Here is my controller:
<?php
class Emails extends Controller{
//Send email to remamber the expirity date
public function sendReinder($data){
$emailTemplate = $this->view('emails/expirityRemainder');
$data=[
'recipient'=>'anEmail#yahoo.com',
'subject'=>'TheSubject',
'htmlBody'=>$emailTemplate,
'nonHtmlBody'=>'This is the body in plain text for non-HTML mail clients',
'sentMessage'=>'Message has been sent'
];
$email = new Email();
$email->sendMail($data);
}
}
The 'expirityRemainder.php' file contains a text:
Here will be the HTML code formatted
The PHPMailer file is inside of that libraries/PHPMailer folder.
The Email class send the email (on my server the below blank details are filled):
<?php
// 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;
require 'src/Exception.php';
require 'src/PHPMailer.php';
require 'src/SMTP.php';
class Email{
public function sendMail($data){
$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
//Server settings
$mail->SMTPDebug = 0; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = ''; // Specify main and backup SMTP servers smtp.topwebdeveloper.co.uk
$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 465 25 587
//Recipients
$mail->setFrom('', '');
//$mail->addAddress('', ''); // Add a recipient
//$mail->addAddress(''); // Name is optional
$mail->addAddress($data['recipient'], 'Nameee');
$mail->addReplyTo('', 'Information');
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = $data['htmlBody'];
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
print_r($data);
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
print_r($data);
}
}
}
?>
This is the output:
Here will be the html code formatted
Message could not be sent.
Mailer Error: Message body emptyArray ( [recipient] => anEmail#yahoo.com [subject] => TheSubject [htmlBody] => [nonHtmlBody] => This is the body in plain text for non-HTML mail clients [sentMessage] => Message has been sent )`
I think the view content is expected to not be a string... The $data['htmlBody']inside if sendMail($data) did not receive the view content.
The view method works perfect for my MVC, except that situation when I try to load an mail text:
<?php
class Controller{
public function model($model){
require_once '../app/models/'.$model.'.php';
return new $model();
}
public function view($view, $data=[]){
if(file_exists('../app/views/'.$view.'.php')){
require_once '../app/views/'.$view.'.php';
} else {
die('vien not exists');
}
}
}
I created a new method but still not working:
<?php
public function loadEmailView($view, $data=[]){
if(file_exists('../app/views/'.$view.'.php')){
//ob_start();
//include('../app/views/'.$view.'.php');
//$file = ob_end_flush();
//echo file_get_contents('../app/views/'.$view.'.php');
//$data['htmlBody'] = require_once '../app/views/'.$view.'.php';
} else {
die('Email vien not exists');
}
}
None of the 3 above solutions not add the view content to my htmlBody variable:
<?php
class Emails extends Controller{
//Send email to remamber the expirity date
public function sendReinder($data){
$emailTemplate = $this->loadEmailView('emails/expirityRemainder');
//$emailTemplate = file_get_contents('email_template.php');
$data=[
'recipient'=>'anEmail#yahoo.com',
'subject'=>'TheSubject',
'htmlBody'=>$emailTemplate,
'nonHtmlBody'=>'This is the body in plain text for non-HTML mail clients',
'sentMessage'=>'Message has been sent'
];
$email = new Email();
$email->sendMail($data);
}
}
Thank you!

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).

fastest way to send mails using phpmailer smtp?

i am using following phpmailer function to send 1000+ mails
<?php
function sendMail($sendTo,$Subject,$Body){
require_once 'PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->Host = 'smtp.example.com;smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'newsletter#example.com';
$mail->Password = 'password';
$mail->SMTPSecure = 'ssl';
$mail->Port = 465;
$mail->From = 'newsletter#example.com';
$mail->FromName = 'xyz';
$mail->WordWrap = 50;
$mail->isHTML(true);
$mail->addAddress($sendTo);
$mail->Subject = $Subject;
$mail->Body = ( stripslashes( $Body ) );
$mail->AltBody = 'Please Use a Html email Client To view This Message!!';
if(!$mail->send()) {
$return = 'Message could not be sent.';
// echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
$return = 'Message has been sent!';
}
return $return;
}
and this is the code i am using to call function
foreach ($emails as $email) {
$subject = "sample subject";
$body = "sample body";
sendMail($email, $subject, $body);
}
size of $emails array is 1000+
is there any faster and better way to do this?
You should start by reading the docs provided with PHPMailer where you will find this example.
Of particular note in there, make sure you use SMTPKeepAlive - you may find benefit in sorting your list by domain to maximise connection re-use.
As zerkms said, you should submit to a local mail server for best performance, though surprisingly using mail or sendmail options in PHPMailer is not always faster than SMTP to localhost, largely because postfix' sendmail binary opens a synchronous SMTP connection to localhost anyway - postfix' docs recommend SMTP to localhost for best performance for this reason.
If you are sending to localhost, don't use auth or encryption as the overhead doesn't gain you anything, but if you are using a remote server, use tls on port 587 in preference to the obsolete ssl on port 465.
Generally sending directly to end users is to be avoided - the SMTP client in PHPMailer is somewhat dumb - it does not handle queuing at all, so any domains with greylisting or delivery deferrals for traffic control will fail to be delivered. the best approach is to use SMTP to a nearby MTA and leave the queue handling to that. You can get bounces back from that as well so you can remove bad addresses from your list.
Untested, but this should work.
Basically, it reuses the original object (thus reducing memory allocations).
require_once 'PHPMailer/PHPMailerAutoload.php';
class BatchMailer {
var $mail;
function __construct () {
$this->mail = new PHPMailer;
$this->mail->isSMTP();
$this->mail->Host = 'smtp.example.com;smtp.example.com';
$this->mail->SMTPAuth = true;
$this->mail->Username = 'newsletter#example.com';
$this->mail->Password = 'password';
$this->mail->SMTPSecure = 'ssl';
$this->mail->SMTPKeepAlive = true;
$this->mail->Port = 465;
$this->mail->From = 'newsletter#example.com';
$this->mail->FromName = 'xyz';
$this->mail->WordWrap = 50;
$this->mail->isHTML(true);
$this->mail->AltBody = 'Please use an HTML-enabled email client to view this message.';
}
function setSubject ($subject) {
$this->mail->Subject = $subject;
}
function setBody ($body) {
$this->mail->Body = stripslashes($body);
}
function sendTo ($to) {
$this->mail->clearAddresses();
$this->mail->addAddress($to);
if (!$this->mail->send()) {
// echo 'Mailer Error: ' . $this->mail->ErrorInfo;
return false;
} else {
return true;
}
}
}
$batch = new BatchMailer;
$batch->setSubject('sample subject');
$batch->setBody('sample body');
foreach ($emails as $email) {
$batch->sendTo($email);
}
Drop the function into c++ via cgi. A c++ mailer would be far more robust than hitting the entire http framework first. http://www.cplusplus.com/forum/windows/86562/
But PhP already uses hash table for it's associative array, so you won't pick up anymore speed with a hash table. So you really are sort of maxed out in your web framework.
Drop it to a system level function and c is your fastest/leanest choice.
Unless you are really talented with assembly language.

Sending multiple emails with PHPmailer

Edit: I forgot I'd created the SendMail(); function myself, which is why the explanation doesn't mention at first what it does.
I'm having some trouble with PHPMailer (https://github.com/PHPMailer/PHPMailer) when attempting to send two emails, one directly after the other.
The script is almost completely 'out of the box', with only a few modifications such as a foreach loop to allow for multiple addresses, and everything still works perfectly.
However, if I attempt to call more than one instance of SendMail(); I get the error message:
Fatal error: Cannot override final method Exception::__clone() in .... online 0
Previously I was using the in-built mail(); function, which allowed me to use it as many times as I liked in quick succession , but it doesn't appear to be that simple with PHPmailer:
$to = me#me.com;
$to2 = me2#me2.com';
$headers = 'php headers etc';
$subject = 'generic subject';
$message = 'generic message';
mail($to, $subject, $message, $headers);
mail($to2, $subject, $message, $headers);
The above would result in two identical emails being sent to different people, however I can't easily replicate this functionality with PHPmailer.
Is there a way of stacking these requests so that I can send successive emails without it failing? Forcing the script to wait until the first email has been sent would also be acceptable, although not preferential.
As I mentioned I know it works when only one instance is called, but I don't seem to be able to re-use the function.
I haven't included the source code, although it is all available on the link provided above.
Thanks in advance
Edit as requested
// First Email
$to = array(
'test#test.com',
'test2#test.com',);
$subject = "Subject";
$message = $message_start.$message_ONE.$message_end;
sendMail();
// Second Email
$to = array(
'test#test.com',
'test2#test.com',);
$subject = "Subject";
$message = $message_start.$message_TWO.$message_end;
sendMail();
The above is how I want this to work, as it would work with mail();. The first email will work fine, the second will not.
SendMail() code
This is from the PHPmailer website, and is what is defined as SendMail();. The only difference from the example is the loop for AddAddress, and the inclusion of $to as a global variable.
$mail = new PHPMailer();
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "smtp1.example.com;smtp2.example.com"; // specify main and backup server
$mail->SMTPAuth = true; // turn on SMTP authentication
$mail->Username = "jswan"; // SMTP username
$mail->Password = "secret"; // SMTP password
$mail->From = "from#example.com";
$mail->FromName = "Mailer";
foreach($to as $to_add){
$mail->AddAddress($to_add); // name is optional
}
$mail->AddReplyTo("info#example.com", "Information");
$mail->WordWrap = 50; // set word wrap to 50 characters
$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 = "Here is the subject";
$mail->Body = "This is the HTML message body <b>in bold!</b>";
$mail->AltBody = "This is the body in plain text for non-HTML mail clients";
if(!$mail->Send())
{
echo "Message could not be sent. <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
echo "Message has been sent";
You haven't posted this code that lets me make this a complete conclusion, but from the Exception and the way you've defined an overriding class inside a function, you probably have class.phpmailer.php loading every time like this:
require('class.phpmailer.php');
or
include('class.phpmailer.php');
You should change that line to
require_once('class.phpmailer.php');
The reason you need to change it to require_once is so that PHP will not load the class file the second time when you try to create the new/second PHPMailer class. Otherwise, the line class PHPMailer throws the __clone() exception.
Added an example below:
<?php
/**
* This example shows how to send a message to a whole list of recipients efficiently.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
error_reporting(E_STRICT | E_ALL);
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
//Passing `true` enables PHPMailer exceptions
$mail = new PHPMailer(true);
$body = file_get_contents('contents.html');
$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 = 25;
$mail->Username = 'yourname#example.com';
$mail->Password = 'yourpassword';
$mail->setFrom('list#example.com', 'List manager');
$mail->addReplyTo('list#example.com', '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
$mysql = mysqli_connect('localhost', 'username', 'password');
mysqli_select_db($mysql, 'mydb');
$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = FALSE');
foreach ($result as $row) {
try {
$mail->addAddress($row['email'], $row['full_name']);
} catch (Exception $e) {
echo 'Invalid address skipped: ' . htmlspecialchars($row['email']) . '<br>';
continue;
}
if (!empty($row['photo'])) {
//Assumes the image data is stored in the DB
$mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
}
try {
$mail->send();
echo 'Message sent to :' . htmlspecialchars($row['full_name']) . ' (' . htmlspecialchars($row['email']) . ')<br>';
//Mark it as sent in the DB
mysqli_query(
$mysql,
"UPDATE mailinglist SET sent = TRUE WHERE email = '" .
mysqli_real_escape_string($mysql, $row['email']) . "'"
);
} catch (Exception $e) {
echo 'Mailer Error (' . htmlspecialchars($row['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();
}
In addition to #Amr most excellent code.
In order to use this in a cron fasion, two adds are useful.
$mail-> SMTPDebug = true;
$mail-> Debugoutput = function( $str, $level ) {_log($str);};
The function _log is up to you. Writing to a file, to a database or wherever. I personally have reduced this to
$mail-> Debugoutput = function( $str, $level ) {if( $level===3 ) {_log( $str ); } };
to only write the more juicier messages
the solution is to reset recipients data like this:
$Mailer->clearAddresses()
use your own variable as an instance of PHPMailer (instead of $Mailer)
$Mailer->clearAddresses()
This is the solution to avoid multiple msj to be send to the same recipient.

Sending 2 emails with PHP mailer fails

I am rather puzzled with this one.
//SMTP servers details
$mail->IsSMTP();
$mail->Host = "mail.hostserver.com";
$mail->SMTPAuth = false;
$mail->Username = $myEmail; // SMTP usr
$mail->Password = "****"; // SMTP pass
$mail->SMTPKeepAlive = true;
$mail->From = $patrickEmail;
$mail->FromName = "***";
$mail->AddAddress($email, $firstName . " " . $lastName);
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = $client_subject;
$mail->Body = $client_msg;
if($mail->Send())
{
$mail->ClearAllRecipients();
$mail->ClearReplyTos();
$mail->ClearCustomHeaders();
...
$mail->From = "DO_NOT_REPLY#...";
$mail->FromName = "****";
$mail->AddAddress($ToEmail1, "***"); //To: (recipients).
$mail->AddAddress($ToEmail2, "***"); //To: (recipients).
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = $notification_subject;
$mail->Body = $notification_msg;
if($mail->Send())
{
...
The first email sends fine. The second one doesn't. What could be the reason for that behavior? Am I missing some kind of reset?
Update: using a different mail server seems to work so apparently it's a setting of that specific mail server causing problems. Any idea what that could be?
Some providers impose restrictions on the number of messages that can be sent within a specific time span. To determine if your problem depends by a provider "rate limit", you should try to add a pause after the first send. For example:
if ($mail->Send()) {
sleep(10); // Seconds
...
if ($mail->Send()) {
...
}
}
Then, by progressively lowering the sleep time, you should be able to determine which is the rate limit.
Try this:
As #Felipe Alameda A mentioned Remove $mail->SMTPKeepAlive = true;
// for every mail
if(!$mail->Send())
{
echo 'There was a problem sending this mail!';
}
else
{
echo 'Mail sent!';
}
$mail->SmtpClose();
IMHO you need to create new PHPMailer object for every sent email. If you want to share some common setup, use something like this:
$mail = new PHPMailer();
/* Configure common settings */
while ($row = mysql_fetch_array ($result)) {
$mail2 = clone $mail;
$mail2->MsgHTML("Dear ".$row["fname"].",<br>".$cbody);
$mail2->AddAddress($row["email"], $row["fname"]);
$mail2->send();
}
I think your problem is $mail->SMTPAuth = false;
It is hard to believe there are ISP or SMTP providers that don't require authentication, even if they are free.
You may try this to check for errors instead of or in addition to checking for send() true:
if ( $mail->IsError() ) { //
echo ERROR;
}
else {
echo NO ERRORS;
}
//Try adding this too, for debugging:
$mail->SMTPDebug = 2; // enables SMTP debug information
Everything else in your code looks fine. We use PHPMailer a lot and never had any problems with it
The key may lie in the parts you have omitted. Is the domain of the sender of both emails the same? Otherwise the SMTP host may see this as a relay attempt. If you have access to the SMTP server logs, check these; they might offer a clue.
Also, check what $mail->ErrorInfo says... it might tell you what the problem is.
i personally would try to make small steps like sending same email.. so just clear recipients and try to send identical email (this code works for me). If this code passes you can continue to adding back your previous lines and debug where it fails
and maybe $mail->ClearCustomHeaders(); doing problems
//SMTP servers details
$mail->IsSMTP();
$mail->Host = "mail.hostserver.com";
$mail->SMTPAuth = false;
$mail->Username = $myEmail; // SMTP usr
$mail->Password = "****"; // SMTP pass
$mail->SMTPKeepAlive = true;
$mail->From = $patrickEmail;
$mail->FromName = "***";
$mail->AddAddress($email, $firstName . " " . $lastName);
$mail->WordWrap = 50;
$mail->IsHTML(true);
$mail->Subject = $client_subject;
$mail->Body = $client_msg;
// all above is copied
if($mail->Send()) {
sleep(5);
$mail->ClearAllRecipients();
$mail->AddAddress('another#email.com'); //some another email
}
...
Try with the following example.,
<?php
//error_reporting(E_ALL);
error_reporting(E_STRICT);
date_default_timezone_set('America/Toronto');
require_once('../class.phpmailer.php');
//include("class.smtp.php"); // optional, gets called from within class.phpmailer.php if not already loaded
$mail = new PHPMailer();
$body = file_get_contents('contents.html');
$body = eregi_replace("[\]",'',$body);
$mail->IsSMTP(); // telling the class to use SMTP
$mail->Host = "mail.yourdomain.com"; // SMTP server
$mail->SMTPDebug = 2; // enables SMTP debug information (for testing)
// 1 = errors and messages
// 2 = messages only
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Host = "mail.yourdomain.com"; // sets the SMTP server
$mail->Port = 26; // set the SMTP port for the GMAIL server
$mail->Username = "yourname#yourdomain"; // SMTP account username
$mail->Password = "yourpassword"; // SMTP account password
$mail->SetFrom('name#yourdomain.com', 'First Last');
$mail->AddReplyTo("name#yourdomain.com","First Last");
$mail->Subject = "PHPMailer Test Subject via smtp, basic with authentication";
$mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
$mail->MsgHTML($body);
$address1 = "whoto#otherdomain.com";
$address2 = "whoto#otherdomain.com";
$mail->AddAddress($address1, "John Doe");
$mail->AddAddress($address2, "John Peter");
$mail->AddAttachment("images/phpmailer.gif"); // attachment if any
$mail->AddAttachment("images/phpmailer_mini.gif"); // attachment if any
if(!$mail->Send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
?>
Note : Better you can make a multiple user email and name as an ARRAY, like
<?php
$recipients = array(
'person1#domain.com' => 'Person One',
'person2#domain.com' => 'Person Two',
// ..
);
foreach($recipients as $email => $name)
{
$mail->AddCC($email, $name);
}
(or)
foreach($recipients as $email => $name)
{
$mail->AddAddress($email, $name);
}
?>
i think this may help you to resolve your problem.
I think you've got organizational problems here.
I recommend:
Set your settings (SMTP, user, pass)
Create new email object with info from an array holding messages and to addresses
Send email
Goto step 2

Categories