1

I am using PHPMailer to send emails with verification code. When I tried putting it inside a function and try to submit the form , the email is not being sent .

I have used the valid gmail ID for username , password and setFrom mail address.

$mail->Username   = 'abc@gmail.com';                
$mail->Password   = 'secret'; 
$mail->setFrom('abc@gmail.com', 'Test Email') 

but still the email is not being sent.

Is there something wrong in the code? Please if any one can help me with this.

<?php  

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

//Load Composer's autoloader
require 'vendor/autoload.php';

function sendmail($email,$v_code) {
  //Create an instance; passing `true` enables exceptions
  $mail = new PHPMailer(true);

  try {
    //Server settings
    $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      //Enable verbose debug output
    $mail->isSMTP();                                            //Send using SMTP
    $mail->Host       = 'smtp.gmail.com';                     //Set the SMTP server to send through
    $mail->SMTPAuth   = true;                                   //Enable SMTP authentication
    $mail->Username   = 'abc@gmail.com';                     //SMTP username
    $mail->Password   = 'secret';                               //SMTP password
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;            //Enable implicit TLS encryption
    $mail->Port       = 465;                                    //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`

    //Recipients
    $mail->setFrom('abc@gmail.com', 'Test Email');
    $mail->addAddress($email);     //Add a recipient
   
    //Content
    $mail->isHTML(true);                                  //Set email format to HTML
    $mail->Subject = 'Email verification code';
    $mail->Body    =  "click the link to verify<a href=''>click here</a>";
        
    $mail->send();
    return true;
  }
  catch (Exception $e) {
    return false;
  }
}

if(isset($_POST['signup-submit'])) {
  $username = $_POST['username'];
  $email = $_POST['email'];
  $password = $_POST['password'];
  $cnfmpwd = $_POST['repeatpsw'];
    
  if (empty($username)) {  
    header("Location: ../signup.php?error=requiredusername");
    exit();
  }
  else if (!filter_var($email, FILTER_VALIDATE_EMAIL) && !preg_match("/^[a-zA-Z0-9]*$/", $username)) {
    header("Location: ../signup.php?error=invaliedusernameemail");
    exit();
  }
  else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    header("Location: ../signup.php?error=invaliedemail");
    exit();
  }
  else if (!preg_match("/^[a-zA-Z0-9]*$/", $username)) {
    header("Location: ../signup.php?error=invalidusername");
    exit();
  }
  else if (empty($email)){
    header("Location: ../signup.php?error=requiredemail");
    exit();
  }
  else if (empty($password)){
    header("Location: ../signup.php?error=requiredpassword");
    exit();
  }
  else if (empty($cnfmpwd)){
    header("Location: ../signup.php?error=requiredcnfmpwd");
    exit();
  }
  else if ($password !== $cnfmpwd) {
    header("Location: ../signup.php?error=pwddonotmatch");
    exit();
  }
  else {
    $check_user="SELECT * FROM users WHERE username ='$_POST[username]' OR email = '$_POST[email]'";
    $result=mysqli_query($conn,$check_user);
    
    if($result) {
      if(mysqli_num_rows($result)>0)
      {
        $result_fetch = mysqli_fetch_assoc($result);
        if($result_fetch['username']==$_POST['username']) {
          header("Location: ../signup.php?error=usernameexists");
          exit();
        }
        else {
          header("Location: ../signup.php?error=emailexists");
          exit();
        }
      }
      else {
        $password = password_hash($_POST['password'], PASSWORD_BCRYPT);
        $v_code = bin2hex(random_bytes(16));
        $query = "INSERT INTO `users`(`username`, `email`, `password`, `verification_code`, `v_user`) VALUES ('$username','$email','$password','$v_code','0')";
    
        if(mysqli_query($conn,$query) && sendmail($email,$v_code) ) { // data inserted successfully
          header("Location: ../signup_success.php?signup=success");
          exit();
        }
        else { // if data cannot be inserted
          header("Location: ../signup.php?unsuccesss=unsuccesss");
          exit();
        }
      }
    }
  }
  mysqli_close($conn);  
}
else {
  header("Location: ../signup.php");
  exit();
} 
?>
ADyson
  • 57,178
  • 14
  • 51
  • 63
