Could you have a look at this PHP script using PHPMailer to see its correction?

Hi Experts

Could you have a look at this PHP script using PHPMailer to see its correction?

After some tests with a small number of address it run well.
But then, when using the complete base - about 750 address it seens to be erratic!

f.e.  - My own email address had received 03 copies of the same email, after a while my SMTP provider warned me that I reached the limit of email sendings I could send in 01 hour.


<?php

   error_reporting(E_STRICT | E_ALL);

   date_default_timezone_set('Etc/UTC');

   $host = "mysql.xxxxxxxxxx.com.br"; // Host KingHost

   $usermysql = "XXXXXXXX"; // Mysql username
   $passmysql = "XXXXXXXX"; // Mysql password
   $db_name = "XXXXXXXX"; // Database name locaweb
   $admin_user = "XXXXXXXX"; // Administrative user

   require '../PHPMailerAutoload.php';

   $mail = new PHPMailer;

   $mail->isSMTP();
   $mail->Host = 'smtp.xxxxxxxxxx.net';
   $mail->SMTPAuth = true;
   $mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
   $mail->Port = 25;

   $mail->Username = 'contato@xxxxxxxxxxxxx.com.br';
   $mail->Password = 'cipava01';


   $mail->setFrom('contato@xxxxxxxxxxx.com.br', 'Espiriplug - Gestao de Bibliotecas Espiritas');
   $mail->Subject = "eSpiriplug - Boletim 021 - Lancamento BETA do Sistema de Gestao de Bibliotecas Espiritas";
   $mail->AltBody = 'Para ver a mensagem use um leitor de email compatível com HTML!';


   //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($host, $usermysql, $passmysql, $db_name);


   mysqli_select_db($mysql, 'mydb');

