0

Using PHPMailer, emails are successful. Then my script inserts the email content into mysqli database.
Most of the time this query insert fails. But sometimes the query insert does works.

Using function my_error_handler ($e_number, $e_message, $e_file, $e_line, $e_vars) I can see the error code which is: mysqli::ping(): send of 5 bytes failed with errno=32 Broken pipe.

(The database insert query is wrapped inside if($con->ping()){...}.)

Having read (in stackoverflow) what 'broken pipe' means, I do not know how to correct this error. Any help please. Thanks for your response.

For information, PHPMailer takes about 1 minute to execute. Inside the PHPMailer loop are only calls to $mail->Body, $mail->AltBody, $mail->addAddress(), $mail->send() and $mail->clearAddresses() (after sending). Here is the code:

    $mail = new PHPMailer(true); //Argument true in constructor enables exceptions
    $mail->isHTML(true);
    $mail->isSMTP(true);
    $mail->Host = "$smtpHost";
    $mail->Port = "$smtpPort";
    $mail->Username = "$username"; // SMTP username
    $mail->Password = "$password"; // SMTP password
    $mail->SMTPKeepAlive = true; //SMTP connection will not close after each email sent, 
    $mail->SMTPAuth   = true;                            //Enable SMTP authentication
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;     //Enable implicit TLS encryption
    $mail->SMTPAuth   = true;                                   //Enable SMTP authentication
    $mail->SMTPDebug = 0;    
    $realfrom=$username;
    $mail->From = "$realfrom";
    $mail->FromName = "$sendname";
    $mail->addReplyTo("$username", "Admin");
    $mail->Subject = "$subject";
    $mail->AddEmbeddedImage('../../Images/bannersm2.jpg', 'banner', 'JC');      
    $body ="....."; // edit $body 
    //for each subscriber
    while ($row = mysqli_fetch_array($Qemails, MYSQLI_ASSOC)){ // all members from TempTable
    $First = $row['First_Name'];
    $Last = $row['Last_Name'];
    $email = $row['email'];
    $emailaddress = $email;
    $to = $email;
    $name=($row['addressto']);
    $site_name = "www.jc.net"; // Your website name
    
    //Edit the body of the message to be sent here
    $body = "Hello $First".$body;
    $mail->Body = "<img alt=\"PHPMailer\" src=\"cid:banner\"><br><br>$body";
    $mail->AltBody = "$body";
    $mail->addAddress("$to", "$name");//To address and name
    try {
    $mail->send();
    print ("<div id=\"sectionContent\">");
    print ("<font color=\"red\"><img src=../../Images/checkmark.jpg> Successful.</font><br><br>");
    print ("</div><br>");
    $count++;
        
    echo"<font class='F088'>";
    echo "This email makes a cummulative total of $count messages sent.<br>";
    echo"</font>";
    } catch (Exception $e) {
    $fail = $fail +1;
    echo "Mailer Error: " . $mail->ErrorInfo;
    print ("<div id=\"sectionContent\">");
    echo"<font class='F088'>";
    print ("<br><br><font color=\"red\"><img src=Images/crossMark.jpg> Uh-Oh! Something.</font>");
    print ("</font></div>");
    echo"<font class='F088'>";
    echo "This email makes a cummulative total of $fail messages NOT sent.</font>";
    }   
    $mail->clearAddresses();//Clear all addresses and attachments (only if different) for the next iteration
    }
    if($count>=1){
    $sent=$count + $sent;
    }
    // Connect to the database is $con
     /* check if server is alive */
    if ($con->ping()) {
    $subject1 = mysqli_real_escape_string($con, $subject);
    $message1 = $_POST["message"];
    $message1 = mysqli_real_escape_string($con, $message1);
    $sendname1= mysqli_real_escape_string($con, $sendname);
    $queryarchive = "INSERT INTO archived_groupemails (groupname, subject, message, sendname, datesent, numberemails) VALUES ( '$selectedgroupsl', '$subject1', '$message1', '$sendname1', NOW(), '$sent') ";
    $resultarchive = @mysqli_query($con ,$queryarchive); // Run the query.
    }