T.Z
  • 11
  • 2
  • 1
    So...what debugging have you done? What response do you get from PHP? Where does your (crazy) redirection system send you to? Are there any PHP errors? `catch (Exception $e) { return false; }` is really going to hinder you if an error occurs, because you're taking all that useful error info and just flushing it away. There shouldn't really be any reason to catch the error there but if you insist, then you must at least ensure the exception data is logged to a file so you can debug it later. – ADyson Aug 24 '23 at 12:41
  • 1
    P.S. See https://phpdelusions.net/articles/error_reporting for a sane approach to error handling, instead of the mess you've got above. – ADyson Aug 24 '23 at 12:42
  • 1
    Also: **Warning:** Your code is vulnerable to SQL Injection attacks. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. **Never** insert unparameterised data directly into your SQL. The way your code is written now, someone could easily steal, incorrectly change, or even delete your data. – ADyson Aug 24 '23 at 12:42
  • https://phpdelusions.net/mysqli also contains good examples of writing safe SQL using mysqli. See also the [mysqli documentation](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) and this: [How can I prevent SQL injection in PHP?](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) . Parameterising your queries will also greatly reduce the risk of accidental syntax errors as a result of un-escaped or incorrectly quoted input values. If you learnt your current technique from a tutorial or book, please don't use that resource again. – ADyson Aug 24 '23 at 12:42
  • Also see https://mailtrap.io/blog/phpmailer-gmail/ for an up to date way to connect to Gmail using PHPMailer, and ensure you'e following all the steps. Currently your code looks different, I don't know where you got the settings from. Also, to get a specific diagnosis of any problems within the email sending process, you can also follow the PHPMailer troubleshooting guide: https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting . Unless you've omitted a lot of info from your question, it seems you haven't really done much, if any, meaningful investigation into your issue yet. – ADyson Aug 24 '23 at 12:45
  • As I am new to PHP and still learning , i am trying with (MySQLi Procedural) method . Its not showing any errors or exceptions, when trying to submit the form ,its redirecting to the database connection page – T.Z Aug 24 '23 at 13:41
  • `As I am new to PHP and still learning , i am trying with (MySQLi Procedural) method`...that's fine, but regardless if you use procedural or OOP, you still need to parameterise your queries for safety and reliability. Learn to do it the correct way, not the wrong way. Then you don't have to un-learn your bad habits later. – ADyson Aug 24 '23 at 13:49
  • `its redirecting to the database connection page`...which of the many URLs listed in your code is it redirecting to? Be specific please. – ADyson Aug 24 '23 at 13:50
  • `Its not showing any errors or exceptions`...so have you a) enabled PHP error reporting, b) enabled mysqli error reporting, and c) removed that pointless try/catch from the sendmail() function? Do all that, and try again. Then also do some [debugging](https://www.atatus.com/blog/debugging-in-php/) to see what paths your code is taking, and ensure it actually gets to the `$mail->send();` command (and doesn't stop or deviate before then). And then use the PHPMailer troubleshooting guide, and the blog I mentioned above. **Then** you can come and report back to us. – ADyson Aug 24 '23 at 13:52
  • 1
    You should be getting noisy debug output from your mail function, which suggests it's not even getting there. Try calling your function with static values, isolated from all your other code, so that you can eliminate it from your debugging efforts. – Synchro Aug 24 '23 at 14:19
  • Some of your error checks can be done at the front-end (I am assuming you are using a HTML form). For example setting a "required" attribute for the username input field ensures the field cannot be empty. You can also set a regex pattern for HTML text input fields. – fat penguin Aug 25 '23 at 08:11
  • @fatpenguin True but that doesn't mean you can get rid of the server-side validation. Client-side validation in the browser can easily be by bypassed or disabled by anyone who wants to. – ADyson Aug 25 '23 at 08:33

2 Answers2

0

Your code looks mostly correct at a glance, but I can point out a couple of potential issues and improvements:

  1. Missing Connection to the Database: It seems that your code interacts with a database using SQL queries (mysqli_query). However, I don't see the part of your code where you establish a connection to the database using mysqli_connect before executing queries. Make sure you establish a database connection before querying the database.

  2. SMTP Secure Option: Gmail generally uses STARTTLS encryption on port 587. However, in your code, you have used ENCRYPTION_SMTPS which corresponds to port 465 and SSL/TLS encryption. Make sure you are using the correct combination of encryption and port for your SMTP configuration.

  3. Debugging: If the email is not being sent, consider enabling debugging for PHPMailer using $mail->SMTPDebug to get more insights into the issue.

Mian Asad Ali
  • 53
  • 2
  • 11
  • 1
    1.I have connected it to the database , but missed to include it here . 2. SMTP Secure Option , i have tried this option too .but its not working. 3. it shows no error , but when I submit the form it redirects to the database connection page. – T.Z Aug 24 '23 at 13:28
  • If the form submission is redirecting you to the database connection page, it indicates that the execution of your PHP script is failing somewhere. To see if there are any hidden errors, you can try adding the following lines at the beginning of your PHP script: error_reporting(E_ALL); ini_set('display_errors', 1); – Mian Asad Ali Aug 24 '23 at 16:06
  • Its giving below error Warning: require(vendor/autoload.php): Failed to open stream: No such file or directory in /Applications/XAMPP/xamppfiles/htdocs/DEMO/includes/signupcode.php on line 13 Fatal error: Uncaught Error: Failed opening required 'vendor/autoload.php' (include_path='.:/Applications/XAMPP/xamppfiles/lib/php') in /Applications/XAMPP/xamppfiles/htdocs/DEMO/includes/signupcode.php:13 Stack trace: #0 {main} thrown in /Applications/XAMPP/xamppfiles/htdocs/DEMO/includes/signupcode.php on line 13 – T.Z Aug 25 '23 at 08:04
  • @T.Z so that just means your autoload file is missing, or not in the location you've specified. Nothing to do with actually sending the email, it isn't even loading the phpmailer library. This is why you always need error reporting switched on when developing. I am continually baffled that people don't take this simple step at the start when setting up their environment. It's _essential_, to be able to make any progress and to spot problems. – ADyson Aug 25 '23 at 08:47
  • @ADyson I tried updating composer in the local host , but its giving the same error. – T.Z Aug 25 '23 at 10:47
  • @T.Z that information is too vague for anyone to tell if you if you did it correctly or not. Maybe delete this post, and start a new question focusing on the composer / autoload issue specifically. – ADyson Aug 25 '23 at 11:36
  • 2
    It's working now , I had to go back one directory to access autoload.php correctly '../vendor/autoload.php'; .. Thank you so much , PHP error reporting helped alot to figure out where exactly the issue is . – T.Z Aug 25 '23 at 12:16
  • @T.Z yes, that's what it's for! Glad you solved it :-) – ADyson Aug 25 '23 at 12:22
  • @T.Z I'm glad it worked for you. – Mian Asad Ali Aug 29 '23 at 15:57
-1

You need to enable 2 factor authentication in your settings (same place you used to see the less secure apps) then once you enable that you will see a new option called App Passwords - you can then create a app password that you would use for the SMTP settings