Jump to content

PHPMailer


Olumide

Recommended Posts

I have an admission application form, and I want an email and SMS notification to be sent to the applicant's email and phone upon successful registration. I have tried using the mail() function, but I am not receiving any email notifications at the recipient's email. I also tried using Gmail, but none of them are working.

I used Composer to install the vendor autoload, but it is still not working. I don't know where the error is coming from.

Below are the tables and the code:

Table

CREATE TABLE applicants (
    id INT AUTO_INCREMENT PRIMARY KEY,
    application_id VARCHAR(20) UNIQUE,
    surname VARCHAR(100),
    othername VARCHAR(100),
    dob DATE,
    phone VARCHAR(20),
    email VARCHAR(100),
    lga VARCHAR(100),
    state_origin VARCHAR(100),
    current_school VARCHAR(100),
    current_class VARCHAR(50),
    proposed_class ENUM('Year 7 (JSS1)', 'Year 8 (JSS2)', 'Year 10 (SS1)', 'Year 11 (SS2)', 'Year 1 (PRY 1)', 'Year 2 (PRY 2)', 'Year 3 (PRY 3)', 'Year 4 (PRY 4)'),
    status VARCHAR(20) DEFAULT 'Pending'
);

CREATE TABLE exam_dates (
    id INT AUTO_INCREMENT PRIMARY KEY,
    exam_date DATE,
    type ENUM('Online', 'On-site'),
    is_past BOOLEAN DEFAULT FALSE
);

CREATE TABLE exam_registrations (
    id INT AUTO_INCREMENT PRIMARY KEY,
    applicant_id INT,
    exam_date_id INT,
    FOREIGN KEY (applicant_id) REFERENCES applicants(id),
    FOREIGN KEY (exam_date_id) REFERENCES exam_dates(id)
);

ALTER TABLE applicants ADD registered_on DATETIME;

 

PHP

<?php
session_start();
require_once('db_config.php');
//require_once(__DIR__ . '/../vendor/autoload.php');
require_once('vendor/autoload.php');

// Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// Fetch available exam dates from the database
try {
    $stmt = $pdo->query("SELECT * FROM exam_dates WHERE is_past = FALSE");
    $exam_dates = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
}

// Check if the user is logged in as an applicant
if (!isset($_SESSION['user_type']) || $_SESSION['user_type'] !== 'applicant') {
    header("Location: login.php");
    exit();
}

// Logout logic
if (isset($_POST['logout'])) {
    session_destroy(); // Destroy all session data
    header("Location: login.php"); // Redirect to the login page
    exit();
}

// Set the applicant_id from the applicants table
try {
    $username = $_SESSION['username'];
    $stmt = $pdo->prepare("SELECT * FROM applicants WHERE application_id = ?");
    $stmt->execute([$username]);
    $applicant = $stmt->fetch(PDO::FETCH_ASSOC);
    $_SESSION['applicant_id'] = $applicant['id'];
    $applicant_email = $applicant['email']; // Store the applicant's email address
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
    exit();
}

// Check if the applicant has already registered for an exam date
try {
    $stmt = $pdo->prepare("SELECT * FROM exam_registrations WHERE applicant_id = ?");
    $stmt->execute([$applicant['id']]);
    $registered_exam_dates = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
}

// Handle exam registration
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['exam_date'])) {
    // Check if the applicant has already registered for an exam date
    if (!empty($registered_exam_dates)) {
        //echo "You have already registered for an exam date.";
        exit();
    }

    $applicant_id = $_SESSION['applicant_id'];
    $exam_date_id = $_POST['exam_date'];

    // Insert exam registration details into exam_registrations table
    try {
        $stmt = $pdo->prepare("INSERT INTO exam_registrations (applicant_id, exam_date_id) VALUES (?, ?)");
        $stmt->execute([$applicant_id, $exam_date_id]);
        // Redirect to exam confirmation page or show success message
        header("Location: exam_confirmation.php");

        // Send SMS to applicant
        $message = "Thank you for your application. Your username is: " . $applicant['application_id'] . " and Password is your surname.";
        $api_url = 'my api url';
        $token = 'my token';
        $sender = 'Olu';
        $recipient = $applicant['phone'];
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $api_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => array(
                'token' => $token,
                'sender' => $sender,
                'to' => $recipient,
                'message' => $message,
            ),
        ));
        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        if ($err) {
            echo 'cURL Error #:' . $err;
        } else {
            echo 'SMS sent successfully.';
        }

        // Send email notification to applicant using PHPMailer
        sendEmailNotification($applicant_email, $applicant['application_id'], $applicant['surname']);

        exit();
    } catch(PDOException $e) {
        echo "Error: " . $e->getMessage();
    }
}

