Solved

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

Posted on 2016-09-06
25
47 Views
Last Modified: 2016-09-08
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!
0
Comment
Question by:Eduardo Fuerte
  • 12
  • 7
  • 4
  • +2
25 Comments
 
LVL 13

Assisted Solution

by:Andy M
Andy M earned 50 total points
ID: 41785943
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
 
LVL 30

Expert Comment

by:Marco Gasi
ID: 41785949
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
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 50 total points
ID: 41785953
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
 
LVL 30

Expert Comment

by:Marco Gasi
ID: 41785966
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
 

Author Comment

by:Eduardo Fuerte
ID: 41785973
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
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41785989
@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
 

Author Comment

by:Eduardo Fuerte
ID: 41785990
@Marco

I couldn't  capture in what your last code differ from mine?
0
 

Author Comment

by:Eduardo Fuerte
ID: 41785997
@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
 
LVL 30

Accepted Solution

by:
Marco Gasi earned 200 total points
ID: 41786001
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
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41786011
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
 

Author Comment

by:Eduardo Fuerte
ID: 41786022
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
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41786083
What triggers the emails being sent? Do they all go out at once in response to some event?
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:Eduardo Fuerte
ID: 41786161
@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
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41786177
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
 

Author Comment

by:Eduardo Fuerte
ID: 41786210
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
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41786262
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
 

Author Comment

by:Eduardo Fuerte
ID: 41786394
@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
 

Author Comment

by:Eduardo Fuerte
ID: 41786471
@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
 
LVL 30

Expert Comment

by:Marco Gasi
ID: 41786486
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
 

Author Comment

by:Eduardo Fuerte
ID: 41786496
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
 
LVL 51

Assisted Solution

by:Julian Hansen
Julian Hansen earned 200 total points
ID: 41786774
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
 

Author Comment

by:Eduardo Fuerte
ID: 41786954
@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
 

Author Comment

by:Eduardo Fuerte
ID: 41789545
@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
 

Author Closing Comment

by:Eduardo Fuerte
ID: 41789550
Thank you for everyone participation!
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 41789727
You are welcome.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Author Note: Since this E-E article was originally written, years ago, formal testing has come into common use in the world of PHP.  PHPUnit (http://en.wikipedia.org/wiki/PHPUnit) and similar technologies have enjoyed wide adoption, making it possib…
Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now