Creating a mechanism to validate emails - php

I already have an advanced user login/register system on my website (colemansystems.psm2.co.uk). However, I would like to have a email sent to new users for verification of their email address. If they have not clicked the link they will not be able to access their account. I am semi-experienced with PHP and MySQL, so please explain in depth.
The code I'm using for the verify.php file (the link the user click on with a GET (for example, verify.php?d=51773199320))
$secret = $_GET['d'];
$result = mysql_query("SELECT valid FROM users WHERE secret=$secret");
while ($row = mysql_fetch_array($result))
{
$valid = $row['valid'];
}
if ($valid == "") {
echo"There seems to be a problem with the verification code.<br><br><br><br><br>";
}
elseif ($valid == "1")
{
echo"Your account is already verified.<br><br><br><br><br>";
}
else
{
mysql_query("UPDATE users SET valid = '1' WHERE secret=$secret");
echo "Thank you, your account is now verified and you are free to use the exclusive features!<br><br><br><br><br><br>";
}
Is this secure?

The easiest way is not to register unverified users at all.
Ask them for an email address and send email with a link that contains this address sealed with a hash. Upon receiving this link you can start the registration process.
Something like this
$secret = "35onoi2=-7#%g03kl";
$email = urlencode($_POST['email']);
$hash = MD5($_POST['email'].$secret);
$link = "http://example.com/register.php?email=$email&hash=$hash";
And in your register.php add 2 hidden fields to the registration form - email and hash, storing their received values from GET.
Finally, process registration and check,
if (md5($_POST['email'].$secret) == $_POST['hash']) {
//Continue registration.
}

Easiest for whom - user, coder, computer?
What are you optimizing - the quantity of keypresses, the size of the code, the user experience?
The easiest to code is probably unsafe.
You should check the email address for correctness before sending a letter to it.

after registration create a hashed string and save it to the temporary user table send that hashed string to the user email address using this code
if(isset($_POST['register']))
{
$email_id=$_POST['email'];
$pass=$_POST['password'];
$code=substr(md5(mt_rand()),0,15);
mysql_connect('localhost','root','');
mysql_select_db('sample');
$insert=mysql_query("insert into verify values('','$email','$pass','$code')");
$db_id=mysql_insert_id();
$message = "Your Activation Code is ".$code."";
$to=$email;
$subject="Activation Code For Talkerscode.com";
$from = 'your email';
$body='Your Activation Code is '.$code.' Please Click On This link Verify.php?id='.$db_id.'&code='.$code.'to activate your account.';
$headers = "From:".$from;
mail($to,$subject,$body,$headers);
echo "An Activation Code Is Sent To You Check You Emails";
}
and after that create a verify page and then
if(isset($_GET['id']) && isset($_GET['code']))
{
$id=$_GET['id'];
$code=$_GET['id'];
mysql_connect('localhost','root','');
mysql_select_db('sample');
$select=mysql_query("select email,password from verify where id='$id' and code='$code'");
if(mysql_num_rows($select)==1)
{
while($row=mysql_fetch_array($select))
{
$email=$row['email'];
$password=$row['password'];
}
$insert_user=mysql_query("insert into verified_user values('','$email','$password')");
$delete=mysql_query("delete from verify where id='$id' and code='$code'");
}
}
if you have any problem here is a complete tutorial http://talkerscode.com/webtricks/account-verification-system-through-email-using-php.php

Related

Why is the else statement not working inside a foreach loop in php?

