4

I am trying to send multiple emails within while loop, With the following code its not sending email notification and giving error 'Fatal error: Uncaught Error: Class "PHPMailer" not found in C:\xampp\htdocs\clinic\paients\run_medications.php:98 Stack trace: #0 {main} thrown in'. While the location is correct and its sending single email from another child directory.

require_once('../includes/PHPMailer.php');
require_once('../includes/SMTP.php');
require_once('../includes/Exception.php');
$full_dt = date('Y-m-d H:i:s');
$dt = date('Y-m-d');
$dt_hr = date('H');
$check_timing = $con->prepare("SELECT medication, start_time, end_time FROM timings WHERE HOUR(end_time) = :end ");
$check_timing->bindparam(':end', $dt_hr);
$check_timing->execute();
$count1 = $check_timing->rowCount();
if($count1 > 0) {
while($rows = $check_timing->fetch(PDO:: FETCH_OBJ)) {
  $medication = $rows->medication;
  $start_time = $dt.' '. $rows->start_time;
  $end_time = $dt.' '.$rows->end_time;
  $timestamp = strtotime($end_time) + 60*60;
  $end_hour = date('Y-m-d H:i:s', $timestamp);
    $query = "SELECT a.location_code, b.* FROM patients a INNER JOIN medication b ON a.id = b.pat_id WHERE b.status != 2 AND b.directions = :med AND b.last_time NOT BETWEEN :start AND :end AND :crntime BETWEEN b.start_date AND b.end_date AND :crntime BETWEEN :end AND :end_hour";
    $statement = $con->prepare($query);
    $statement->bindparam(':med', $medication);
    $statement->bindparam(':start', $start_time);
    $statement->bindparam(':end', $end_time);
    $statement->bindparam(':crntime', $full_dt);
    $statement->bindparam(':end_hour', $end_hour);
    $statement->execute();
    $count = $statement->rowCount();
    if($count > 0) {
    while($row = $statement->fetch(PDO:: FETCH_OBJ)) {
            $drug_id = $row->drgid;
            $code = $row->location_code;
            $pat_id = $row->pat_id;
            $drug = $row->med_type.' - '.$row->drug.' ('.$row->strength.')';
            $dose = $row->dosage;
            $route = $row->route;
            $directions = $row->directions;
        
            $getUserName = "SELECT name FROM users WHERE FIND_IN_SET(location_code, :codes)>0 ";
            $runUser = $con->prepare($getUserName);
            $runUser->bindParam(':codes',$code);
            $runUser->execute();
            $check = $runUser->rowCount();
            if($check > 0) {
            $userRow = $runUser->fetch(PDO::FETCH_OBJ);
            $by = $userRow->name;
            }
        
            $insert_report = $con->prepare("
                INSERT INTO  `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')");
            
                $insert_report->bindparam(':m_id',$drug_id);
                $insert_report->bindparam(':p_id',$pat_id);
                $insert_report->bindparam(':time',$end_time);
                $insert_report->bindparam(':by',$by);
                $insert_report->execute();
        
                $mail = new PHPMailer();
                $mail->isSMTP();
                $mail-> SMTPOptions = array (
                'ssl' => array (
                'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
                )
                );
                $mail->Host = "smtp.gmail.com";
                $mail->SMTPAuth = true;
                $mail->SMTPSecure = "tls";
                $mail->Port = "587";
                $mail->Username = "[email protected]";
                $mail->Password = "12345678";
                $mail->Subject = "Medication Report";
                $mail->setFrom("[email protected]",$by);
                $mail->isHTML(true);
                //Attachment
                    //$mail->addAttachment('img/attachment.png');
                //Email body
                $mail->Body = "<h3>Medication Report by ($by) </h3></br>
                                You are being alerted that <b>$name</b> has missed their $directions Medication $row->med_type. And you may need to take appropriate action..";
                $mail->addAddress($to_email['Email_add']);
                $mail->send();

      } // /while 

    }// if num_rows
  }//while close
}// if num_rows
4
  • This seems like a basic debugging issue - check what you're actually getting in $count and $count1, test your database queries directly in the database. If code inside an if statement is not running, it means the condition is false, so you need to figure out why. Separately, you should absolutely not need to disable certificate verification when connecting to gmail; figure out what is wrong with your PHP installation instead, as the PHPMailer troubleshooting guide says. Commented Oct 13, 2021 at 12:29
  • @Synchro I have checked these querys. It works properly on MySQL. I think it have the issue in loops. Because it only works for the last record. It is inserting the last row of the matching data. Commented Oct 14, 2021 at 10:40
  • So check what rows your loops are receiving – don't assume that things are doing what you expect, check it all. Also, learn how to use a debugger so you can step through the code and see what's happening. Commented Oct 15, 2021 at 6:37
  • Holy moly, that code... first things first, I'd start with some refactoring because like this it's really hard to figure out what's going on. Commented Oct 22, 2021 at 12:27

3 Answers 3

2
+50

if you're not using exceptions, you do still need to load the Exception class as it is used internally.

So, put use at the top of your page like this (I think this is the reason why you're getting undefined error):

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

Then call files like this :

require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
try {
  $mail->SMTPDebug = 0;
  $mail->isSMTP();
  $mail->Host = "smtp.gmail.com";
  $mail->SMTPAuth = true;
  $mail->Username = "[email protected]";
  $mail->Password = "password";
  $mail->Port = 587;
  $mail->setFrom('[email protected]', 'Mailer');
  $mail->addAddress($email);
  $mail->addReplyTo("[email protected]", "Alias");
  $mail->CharSet = "UTF-8";
  $mail->isHTML(true);
  $mail->Subject = $subject;
  $mail->Body = $message;
  $mail->send();
     echo "Mail sent.";
  } catch (Exception $e) {
     echo "Failed. Mailer error: {$mail->ErrorInfo}";
  }

Some times this line use PHPMailer\PHPMailer\PHPMailer; works like this use PHPMailer\PHPMailer; try both ways. but first one will work for you I think.

I dont use ssl options, if you need it just place it under isSMTP.

$mail-> SMTPOptions = array (
  'ssl' => array (
  'verify_peer' => false,
  'verify_peer_name' => false,
  'allow_self_signed' => true
  )
);

Here is the example for sending multiple emails : Send multiple email

Note: You have to set your gmail account to less secure for apps to use phpmailer.

Because Gmail has started imposing an authentication mechanism that substitutes SMTP athentication for OAuth2-based authorisation. more info

Less secure accounts more info , Less secure accounts

Google is blocking low secure accounts, to your knowledge.

Sign up to request clarification or add additional context in comments.

2 Comments

Its giving this error Failed. Mailer error: SMTP Error: Could not connect to SMTP host. Fatal error: Cannot declare class PHPMailer\PHPMailer\PHPMailer, because the name is already in use
@Namri Looks like you added that line twice,make sure you didnt. if didnt work then Change this $mail = new PHPMailer\PHPMailer\PHPMailer(true); to this $mail = new PHPMailer\PHPMailer\PHPMailer(); or to this $mail = new PHPMailer(); and make sure you don't add same codes twice and your paths are correct. Could not connect to SMTP host means google doesnt let you connect to server, follow steps in my answer.
2

Where is your PHPMailerAutoload.php file located?

You need import it with this :

require_once('phpmailer/PHPMailerAutoload.php');

overall you must do this steps:

  • Download the package from https://github.com/PHPMailer/PHPMailer by clicking on the "Download ZIP" button on the far lower right of the page.

  • Unzip file.

  • upload the language folder, class.phpmailer.php, class.pop3.php, class.smtp.php, and PHPMailerAutoload.php all into the same directory on your server, I like to create a directory on the server called phpmailer to place all of these into.

  • load the class in your project:

    require_once('phpmailer/PHPMailerAutoload.php');

Done...

3 Comments

I did this as you suggestedbut itsgiving this error require_once(phpmailer/PHPMailerAutoload.php): Failed to open stream: No such file or directory Because there is no file naming PHPMailerAutoload.php
Whats your folder structure then? There is something wrong with your paths/directories.
@Bernhard As he suggested upload the language folder, class.phpmailer.php, class.pop3.php, class.smtp.php, and PHPMailerAutoload.php all into the same directory on your server Now there is no file naming PHPMailerAutoload.php. by extracting tha t zip file.
1

You have in your code:

            $check = $runUser->rowCount();
            if($check > 0) {
            $userRow = $runUser->fetch(PDO::FETCH_OBJ);
            $by = $userRow->name;
            }
        
            $insert_report = $con->prepare("
                INSERT INTO  `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')");
            
                $insert_report->bindparam(':m_id',$drug_id);
                $insert_report->bindparam(':p_id',$pat_id);
                $insert_report->bindparam(':time',$end_time);
                $insert_report->bindparam(':by',$by);

But if no rows are returned and $check is therefore 0, variable $by will not have been set. But you then continue with your logic to use $by for database insertion and for sending an email. I would think that this could possibly generate a database exception if column responsible is not nullable. In any case, this is clearly incorrect logic.

You also have lots of tests for the number of rows returned before you execute your while loops. These tests are really redundant: If the count of rows returned is 0, the while loop will exit immediately if you just test for the fetch statement returning FALSE. So the level of nesting can be reduced by removing those redundant checks.

The second problem is that your are reading column name from table users and storing it in varible $by. Yet the body of your email message references variuable $name, which has not been defined. I have tentatively replaced this with varibale $by. But only you can say whether that is correct or not. But clearly if not, then you need to initialize $name with its appropriate value.

$full_dt = date('Y-m-d H:i:s');
$dt = date('Y-m-d');
$dt_hr = date('H');
$check_timing = $con->prepare("SELECT medication, start_time, end_time FROM timings WHERE HOUR(end_time) = :end ");
$check_timing->bindparam(':end', $dt_hr);
$check_timing->execute();
while(($timingRow = $check_timing->fetch(PDO:: FETCH_OBJ)) !== FALSE) {
    $medication = $timingRow->medication;
    $start_time = $dt.' '. $timingRow->start_time;
    $end_time = $dt.' '.$timingRow->end_time;
    $timestamp = strtotime($end_time) + 60*60;
    $end_hour = date('Y-m-d H:i:s', $timestamp);
    $query = "SELECT a.location_code, b.* FROM patients a INNER JOIN medication b ON a.id = b.pat_id
             WHERE b.status != 2 AND b.directions = :med AND b.last_time NOT BETWEEN :start AND :end
             AND :crntime BETWEEN b.start_date AND b.end_date AND :crntime BETWEEN :end AND :end_hour";
    $statement = $con->prepare($query);
    $statement->bindparam(':med', $medication);
    $statement->bindparam(':start', $start_time);
    $statement->bindparam(':end', $end_time);
    $statement->bindparam(':crntime', $full_dt);
    $statement->bindparam(':end_hour', $end_hour);
    $statement->execute();
    while(($row = $statement->fetch(PDO:: FETCH_OBJ)) !== FALSE) {
        $drug_id = $row->drgid;
        $code = $row->location_code;
        $pat_id = $row->pat_id;
        $drug = $row->med_type.' - '.$row->drug.' ('.$row->strength.')';
        $dose = $row->dosage;
        $route = $row->route;
        $directions = $row->directions;
    
        $getUserName = "SELECT name FROM users WHERE FIND_IN_SET(location_code, :codes)>0 ";
        $runUser = $con->prepare($getUserName);
        $runUser->bindParam(':codes',$code);
        $runUser->execute();
        $userRow = $runUser->fetch(PDO::FETCH_OBJ);
        if ($userRow !== FALSE) {
            $by = $userRow->name;
    
            $insert_report = $con->prepare("
                INSERT INTO  `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')"
            );
            
            $insert_report->bindparam(':m_id',$drug_id);
            $insert_report->bindparam(':p_id',$pat_id);
            $insert_report->bindparam(':time',$end_time);
            $insert_report->bindparam(':by',$by);
            $insert_report->execute();
    
            $mail = new PHPMailer();
            $mail->isSMTP();
            $mail-> SMTPOptions = array (
                'ssl' => array (
                'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
              )
            );
            $mail->Host = "smtp.gmail.com";
            $mail->SMTPAuth = true;
            $mail->SMTPSecure = "tls";
            $mail->Port = "587";
            $mail->Username = "[email protected]";
            $mail->Password = "12345678";
            $mail->Subject = "Medication Report";
            $mail->setFrom("[email protected]",$by);
            $mail->isHTML(true);
            //Attachment
            //$mail->addAttachment('img/attachment.png');
            //Email body
            $mail->Body = "<h3>Medication Report by ($by) </h3></br>
                            You are being alerted that <b>$by</b> has missed their $directions Medication $row->med_type. And you may need to take appropriate action..";
            $mail->addAddress($to_email['Email_add']);
            $mail->send();
        }
    } // while($row = ...     
} //while $timingRow = ...

1 Comment

Sorry, The problem was in PHPMailer, my error reporting was off. Its inserting data normally by commenting PHPMailer function. It was inserting only one row and then giving error Fatal error: Uncaught Error: Class "PHPMailer" not found .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.