This question already has answers here:
PHP mail function doesn't complete sending of e-mail
(31 answers)
Closed 6 years ago.
So I'm making a registration/login/you know what I'm talking about system, and I need to verify the user's email addresses in case they forget their password. To do that, I assign them a random PIN which gets sent to them by email. Then, they enter that PIN in the account activation page and yay their account becomes active.
Now, my problem is the e-mail just isn't sending.
I'm using PHP 5.5 on Hostinger, my MX records aren't set up but from the questions that I've read about this, it's not what's causing the problem. Here is the code:
<?php
// connect to database, I'll omit the details because no one cares
$pin=rand(1000,9999);
$email=$_POST['email'];
$rawUser=$_POST['user'];
$user=// hash username but I'm not gonna tell you how because safety reasons
$rawPassA=$_POST['pass1'];
$rawPassB=$_POST['pass2'];
if($rawPassA==$rawPassB){
// hash password, again I'm not gonna tell you how
} else{
echo "<script type='text/javascript'>
window.location.href = 'http://komodokrew.ml/error/login/pass_no_match';
</script>";
};
$first=$_POST['first'];
$checkForUserQuery='SELECT count(*) FROM tableNameThatImNotGonnaTellYouBecauseSqlInjection WHERE user = \'' . $user . '\';';
$checkForUser=mysql_query($checkForUserQuery);
$checkForUserA=mysql_fetch_row($checkForUser);
$checkForUserF=$checkForUserA[0];
if($checkForUserF==0){
$query='INSERT INTO tableNameThatImNotGonnaTellYouBecauseSqlInjection (`user`,`first_name`,`pin`,`password`,`email`,`active`) VALUES (\'' . $user . '\',\'' . $first . '\',' . $pin . ',\'' . $pass . '\',\'' . $email . '\',1);';
mysql_query($query);
$subject='KomoDoKrew - account activation';
$message='You have recently registered an account on KomoDoKrew, under the username ' . $rawUser . '. Please activate your account by visiting komodokrew.ml/activate and entering the following PIN code, your username, and your password. PIN code: ' . $pin . '. Thank you for registering an account with KomoDoKrew! Make sure to join the community at komodokrew.ml/forum.';
$from='admin#komodokrew.ml';
$headers='From:' . $from;
mail($email,$subject,$message,$headers);
echo "<script type='text/javascript'>
window.location.href = 'http://komodokrew.ml/success/login/register';
</script>";
} else{
echo "<script type='text/javascript'>
window.location.href = 'http://komodokrew.ml/error/login/user_exists';
</script>";
};
mysql_close();
?>
Also, yes I KNOW that I'm vulnerable to SQL injections, I'm working on learning prepared statements and PDO, and yes I KNOW that mysql_* is way outdated, I'm working on learning the new PDO stuff, okay? But even if they SQL-injected me, it redirects them after they register anyways, and passwords and usernames are hashed with a varying salt several hundreds of thousands of times, so I'm not too worried at the moment.
This is the typical log that's sent in php_mail.log:
[23-Nov-2016 22:20:28 UTC] mail() on [/home/u964873932/public_html/register/register.php:40]: To: <myEmailAddressThatImNotGonnaTellYou> -- Headers: From:admin#komodokrew.ml
It's not a problem with PHP not being able to get the POST, because the email address of the user gets entered in the database successfully.
Thanks!
I would recommend to do 2 things first:
1. Enable error log:
error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");
2. And change the line where you are sending email
$status = mail($email,$subject,$message,$headers);
if($status)
{
echo '<p>Your mail has been sent!</p>';
} else {
echo '<p>Something went wrong, Please try again!</p>';
}
Then see if you got any error if no error then Follow this answer: PHP mail form doesn't complete sending e-mail
Related
I have a little bit of a problem with a password hash not being updated in a database and I'm struggling to see what I've done wrong. If anyone could help it would be much appreciated.
Basically I have a login.php script, which used to just employ md5 and salt to a user's password and store it in a mysql db, which I know is out of date. So I've recently tried to update it to update users passwords to PHP password_hash when they next log in.
I first collect the password via post then call the db to compare it to the hash in the db. If the password verifies I then run the db password through password_needs_rehash to check if it needs rehashing. If it does then it'll generate a new has and store this to a variable to be run through a mysqli prepared statement that updates the hash along with the time they've last logged in, otherwise it'll just update the db with the last login.
It seems to fail to update the new hash (even though I've checked it is generated) but still updates the time in the query. There are no emails coming through from the exception code or any php errors to report.
// Check if a newer hashing algorithm is available or if the cost has changed
if (password_needs_rehash($dbpass, PASSWORD_DEFAULT, $cost)) {
// If so, create a new hash, and replace the old one
$newHash = password_hash($password, PASSWORD_DEFAULT, $cost);
}
//update last login date
date_default_timezone_set("Europe/London");
$servertime = date("Y-m-d H:i:s");
// connect to db for mysqli
require('../dbconn/user.php');
// query to update password, increment number of logins and set last login date for user
$update_pass_stmt = $mysqli->stmt_init();
// if new hash has been generated
if (isset($newHash)) {
$q = "UPDATE users SET theirpassword=?, lastlogin=? WHERE email=? LIMIT 1";
if ($update_pass_stmt->prepare($q)) {
$update_pass_stmt->bind_param('sss', $newHash, $servertime, $email);
$update_pass_stmt->execute();
$update_pass_stmt->close();
}
} else {
$q = "UPDATE users SET lastlogin=? WHERE email=? LIMIT 1";
if ($update_pass_stmt->prepare($q)) {
$update_pass_stmt->bind_param('ss', $servertime, $email);
$update_pass_stmt->execute();
$update_pass_stmt->close();
}
}
if ($mysqli->error) {
try {
throw new Exception("MySQL error $mysqli->error <br> Query:<br> $q", $mysqli->errno);
} catch(Exception $e) {
$mess = "Error No: ".$e->getCode(). " - ". $e->getMessage() . "<br >";
$mess .= nl2br($e->getTraceAsString());
$contact_email = "webmaster#example.co.uk";
$message_sub = "Mysqli Login Query Error [EN-UUTIME01]";
$hdrs = "From: " . $contact_email . "\r\n";
$hdrs .= "Reply-To: ". $contact_email . "\r\n";
$hdrs .= "MIME-Version: 1.0\r\n";
$hdrs .= "Content-Type: text/html; charset=UTF-8\r\n";
mail($contact_email, $message_sub, $mess, $hdrs);
}
$mysqli->close();
$_SESSION['internalerror'] = TRUE;
header("Location: ". $MM_redirectLoginFailed );
exit();
}
$mysqli->close();
I've echoed out in each section of the code and it seems to be running through to the correct sql statement.
I can only think I've either missed an obvious typo or I've got my logic wrong somewhere.
Any help always appreciated, thank you.
Well as embarassing as it may be, I found the solution to my issue. The email variable I was passing into the query was empty. I'd named it differently earlier on in my code!
Although, why I didn't get a query error email or log anywhere I'm not sure still... see my comment with #RyanVincent above.
Thanks all for taking the time to look over the code!
my IF statements in this code are working, but the ELSE statement NEVER processes...and I am not sure why....in fact all of the code processes up until the ELSE statement, and the captua works properly too, if the captcha is right, the user gets a positive message and the data is posted to the database. If the captcha is wrong, no information is posted, but no message is given either..please help:
if(isset($_POST["captcha"]))
if($_SESSION["captcha"] == strtolower($_POST["captcha"]))
if(mysql_query($sql)) {
echo "<script type='text/javascript'>alert('submitted successfully, The records manager will provide you with your record within 3 days!')</script>";
//mail('joe.blow#idaho.com', 'SRRS - New Records Await Processing', 'SRRS - There are new records for processing in the SRRS System' );
//$to = 'joe.blow2#idaho.com' . ', ';
//$to .= $email;
$to = "joe.blow3#idaho.com";
$subject = "SRRS NOTIFICATION - New Student Record Await Processing";
$message = "New Student Record Requests have been submitted and Await Processing";
$from = "joe.blow#idaho.com";
$headers = "From:" . $from;
mail($to,$subject,$message,$headers);
echo "<script type='text/javascript'>alert('An Email Has to sent from the SRRS Records Management System to the Records Management Administrator for Processing.')</script>";
//Mail the user
$to = $email;
$subject = "SRRS NOTIFICATION - Your new record request has been submitted.";
$message = "SRRS - Your new record request for $givenname, $legname has been submitted, It will be procssed within 3 working days";
$from = "joe.blow#idaho.com";
$headers = "From:" . $from;
mail($to,$subject,$message,$headers);
}
else
{
echo "<script type='text/javascript'>alert('Human Verification not entered properly!')</script>";
}
The problem is that your output for "human verification" being incorrect is the else statement for your SQL query rather than the if statement before that which does the captcha comparison.
Condensed version of what you're doing:
if(isset($_POST["captcha"]))
if($_SESSION["captcha"] == strtolower($_POST["captcha"]))
if(mysql_query($sql)) {
// do stuff
} else {
// output CAPTCHA ERROR! <-- wrong place
}
Change where your statement is:
if(isset($_POST["captcha"])) {
if($_SESSION["captcha"] == strtolower($_POST["captcha"])) {
if(mysql_query($sql)) {
// do stuff
} else {
// CAPTCHA was fine, but the SQL query failed.
}
} else {
echo "<script type='text/javascript'>alert('Human Verification not entered properly!')</script>";
}
}
Note: While using curly brackets for control structures are not necessary when you only have one statement following it (an if block counts as one statement), it's far better for readability if you include them (so I've added them for you).
Looking forward: there are better ways to write your code than lots of nested if statements. You should try working on a structure that catches and handles errors as they happen, instead of wrapping large blocks of code in if statements and dealing with the alternative at the end. Try something like this:
if(!isset($_POST['captcha']) || $_SESSION['captcha'] != strtolower($_POST['captcha'])) {
echo "<script type='text/javascript'>alert('Human Verification not entered properly!')</script>";
exit; // kill the rest of the execution
}
if(!mysql_query($sql)) {
// SQL query failed, output an error
exit; // kill the rest of the execution
}
// Everything's fine, do the rest of your stuff here.
This could be further optimised by using functions and returning false instead of exit from various levels of functions that you call whenever you find an error.
Lastly, I'd suggest that outputting Javascript like that with an alert is probably not the best way to be doing this. You should have a kind of structure where the script/function that performs the task returns a boolean result (true/false) representing whether everything has gone smoothly, perhaps with an accompanying error message to describe it, and you should have a separate script/function that deals with the presentation of that result. An simple example here would be setting the result and message to the session and redirecting the user with PHP to a page that presents the results, instead of using a script tag with an alert.
While I'm at it too - mysql_* functions are deprecated. You should use mysqli_* or PDO instead.
I'm coding a registration system on php. I'm trying to make it impossible to create two accounts with same e-mail address. I wrote a code which should check it, but it doesn't work. I can create as many accounts as I want with the same e-mail. What's wrong with it?
$sqlemail = "SELECT count(*) FROM 'users' WHERE email = ?";
$result = $connection->prepare($sqlemail);
$result->execute($email);
$emailused = $result->fetch();
if ($emailused!=false) {
echo 'An account with this e-mail address already exists!';
}
Make the email field a unique key for the table. Then, if you try to insert a duplicate, mysql will throw an error.
You can then handle the error, and display your friendlier message. You can check for the error with $result->errorCode().
This also keeps you from having to make a SELECT before an INSERT.
Can you try this, use backticks in users not '
$sqlemail = "SELECT count(*) FROM `users` WHERE email = ?";
if ($emailused>0) {
echo 'An account with this e-mail address already exists!';
}
Even if the email came back with multiple results, the script will execute because you are not killing the script! You need to use exit; or die() to stop them from progressing, or a re-direct or something.
if ($emailused>0) {
echo 'An account with this e-mail address already exists!';
exit;
}
This question already has answers here:
How to validate an Email in PHP?
(7 answers)
Closed 9 years ago.
I have a newsletter subscribe form on my website and i want it to go to a page that
confirms the user has been signed up. At the moment it just refreshes the page and gives
you a little message where the form box was. Having tested it, it also doesn't care whether
you put the email address in wrongly etc. I would like it so it checks this info and only
submits correct email addresses. The code that is there at the moment is
<?php
// get vars
$email_address = strtolower(trim($_REQUEST['email_address']));
if((strlen($email_address) > 0) && (strpos($email_address, "#")))
{
// add to db
$newsletterQry = db_query("SELECT * FROM newsletter_subscribers WHERE email='" . mysql_real_escape_string($email_address) . "'");
if(db_num_rows($newsletterQry) == 0)
{
// add
db_query("INSERT INTO newsletter_subscribers (email, created) VALUES ('" . mysql_real_escape_string($email_address) . "', NOW())");
}
}
// return back to the index page with confirmation
header("location: ".$_SERVER["HTTP_REFERER"]."?nlMsg=".urlencode("You've been added to the site newsletter."));
exit;
?>
See the solution on How to validate an Email in PHP.
You want to sanitize e-mail addresses using either RegEx, or PHP's built-in filter_var() function.
<?php
$email_address = strtolower(trim($_REQUEST['email_address']));
if (filter_var($email_address, FILTER_VALIDATE_EMAIL)) {
// This email address is valid insert into newsletter
}
I'm using the following code which you may recognise from php.net to delete all the emails in my inbox:
function deleteEmails($emailAddress)
{
// connect to gmail with your credentials
$hostname = '{imap.gmail.com:993/imap/ssl}INBOX';
$username = $emailAddress; # e.g somebody#gmail.com
$password = '****************';
// try to connect
$inbox = imap_open($hostname,$username,$password) or die('Cannot download information: ' . imap_last_error());
$check = imap_mailboxmsginfo($inbox);
echo "Messages before delete: " . $check->Nmsgs . "<br />\n";
imap_delete($inbox, '1:*');
$check = imap_mailboxmsginfo($inbox);
echo "Messages after delete: " . $check->Nmsgs . "<br />\n";
imap_expunge($inbox);
$check = imap_mailboxmsginfo($inbox);
echo "Messages after expunge: " . $check->Nmsgs . "<br />\n";
imap_close($inbox);
}
which helps deal with a clog in my account that happens on occasion if I let it get out of hand. However, what I really need is for it to delete all my email except the most recent one. I have tried to change imap_delete($inbox, '1:*'); to imap_delete($inbox, '2:*'); but this just caused it to not work at all.
What am I missing?
EDIT
With advise below I tried the following:
imap_delete($inbox, "2:$check->Nmsgs");
But interestingly it deleted all but one of the 'conversations' but in gmail 'conversations' can max out at 61 emails! I'm not sure how to get around this. Also, the deleted ones returned after a few mins...
I know gmail does some interesting stuff with just tagging it differently and putting it in an All Mail folder, since there aren't actual "Folders" like on most IMAP systems. Have you tried just giving it a range, such as
imap_delete($inbox,2:$check->Nmsgs);
If that doesn't work, you might have to just loop through marking them for deletion and then expunge after that.
I found the issue. Gmail by default is set up using 'conversations' meaning any emails coming in with the same subject get grouped together. This screws with everything but it can be turned off in gmail settings. Once done I needed to make sure I was deleting all but the most recent. using imap_delete($inbox,2:$check->Nmsgs); deleted all but the oldest. so the following code did it for me:
$emails = ($check->Nmsgs)-1;
imap_delete($inbox, '1:' . $emails);
so that I was getting the numbers but was deleting all up to the last one to come in (the most recent)
Done