// Just for the test... ok!
//   $result = mysqli_query($mysql, "SELECT username , email , realname FROM forum_user WHERE substring(username,1,5)='teste'
//   OR   username ='eduardofuerte'");

   $result = mysqli_query($mysql, "SELECT username , email , realname FROM forum_user");

   foreach ($result as $row)
   { //This iterator syntax only works in PHP 5.4+

       $mail->addAddress($row['email'], $row['realname']);

       $body = "<header>";
       $body = "<font face=Arial size=2>";
       $body = $body ."<p>";
       $body = "<b> Prezado(a) ".$row['username'] . "<b> </br>";
       $body = $body . "</br>";
       $body = $body . "</header>";
       $body = $body . file_get_contents('contents_espiriplug.html');

       //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


       if (!$mail->send())
       {
           echo "Mailer Error (" . str_replace("@", "&#64;", $row["email"]) . ') ' . $mail->ErrorInfo . '<br />';
           
           // Não parar de enviar.
           //break; //Abandon sending
           
           
       } else
       {
           echo "Message sent to :" . $row['username'] . ' (' . str_replace("@", "&#64;", $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']) . "'");
       }
       // Clear all addresses and attachments for next loop
       $mail->clearAddresses();
       $mail->clearAttachments();
   }

Open in new window


Thanks in advance!
Eduardo FuerteAsked:
Who is Participating?
 
Marco GasiConnect With a Mentor FreelancerCommented:
In the dot added before the equal sign
$body .= 'xxx' instead of $body = 'xxx'

Open in new window

The dot tells php to concatenate strings, that is the new string will be added to the existing $body variable. In your code, you are rewriting the $body variable from scratch:

Your code:
       $body = "<header>";                                                                              $body is <header>
       $body = "<font face=Arial size=2>";                                                    $body is <font face=Arial size=2>
       $body = $body ."<p>";                                                                           $body is <p>
       $body = "<b> Prezado(a) ".$row['username'] . "<b> </br>";           $body is <b> Prezado(a) ".$row['username'] . "<b> </br>
       $body = $body . "</br>";                                                                       $body is </br>
       $body = $body . "</header>";                                                              $body is </header>
       $body = $body . file_get_contents('contents_espiriplug.html')      $body is the content of the file

Open in new window


Notice that </br> is wrong: use <br /> instead.
my code:

       $body = "<header>";                                                                              $body is <header>
       $body .= "<font face=Arial size=2>";                                                    $body is <header><font face=Arial size=2>
       $body .= $body ."<p>";                                                                           $body is <header><font face=Arial size=2><p>
       $body .= "<b> Prezado(a) ".$row['username'] . "<b> </br>";           $body is <header><font face=Arial size=2><p><b> Prezado(a) ".$row['username'] . "<b> </br>
       $body .= $body . "</br>";                                                                       $body is  <header><font face=Arial size=2><p><b> Prezado(a) ".$row['username'] . "<b> </br></br>
       $body .= $body . "</header>";                                                              $body is  <header><font face=Arial size=2><p><b> Prezado(a) ".$row['username'] . "<b> </br></br></header>
       $body .= $body . file_get_contents('contents_espiriplug.html')      $body is <header><font face=Arial size=2><p><b> Prezado(a) ".$row['username'] . "<b> </br></br></header> more the content of the file

Open in new window

0
 
Andy MConnect With a Mentor Internal Systems ManagerCommented:
My own email address had received 03 copies of the same email, after a while my SMTP provider warned me that I reached the limit of email sendings I could send in 01 hour.

Not sure on the additional copies (could be issues when sending large number of emails through the server) but the warning from your SMTP provider is quite a common one. If you're not subscribed to/using a mass-emailing package or service, many providers will limit how many emails you can send in a given timeframe. It's to prevent their systems getting flagged as a spam source and being blocked as a result. It's likely you're sharing the service with a number of other users so the provider limits you to prevent other users having issues in the long run.

If you're going to be regularly ending out emails to a large number of users you may want to have a read up on mass-emailing, mailing lists and spamming best practices.
1
 
Marco GasiFreelancerCommented:
You can just add this line before to the addAddress call:
$mailer->ClearAllRecipients( );

Open in new window

Because now you sen email to all added address at any iteration.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
Ray PaseurConnect With a Mentor Commented:
Sending bulk emails is a full time job all by itself.  It's complicated and difficult, with all kinds of external issues that you can only learn about after the process fails.  And I guarantee you, this is only the first failure.  The only thing I can't tell you is what failure you will encounter next!

You might want to consider ConstantContact.
0
 
Marco GasiFreelancerCommented:
You must also correct your code: when you build your $body you are continously overriding it. Use concatenation notation:
       $body = "<header>";
       $body .= "<font face=Arial size=2>";
       $body .= $body ."<p>";
       $body .= "<b> Prezado(a) ".$row['username'] . "<b> </br>";
       $body .= $body . "</br>";
       $body .= $body . "</header>";
       $body .= $body . file_get_contents('contents_espiriplug.html')

Open in new window

0
 
Eduardo FuerteAuthor Commented:
Hi

Thanks for replies.

@Ray
It's a non profitable email sendings and very eventual - so I have to deal it by myself.

@Marco
I'm going to try your suggestions with a small number of emails each step.
0
 
Julian HansenCommented:
@Eduardo,

It looks like you have copied the sample from the PHPMailer page - which is good.

The sample includes code to authenticate to SMTP - note this may not be necessary - your may server be configured to connect automatically for you. No harm in doing it this way though especially if you were having problems with mail before.

I would also consider using HEREDOC for your message construction - it will make your code easier to read and maintain.
0
 
Eduardo FuerteAuthor Commented:
@Marco

I couldn't  capture in what your last code differ from mine?
0
 
Eduardo FuerteAuthor Commented:
@Julian

What you post makes all sense.

The provider claims that the limit of "authenticated" emails sent was reached.... (at about 300 per hour)

So I can avoid to use smtp strategy, ok?

Could you possibly point how to workaround it (in code) ?
0
 
Julian HansenCommented:
If you have another SMTP server you can log onto that does not have a limit then you can do so as you are doing. However, you might find the same problem - many ISP's impose limits on number of emails sent in a time period.

How many emails are you planning to send at a time?
0
 
Eduardo FuerteAuthor Commented:
Just about 750 in total ... so I can divide it during the day... (100 for hour f.e.)  so I can maintain SMTP.
I guess.
0
 
Julian HansenCommented:
What triggers the emails being sent? Do they all go out at once in response to some event?
0
 
Eduardo FuerteAuthor Commented:
@Julian

I don't know if I well understood your question.

Accordingly to what I posted in my profile I'm working to real charity institutions interested in better organize themselves mainly here in Brazil, absolutely free of charges for them, this just during my free time.

I'm releasing a new software for libraries, something requested from time to time from some of them. So I'm advertising it by this mail!
0
 
Julian HansenCommented:
What I meant was, what causes the email to be sent?

You said you have to send out 750 emails - do these all go out at in one go or do they get sent only when something happens.

How often are they sent.
0
 
Eduardo FuerteAuthor Commented:
Sorry!

These mails doesn't need to be sent at the same time or even during a short period of one day.

It can ben sent between a week or even a large period.
0
 
Julian HansenCommented:
So you could have a server process that runs say every hour / day / whatever and processes the next N emails.

For instance a cron job kicks off a script that reads the next 100 unprocessed emails from the DB and sends them. The cron job can be scheduled to run far enough apart to keep the ISP happy.
0
 
Eduardo FuerteAuthor Commented:
@Marco
Thank you for the advises you gave me about my code corrections.

@Julian
Just to know.
The cron job to be scheduled  as you mentioned demands to be made at provider's Linux?  
(it seens very trick to be done)
0
 
Eduardo FuerteAuthor Commented:
@Marco

Just something that confused me, are you certain that without

$mail->ClearAllRecipients();

Open in new window


All the mails are sent at any interation?
Because PHPMailer example: mailing_list.php, where I obtained and adapted my code, doesn't use it.
0
 
Marco GasiFreelancerCommented:
You're right: I had not seen the last 2 lines within the loop
       $mail->clearAddresses();
       $mail->clearAttachments();

Open in new window

So you can ignore that comment (but keep the other about string concatenation as valid).

Julian suggested a good solution mentioning a CRON job.
0
 
Eduardo FuerteAuthor Commented:
I didn't  catched how to create a Linux CRON job, I have to learn about how to do it)

By now I'm sending it in a simpler way , in parts.
0
 
Julian HansenConnect With a Mentor Commented:
The creation of a cron job is dependent on what your ISP provides you in terms of functionality. Check with them to see if they offer that as an option.
0
 
Eduardo FuerteAuthor Commented:
@Julian
I opened a ticket to my ISP snf soon I will have a reply about CRON.

@Ray
Really erratic. A friend received 04 email copies  I run the script just one time with all the complee user's table content and then the  browser "freezed".
After that ISP told me I reached the limit of emails/hour (300).
0
 
Eduardo FuerteAuthor Commented:
@Julian

The ISP replied me it's possible to schedule a CRON created by the user.

By the way, running the PHPMailer script - 100 mails each time, until ISP SMTP advices about emails limit per hour reached, stop a hour and then restart (since the email number is not so large, it's OK) everything seems to go fine, just one copy to each email address.
0
 
Eduardo FuerteAuthor Commented:
Thank you for everyone participation!
0
 
Julian HansenCommented:
You are welcome.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.