Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

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

Posted on 2016-09-06
25
Medium Priority
?
94 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 12
  • 7
  • 4
  • +2
25 Comments
 
LVL 14

Assisted Solution

by:Andy M
Andy M earned 200 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 31

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 111

Assisted Solution

by:Ray Paseur
Ray Paseur earned 200 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 31

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 59

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 31

Accepted Solution

by:
Marco Gasi earned 800 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 59

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 59

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
 

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 59

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 59

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 31

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 59

Assisted Solution

by:Julian Hansen
Julian Hansen earned 800 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 59

Expert Comment

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

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
Suggested Courses

618 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