// Function to send email notification using PHPMailer
function sendEmailNotification($recipientEmail, $applicationId, $surname) {
    // Instantiate PHPMailer
    $mail = new PHPMailer(true);

    try {
        // SMTP configuration (Gmail)
        $mail->isSMTP();
        $mail->Host = 'smtp.gmail.com';
        $mail->SMTPAuth = true;
        $mail->Username = 'olu@gmail.com'; 
        $mail->Password = 'mypassword'; 
        $mail->SMTPSecure = 'tls';
        $mail->Port = 587;

        // Email content
        $mail->setFrom('olu@gmail.com', 'My Schol');
        $mail->addAddress($recipientEmail);
        $mail->Subject = 'Application Registration Confirmation';
        $mail->isHTML(true);
        $mail->Body = "Dear $surname,<br><br>Thank you for your application at my Schol. Your username is: $applicationId and Password is your surname.<br><br>Best regards,<br>My Schol";

        // Send email
        $mail->send();
        echo 'Email sent successfully!';
    } catch (Exception $e) {
        echo "Error: {$mail->ErrorInfo}";
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Applicant Dashboard</title>
   
    <script>
        // JavaScript function to display a popup
        function displayPopup() {
            alert("You have already registered for an exam date.");
        }
    </script>
</head>
<body>
    <h2>Welcome, <?php echo $applicant['surname']; ?></h2>
    <!-- Display applicant information -->
    <p>Applicant's Name: <?php echo $applicant['surname'] . ' ' . $applicant['othername']; ?></p>
    <p>Application ID: <?php echo $applicant['application_id']; ?></p>
    <p>Date of Birth: <?php echo $applicant['dob']; ?></p>
    <p>Phone: <?php echo $applicant['phone']; ?></p>
    <p>Email: <?php echo $applicant['email']; ?></p>
    <p>Local Government Area: <?php echo $applicant['lga']; ?></p>
    <p>State of Origin: <?php echo $applicant['state_origin']; ?></p>
    <p>Current School: <?php echo $applicant['current_school']; ?></p>
    <p>Current Class: <?php echo $applicant['current_class']; ?></p>
    <p>Proposed Class: <?php echo $applicant['proposed_class']; ?></p>
    <!-- Selected exam date -->
    <p>Selected Exam Date: 
        <?php 
        if (!empty($registered_exam_dates)) {
            $selected_exam_date_id = $registered_exam_dates[0]['exam_date_id'];
            foreach ($exam_dates as $date) {
                if ($date['id'] == $selected_exam_date_id) {
                    echo date('F j, Y', strtotime($date['exam_date'])) . " (" . $date['type'] . ")";
                    break;
                }
            }
        } else {
            echo 'Not selected';
        }
        ?>
    </p>

    <hr>

    <!-- Exam date selection -->
    <h3>Exam Date Selection</h3>
    <form id="exam_form" method="post">
        <label for="exam_date">Select Exam Date:</label><br>
        <select id="exam_date" name="exam_date">
            <?php foreach ($exam_dates as $date) : ?>
                <option value="<?php echo $date['id']; ?>"><?php echo $date['exam_date'] . " (" . $date['type'] . ")"; ?></option>
            <?php endforeach; ?>
        </select><br><br>
        <input type="button" value="Register for Exam" onclick="checkExamRegistration()">
        <!--<input type="submit" value="Register for Exam">-->
    </form>

    <!-- Application status -->
    <h3>Application Status</h3>
    <p>Status: <?php echo $applicant['status']; ?></p>
   

    <!-- Logout form -->
    <form method="post">
        <input type="submit" name="logout" value="Logout">
    </form>
     <script>
        // Function to check if the applicant has already registered
        function checkExamRegistration() {
            <?php if (!empty($registered_exam_dates)): ?>
                displayPopup();
            <?php else: ?>
                document.getElementById("exam_form").submit();
            <?php endif; ?>
        }
    </script>
</body>
</html>

 

Link to comment
Share on other sites

i recommend that you make a new file with the code necessary to load the phpmailer script and with your sendEmailNotification() function in it, setup some test data, and call the sendEmailNotification() function and get the email to work. once you get the email to work on its own, then make sure that your full code is actually calling the sendEmailNotification() function, by echoing/logging a value at the completion of the email code.

you are performing a redirect right after the INSERT query. it's possible that the sms code will take enough time to make the curl request that the browser can abort the current request and halt code execution before your code gets to the email code. it's also possible that the curl code is throwing an error and your code never gets to the email code. any such redirect needs to be at the end of the post method form processing code, it should only occur if there are no user/validation errors, and it should be to the exact same URL of the current page to cause a get request for that page.

here's a list of things that will simplify the code, making it easier to see what the code is trying to do -

  1. you should only catch and handle database exceptions for user recoverable errors, such as when inserting/updating duplicate user submitted data. for all other insert/update query error numbers, just rethrow the exception and let php handle it and for all other type of queries, let php catch and handle any database exception. for the INSERT query you should be catching and testing for a duplicate index error number. if an applicant can only register once, the applicant_id column should be defined as a unique index, so that only one record per applicant_id can be inserted. if an applicant can only register for a single exam_date_id, the combined applicant_id and exam_date_id columns need to be defined as a composite unique index.
  2. if you set the default fetch mode to assoc when you make the database connection, you won't have to specify it in each fetch statement.
  3. don't copy variables to other variables for nothing. just use the original variables that data is in.
  • Like 1
Link to comment
Share on other sites

I don't know what your development platform is, but there are many issues with email deliverability that will be hard to diagnose.  For this reason, I highly recommend using a local mail catcher/debugger with one of the best known being Mailhog.  Unfortunately mailhog seems to be an abandoned project, so a newer one that is currently maintained is mailpit.

Assuming that you have docker installed, you can start mailpit easily using docker run:

docker run -d \
--restart unless-stopped \
--name=mailpit \
-p 8025:8025 \
-p 1025:1025 \
axllent/mailpit

This will start what looks to client code like an SMTP server available at localhost:1025, and there will be an admin web interface that shows you the emails that are received on port localhost:8025.

You would need to change your phpmailer setup slightly for testing, so that you send mail to localhost and port 1025.  I don't know if TLS support works or not so you may need to disable the tls settings.

I also think it would help you if you studied the concept of dependency injection.  For example, whenever you have a method or function that is doing something like this:

 

// Function to send email notification using PHPMailer
function sendEmailNotification($recipientEmail, $applicationId, $surname) {
    // Instantiate PHPMailer
    $mail = new PHPMailer(true);

That should be a sign to you that you probably want to use dependency injection instead.

Best practices at this point are to move credentials out of your code base and into .env files or something similar.  Having credentials in your code is another vector for security exploitation. If someone gets access to your source code, they have everything they need to connect to your server or in a case like this, send emails to an account.

They also make having different environments (dev/test/stage/production) each with different configurations that isolate them from each other.  Hopefully you are not developing and testing in production!

Most of what you are doing in sendEmailNotification() is setting up PHPMailer.  You should move all of that code out into a configuration routine that reads configuration variables from a .env or perhaps a simple php configuration file.  

Instead of what you are currently doing, you should create and configure your phpmailer object outside the sendEmailNotification function, and pass it as a dependency.

 

// Function to send email notification using PHPMailer
function sendEmailNotification(PHPMailer $mail, $recipientEmail, $applicationId, $surname) {

 

You could add a simple function that configures and returns a PHPMailer object, and reads in configuration variables in some other way.  There are plenty of libraries out there, to read .ini files, or dotenv etc.

Link to comment
Share on other sites

To troubleshoot the email sending issue, first, verify that your SMTP configuration for Gmail is accurate, including the username, password, host, port, and encryption method (TLS). Ensure that you've enabled access for less secure apps in your Gmail settings. Additionally, set PHPMailer's SMTPDebug property to 2 to enable detailed error reporting. Double-check the recipient email address for correctness. Temporarily comment out the SMS sending code to isolate the problem. Finally, test your email sending code in a development environment to identify any potential issues with your production setup.

$mail->SMTPDebug = 2; // Enable detailed error reporting
// Verify SMTP configuration settings for Gmail
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = 'olu@gmail.com'; 
$mail->Password = 'mypassword'; 
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

Best Regard

Danish hafeez | QA Assistant

ICTInnovations

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.