Updating Mysql Database for Password Reset

The only challenge I’m having with the code below is that the update query doesn’t work. I want the generated key stored in the database against the selected email address so that the stored key and the one sent via email to the user who forgot his password can be compared and if they are the same, he can be presented with password update form. Thanks all.

<?php require_once 'classes/Config.php'; require_once 'classes/DatabaseManager.php'; $result = new ECConfig(); $result->getSiteName(); $result->getSiteNickName(); $result->getWebUrl(); $error = array(); if((isset($_POST['button']) && ($_POST['button']) == 'Go') && ($_POST['email-address']) == '') { header('Location: .'); } if(isset($_POST['button']) && ($_POST['button']) == 'Go') { if (empty($_POST['email-address'])) { $error[] = 'Please Enter your Email '; } else { if (preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/", $_POST['email-address'])) { //regular expression for email validation $email = $_POST['email-address']; } else { $error[] = 'Your Email Address is invalid '; } } // connect to the database $conn = DatabaseManager::getConnection(); $sql = "SELECT email FROM user WHERE email = ?"; $st = $conn->prepare($sql); // bind variables when executing statement $st->execute(array($email)); // if a match is found, rowCount() produces 1, which is treated as true $row = $st->fetch(); $email = $row['email']; //Create a key and store in the database for the selected email address // Create a unique activation code: $key = md5(uniqid(rand(), true)); //Update the database with the token key for the selected email address try { $sql = "UPDATE `user` SET `key` = :key WHERE `email` = :email LIMIT 1"; $stm = $conn->prepare($sql); $stm->bindValue(':key', $key); $stm->bindValue(':email', $email); $stm->execute(); } catch(PDOException $e) { $error[] = "Your password cannot reset for now, please try again later"; } if($st->rowCount()) { require_once 'lib/swift_required.php'; // Create the Transport $transport = Swift_SmtpTransport::newInstance('mail.me.com', 25) ->setUsername('**********') ->setPassword('**********') ; // Create the Mailer using your created Transport $mailer = Swift_Mailer::newInstance($transport); // Create a message $message = Swift_Message::newInstance('Reset Your Password') ->setFrom(array('info@me.com' => 'Pope')) ->setTo(array('you@yahoo.com')) ->setBody("To have access to change your account's password, please click on this link: " . $result->getWebUrl() . '/my-web-account' . '/update-password/?email=' . urlencode($email) . "&key=$key" ) ; // Send the message $result = $mailer->send($message); header('Location: ../success/'); } // if no match, destroy the session and prepare error message else { $error[] = 'There is an error, please try again'; exit(); } } ?>

Can you expand on “the update query doesn’t work”? Does it throw an error, in which case what’s the error message? If you type the query in with good values from phpmyadmin (or whatever you use) does the query work there? Is the ‘key’ column big enough for the MD5 hash? If you follow the code through with echo() debugging statements, does that not help show where things go wrong? Presumably you get the email with an appropriate key value in it?

general note: PDO must explicitly be set to throw exception, otherwise they are silently ignored.

1: Dont rely on a submit button being in the $_POST array. IE has issues with that when someone uses Enter to submit a form.

2:

You’re not checking rowCount() until much later, you’re assuming a row exists, and then setting the email to the value of the row which… you used to search the database. So… that’s a redundant pair of statements at the bottom there, and you might want to wrap the whole update thing inside the later if.

3: LIMIT 1 is redundant because presumably email is a unique field in the table. Right? Same as Key?
4: Check that $key and $email contain what you think they contain; you may also want to explicitly declare them as type PDO::PARAM_STR in your bind so that the system doesnt get confused.
5: Check $stm->errorInfo() after the execute to see if your database kicked back a problem.

Thanks a lot guys for your offer to help and suggestions. The query actually works. I guess my system memory was already clogged last night while working on it. I re-launched now and it working fine nevertheless, I will implement your suggestions. If I encounter any other issue, I will let you guys know but for now, the update query is working.

Thanks. I was really trying to get the OP to give a bit more information rather than just saying “doesn’t work”. I figured the try-catch around the query might have given an error, is that not the case? Seems as if it was just a weird test server thing in any case.

try…catch in PDO works in exactly 2 cases

  1. the PDO constructor always throws an exception (because you can only set the error handling after the connection is established)
  2. PDO’s error handling mode is set to exceptions (the default is no error handling, the other option is to emit PHP errors (which ignore try…catch completely)

The try/catch didn’t give any error message, It simply wasn’t updating but the email get sent.

Thanks a lot guys, everything is working fine now. Thanks for your advise and suggestions.