I'm building a script that helps a user reset their password if they forgot it. This specific script firstly checks if the email the user wants the token sent to exists. If it does, the token is inserted into a tokens table.
I am still developing and testing, so I haven't created the mail function yet.
I have an if statement that checks if the email exists, then creates the token. If it doesn't exists, it shows the page to enter an email address again. The if statement is working perfect, but the else is not. I'm pasting the entire file here, though it is only the part with the foreach statement that concerns our problem.
The else statement shows absolutely nothing.
<?php
//generate tokens to verify users who forgot their passwords. Send these tokens to the user's email
require $_SERVER['DOCUMENT_ROOT'] . "/phonebook/config.php";
//get user's email
$mail = htmlspecialchars($_POST['email']);
//generate token
$token = $token = openssl_random_pseudo_bytes(20);
//Convert the binary data into something more readable
$token = bin2hex($token);
//check if the email entered exists
$check = $conn->prepare("SELECT email FROM users WHERE email = :email");
$check->bindParam(":email", $mail);
$check->execute();
foreach ($check as $confirm) {
if ($confirm['email'] == $mail) {
//send tokens to the database
$sql = $conn->prepare("INSERT INTO tokens (email, token)
VALUES(:email, :token)");
$sql->bindParam(":email", $mail);
$sql->bindParam(":token", $token);
$sql->execute();
echo "<h2>Enter security code</h2>
A security code has been sent to the email addres $mail. Enter that code in the box below:
<form action = 'http://localhost/phonebook/controls/forgotpassword.php' method = 'post'>
<input type = 'hidden' name = 'email' value = '$mail'>
<input type = 'text' name = 'token'> <br>
<input type = 'submit' value = 'Reset password'>
</form>
Did not receive code? Go <a href = 'http://localhost/pages/forgotpassword.php'here</a>";
} else {
echo "That email does not exist. Please try again.";
include_once "$paste/phonebook/pages/forgotpassword.php";
}
}
Spotting three problems here.
You compare $mail which is encoded using htmlspecialchars() against an email address which is probably not encoded.
You fetch several rows instead of one:
//check if the email entered exists
$check = $conn->prepare("SELECT email FROM users WHERE email = :email LIMIT 1");
$check->bindParam(":email", $mail);
$check->execute();
$confirm = $check->fetch()
if (isset($confirm['email']) && $confirm['email'] === $mail) {
//send tokens to the database
You tell the "user" that the email address does exist in your system; this is a privacy and data security concern. Just send something like "If the entered email address is in our system, we just sent a password reset link to it."

email sent when logged out

I have a user login/registration system on my simple site everything works great but I would like to have a function that sends a generic email to the user when the logout button is clicked. probably saying something like please send us an email regarding your findings on our site.
the site is an entertainment agency that books out Carnival equipment, registration and login is purely for users to view prices should they be interested in the actual product.
i have no idea where or how to implement anything like this.
my understanding is i must create a query to the databases requesting email from email column and if user email address exist proceed with the email sending (if they are at the point of logout then that means email address is available in database) then once it is sent log user out and redirect to a page. i just dont know how to do the query exactly.
any advice would be much appreciated
ps, I don't know what documentation you would need to see in order to see what i have done?
this is my logout page:
<?php
require_once 'db.php';
session_start();
if (isset($_SESSION['username']) && !empty($_SESSION['username'])):
if (isset($_GET['action']) && !empty($_GET['action'])) {
$action = $_GET['action'];
if ($action == "logout") {
$stmt = $pdo->prepare("SELECT email FROM users WHERE email = ? ");
$stmt->execute([$_SESSION['username']]);
$email = $stmt->fetchColumn();
$message = "Hellow you just used our website....";
if (mail($email, "Feedback", $message)) {
// the email is sent now log the user out.
session_destroy();
header("location:login_page.php");
exit();
}
}
}
endif;
?>
You can follow the following steps to accomplish that
Step 1:
When the user logs in, save his Email ID in the session. I.e When the login ios successful you must be sending some "Success" response and redirecting to the user page.So, before doing that, if the login is successful create a session and store the Email Id in it.
login.php
<?php
session_start();
//Some database actions...
if($login == "success"){ // Just an example
$_SESSION["email"] = $EMAIL // This is the user Email Address.
}
?>
Step 2:
When the user logs out, he must be redirected to the logout page where you destroy all the sessions.You'll have to call the trigger mail function in that function.
In logout.php
<?php
session_start();
$EMAIL = $_SESSION["email"] // Get the previously saved email in login process.
triggerMail($EMAIL);
session_unset();
session_destroy();
header("location:home.php");
exit();
function triggerMail($email){
//Your email logic.. return either true or false.
}
?>
When the user successful log's in if they are using their email address to login then store that email address on a session. Then on logout before destroying the session send the email to the email stored in the session.
Then have a logout link like this :
Logout
then you can verify the action on that logoutpage if user wanna logout.
<?php
session_start();
if (isset($_SESSION['currentUser']) && !empty($_SESSION['currentUser'])):
if (isset($_GET['action']) && !empty($_GET['action'])) {
$action = $_GET['action'];
if ($action == "logout") {
$message = "Hellow you just used our website.... what ever you want to write";
if (mail($_SESSION['currentUser'], "Feedback", $message)) {
// the email is sent now log the user out.
session_destroy();
header("location:loginPage.php");
exit();
}
}
}
endif;
?>
NB : $_SESSION['currentUser'] is the session you created when the
user was logging and stored their email.
Well if you not using email address as username for login then then you can query the email address before user log's out. then send email then logout.
<?php
session_start();
if (isset($_SESSION['currentUser']) && !empty($_SESSION['currentUser'])):
if (isset($_GET['action']) && !empty($_GET['action'])) {
$action = $_GET['action'];
if ($action == "logout") {
$stmt = $dbh->prepare("SELECT email FROM users WHERE userID = ? ");
$stmt->execute([$_SESSION['currentUser']]);
$email = $stmt->fetchColumn();
$message = "Hellow you just used our website....";
if (mail($email, "Feedback", $message)) {
// the email is sent now log the user out.
session_destroy();
header("location:loginPage.php");
exit();
}
}
}
endif;
?>
I' m not quit sure which API you are using MYSQLI or PDO as you did not specify much on your question, the above uses PDO.

PHP: The page isn’t redirecting properly, Too many redirects

I tried implementing a system wherein the user enters his username and phone number, when the form is submitted, it checks the database to verify the number and username based on it's existence. An SMS is sent to that number. He gets a popup to enter the OTP code.
However on entering the OTP code I get an error of redirecting loops. I'll just explain the flow of the files below:
INDEX.PHP -> LOGIN.PHP -> OTP.PHP -> CHECK_OTP.PHP -> HOME.PHP
Those are the files being used. It reaches the otp page and when you enter, it does authenticate successfully but it goes into a loop. I will post the code to see what is wrong with the OTP authentication code.
session_start(); // Starting Session
$error=''; // Variable To Store Error Message
if (isset($_POST['verify'])) {
if (empty($_POST['otp'])) {
$error = "OTP is invalid";
}
else
{
// Post OTP
$otp=$_POST['otp'];
}
$otp = stripslashes($otp);
$otp = pg_escape_string($otp);
$check = "select * from otp where otp = '$otp'";
$ret_check = $dbConnection->executeQuery($check);
$ret_num = $dbConnection->numRows($ret_check);
$cust_code = '';
while($row = $dbConnection->fetchRow($ret_check)){
$cust_code = $row[0];
}
$cust_code;
if($ret_num != 1){
$error = "Wrong OTP entered";
header("Location: otp-home.php");
}
else {
echo $_SESSION['login_user'] = $cust_code;
header("Location: home.php");
}
I hope this is enough. If anything else is required. Please let me know. Any help will be greatly appreciated. Thank you

Php/sqli executed by referencing the link in a send email function?

So i have this page called unsubscribe_process which when given a url query, e.g. www.example.com/unsubscribe_process.php?passkey=123, it will then find and delete the member using mysqli.
The problem I am having is with my unsubscribe.php page. It includes a form and allows the user to put in their email. The form will be submitted, and then an email is sent to the user linking the unsubscribe_process.php page with the specific query and passkey for that user. The hope would be then the user checks their email and clicks the link and then the unsubscribe_process page would remove them from the database.
Back to subscribe.php page, it has no DELETE slqi function anywhere in it, however somehow the user gets deleted after submitted the form. It seems to execute the www.example.com/unsubscribe_process.php?passkey=123 within subscribe.php, without the user having to click on it in the email.
Here is the function that is executed once a user submits their email:
function sendEmail() {
//enter details into db automatically
$con = #require './../dbcon.php';
// Check connection
if (mysqli_connect_errno($con))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
else
{
$email = mysqli_real_escape_string($dbConnection, $_POST['email']);
$atIndex = strrpos($email, "#");
$emailindex = substr($email, 0, $atIndex);
if ($email=='')
{
echo "<p>No Username has been specified. Please <a href=http://www.example.com/unsubscribe.php> try again.</a></p>";
}
//check if username exists in database
$result = mysqli_query($DB,"SELECT * FROM members WHERE user='". $emailindex ."'") or die(mysql_error());
if (mysqli_num_rows($result) > 0) {
$row = mysqli_fetch_array($result);
$passkey = $row['confirmcode'];
//if password is set then erase password and send an email to user to update details/create new password.
if ($row['paid'] ==1){
$to=$email;
$subject="Unsubscribe";
$header="from: webmaster#example.com";
$message.="You can now unsubscribe yourself in one click with the following link: \r\n";
$message.="http://www.example.com/unsubscribe_process.php?passkey=$passkey\r\n\r\n";
$sentmail = mail($to,$subject,$message,$header);
if($sentmail){
echo "</br><p class='maintextSubmit' align='center'> Please check your email to complete the process.</p>";
}
else echo "</br><p class='maintextError' align='center'> An error occurred. Please try again.</p>";
}
mysqli_close($DB);
}
}
}
SO: Does php execute the link for me when sending the email? This is literally the only reference to the unsubscribe_process.php page anywhere on the subscribe.php page. Why does the unsubscribe_process.php?passkey=$passkey get executed when the email is sent? How can I prevent this from happening (aka only when the link is clicked via the email)? Am I missing something?

Verification link not activating account

So I've sent a link after registration to Verify an account, the link contains the users email address and a 32 character code for example:
$to = $email;
$subject = 'Signup | Verification';
$message = '
Thanks for signing up!
Your account has been created, you can login with the following credentials after you have activated your account by pressing the url below.
------------------------
Username: '.$username.'
Password: '.$password.'
------------------------
Please click this link to activate your account:
localhost:8888/website/verify.php?email='.$email.'&hash='.$hash.'
';
$headers = 'From:myemail#email.com' . "\r\n";
mail($to, $subject, $message, $headers);
That all seems to work fine I'm receiving the email with a link like this:
http://localhost:8888/website/verify.php?email=myemail#email.com&hash=fe646d38bc2145ca6c3cf77d52820cd0
The problem comes when I follow the link and try to activate the account. It takes me to Verify.php fine but I keep getting Invalid Approach and I'm unable to set Validation to 1.
<?php include "includes/base.php"; ?>
<?php
if(isset($_GET['Email']) && !empty($_GET['Email']) AND isset($_GET['Hash']) && !empty($_GET['Hash'])){
$email = mysql_escape_string($_GET['Email']);
$hash = mysql_escape_string($_GET['Hash']);
$search = mysql_query("SELECT Email, Hash, Validation FROM users WHERE Email = '".$email."' AND Hash = '".$hash."' AND Validation = 0") or die(mysql_error());
$match = mysql_num_rows($search);
if($match > 0){
mysql_query("UPDATE users SET Validation = 1 WHERE Email = '".$email."' AND Hash = '".$hash."' AND Validation = 0") or die(mysql_error());
echo "Your account has been activated, you can now login";
}else{
echo "The url is either invalid or you already have activated your account.";
}
}else{
echo "Invalid approach, please use the link that has been sent to your email.";
}
?>
1) this code is unsecure as it has SQL injection problem. Use prepared statements
Please keep in mind that mysql_* functions are no longer supported and they are depriated
2) Regarding your code I found that your GET request has 'email' and 'hash' all lowercase, but in PHP code you use $_GET['Email'] and $_GET['Hash'].
You need to change this:
if(isset($_GET['Email']) && !empty($_GET['Email']) AND isset($_GET['Hash']) && !empty($_GET['Hash'])){
$email = mysql_escape_string($_GET['Email']);
$hash = mysql_escape_string($_GET['Hash']);
To this
if(isset($_GET['email']) && !empty($_GET['email']) AND isset($_GET['eash']) && !empty($_GET['eash'])){
$email = mysql_escape_string($_GET['email']);
$hash = mysql_escape_string($_GET['eash']);
or change your GET request to the next one:
http://localhost:8888/website/verify.php?Email=myemail#email.com&Hash=fe646d38bc2145ca6c3cf77d52820cd0
Change Hash to hash & Email to email. (Capitalized, but not in link that you send)
Also, your code is prone to sql injection attack as you are directly using the values in the url to query your database. Please use mysql_real_escape_string and perform some sanity checks before making the query.
there's capitals in the PHP whereas there are none in the link
$_GET['Email']
verify.php?email=myemail#email.com

Categories