Based on advice from my server, I edited the .htaccess for the whole website. No help.

    php_value upload_max_filesize 256M
    php_value post_max_size 256M
    php_value memory_limit 512M
    php_value max_input_time 180
    php_value max_execution_time 180

I contacted the server who referred me to stackoverflow.

Synchro
  • 35,538
  • 15
  • 81
  • 104
MartinB
  • 1
  • 2
  • All of those params are for PHP; you may need to increase the timeouts for MySQL too. – Synchro Jul 11 '23 at 19:42
  • That makes sense to me. Can I set this 'time-out' parameter using php? I'm having difficulty understanding answers given in stackoverflow on how this is done. I see:SET GLOBAL MAX_EXECUTION_TIME=2000; – MartinB Jul 13 '23 at 00:53
  • Unless you have many thousands of recipients, you really should be running into MySQL timeouts, which typically only affect to single long queries, not lots of small ones. Your code is hard to read without indenting (I suggest you use an IDE), and I can see you're not being careful about types (e.g. `$mail->Port = "$smtpPort"`). In my experience, the mysql ping command often doesn't actually work, so I'd suggest not using it, instead handling the actual query failing. Also take a look at [the mailing list example provided with PHPMailer]($mail->Port = "$smtpPort"). – Synchro Jul 13 '23 at 08:04
  • "*PHPMailer takes about 1 minute to execute*" - have you traced why it takes so long? If you can solve that problem the MySQL connection timing out problem goes away. – Don't Panic Jul 13 '23 at 08:18
  • Thanks for the feedback. This script is emailing 26 addresses. The script shows same error when it runs without the 'ping'. The parameters are set earlier in the script. For clarity, I didn't include that part of the script that defines these variables. eg: $smtpPort = '465'; As for code indentation, I couldn't post the script when it was generated by IDE with indents. Must be my inexperience with stackoverflow as my attempted entry showed an error. – MartinB Jul 13 '23 at 14:53
  • The tracer using $mail->SMTPDebug = 3; 2023-07-13 15:00:13 Connection: opening to ssl://smtp.titan.email:465, timeout=300, options=array() 2023-07-13 15:00:14 Connection: opened 2023-07-13 15:00:35 SERVER -> CLIENT: 220 smtp-out.flockmail.com ESMTP Postfix. It seems to be the server taking 20 seconds which I cannot control. I'm using the host suggested settings. Host is Hostinger. – MartinB Jul 13 '23 at 15:05
  • Actually the PHPMailer takes closer to 30 seconds rather than a minute --- it seems to be a minute. Thanks for your comments. – MartinB Jul 13 '23 at 15:21
  • My guess is the "Broken pipe" error is down to the MySQL connection closing during those very long requests. Attempting to get MySQL to hold connections open longer, or PHP to run longer, is the wrong approach IMO. What if you need to send 52 emails next month, and it takes 2x as long? Any fix that held your connections open for 30s is now useless. There's no reason sending 26 emails should take 30s. If the mail server is yours or your company's, perhaps you can investigate that. – Don't Panic Jul 14 '23 at 07:48
  • If not, is using an alternative mail service an option? Eg I use and can recommend Mailgun, but there are many others, most have some kind of free tier. There are various options but the simplest would be to just replace the SMTP server/credentials you are currently using with the ones you get from the external service. If that's not an option, maybe some kind of batch/job/queue approach, where you save the stack of mails to send to the DB, and a CLI process that runs every X minutes processes a batch from the DB. – Don't Panic Jul 14 '23 at 07:48
  • Thank you for your insights. This issue is ongoing. The server's technical team have verified the connection time of 20 seconds is their experience with my PHPMailer. This is the time lapse between 'Connection: opened' and 'SERVER -> CLIENT:' response. – MartinB Jul 15 '23 at 19:26

0 Answers0