Tim
Tim

Reputation: 43

php mail() sending multiple duplicate emails

I am having a major problem with the PHP mail() function. I have a user sign-up page that generates an email for verification of their email address. Unfortunately and bizarrely, the function sends anywhere from 6 or 7 to 90+ emails to the same user. I do not understand how or why this is occurring, even after looking through others' posts on here.

Can someone help me debug this?

This is the code:

$first_name = mysql_real_escape_string($_POST['first_name']);
$last_name = mysql_real_escape_string($_POST['last_name']);
$email = mysql_real_escape_string($_POST['email']);
$username = strtoupper(mysql_real_escape_string($_POST['username']));
$password1 = mysql_real_escape_string($_POST['password1']);
$password2 = mysql_real_escape_string($_POST['password2']);
$termsofuse = mysql_real_escape_string($_POST['termsofuse']);
$status = mysql_real_escape_string($_POST['status']);
$approved = mysql_real_escape_string($_POST['approved']);
$acctype = mysql_real_escape_string($_POST['acctype']);
$industry = mysql_real_escape_string($_POST['industry']);
$newsletter = mysql_real_escape_string($_POST['newsletter']);
$contactname = mysql_real_escape_string($_POST['contactname']);
$contactnumber = mysql_real_escape_string($_POST['contactnumber']);

// Hashing of $password1
$password1 = sha256($password1);
$password2 = sha256($password2);

$hash = hash('sha256', $username);

// Check for existing username
$sql = "SELECT * FROM `members`";
$result2=mysql_query($sql);
while($row=mysql_fetch_array($result2)){
  $username2 = $row['username'];

  // If $username doesn't equal $username2 (meaning there isn't an existing username, and both passwords match, write to database
  if($username <> $username2 && $password1 === $password2){
    $sql = "INSERT INTO `members` (`id`, `first_name`, `last_name`, `email`, `username`, `password`, `termsofuse`, `status`, `approved`, `acctype`, `industry`, `newsletter`, `contactnumber`, `hash`, `since`) VALUES (NULL, '$first_name' , '$last_name' , '$email' , '$username' , '$password1' , '$termsofuse', 'Reg', '$approved', '$acctype', '$industry', '$newsletter', '$contactnumber', '$hash', NOW())";
    $result = mysql_query($sql) or die ("Can't insert".mysql_error());
    $to = $email; // Send email to user
    $subject = 'Signup Verification'; //Subject line in email
    $message = 'Welcome ' . $first_name . ','
    . "\r\n\r\n"
    . 'Thanks for signing up!'
    . "\r\n\r\n"
    . 'Your account has been created. To activate your account, click on the link below to get started!'
    . "\r\n\r\n"
    . 'http://www.radioman911.com/pages/CAD/verify.php?email=' . $email . '&hash=' . $hash . '';
    $headers = 'From: xxxx' . "\r\n" .
    'Reply-To: same xxxx as above' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();
    mail($to, $subject, $message, $headers, '-fxxxx same as above'); //Send the email
    header("location:new_member_sucess.php"); //yes, i know i spelled success wrong, but i also spelled it wrong in the page filename lol

  } else {
    echo "<style type='text/css'>A{text-decoration:none}</style>";
    echo "<body bgcolor='black'><font color='white' style='font-family:trebuchet ms;'>";
    echo "Passwords do not match or that username is already taken, please try again!<br>";
    echo "<a href='javascript: history.go(-1)'><font color='red'>Go back</a></font>";
  }
}
?>

Thanks!

Upvotes: 1

Views: 3143

Answers (5)

Phil Cross
Phil Cross

Reputation: 9302

Your problem lies with the SQL to check for duplicate usernames.

// Check for existing username
$sql = "SELECT * FROM `members`";
$result2=mysql_query($sql);
while($row=mysql_fetch_array($result2)){
    $username2 = $row['username'];

...

}}

I have taken your code, and made some minor changes. I have changed your SQL query to retrieve a count of users with the same username, instead of returning every username to check individually.

I have also taken the code around the mail() function out of a loop. If no duplicate usernames have been found, the $duplicateUsername variable is set to false, otherwise its set to true.

If $duplicateUsername is false, then the mail function is called... once, otherwise the error is displayed.

Please everything from // Check for existing username with the following:

// Check for existing username
$username = mysql_real_escape_string($username);
$duplicateUsername = false;


$sql = "SELECT COUNT(username) AS usernameCount FROM members WHERE username = '{$username}'";
$result2=mysql_query($sql);
while($row=mysql_fetch_array($result2)){
    $duplicateUsername = $row['usernameCount']>0 ? true : false;
}

if(!$duplicateUsername){
    $sql = "INSERT INTO `members` (`id`, `first_name`, `last_name`, `email`, `username`, `password`, `termsofuse`, `status`, `approved`, `acctype`, `industry`, `newsletter`, `contactnumber`, `hash`, `since`) VALUES (NULL, '$first_name' , '$last_name' , '$email' , '$username' , '$password1' , '$termsofuse', 'Reg', '$approved', '$acctype', '$industry', '$newsletter', '$contactnumber', '$hash', NOW())";

    $result = mysql_query($sql) or die ("Can't insert".mysql_error());

    $to = $email; // Send email to user
    $subject = 'Signup Verification'; //Subject line in email
    $message = 'Welcome ' . $first_name . ','
       . "\r\n\r\n"
       . 'Thanks for signing up!'
       . "\r\n\r\n"
       . 'Your account has been created. To activate your account, click on the link below to get started!'
       . "\r\n\r\n"
       . 'http://www.radioman911.com/pages/CAD/verify.php?email=' . $email . '&hash=' . $hash . '';
    $headers = 'From: xxxx' . "\r\n" .
         'Reply-To: same xxxx as above' . "\r\n" .
         'X-Mailer: PHP/' . phpversion();

    mail($to, $subject, $message, $headers, '-fxxxx same as above');

    header("location:new_member_sucess.php");
} else {
    echo "<style type='text/css'>A{text-decoration:none}</style>";
    echo "<body bgcolor='black'><font color='white' style='font-family:trebuchet ms;'>";
    echo "Passwords do not match or that username is already taken, please try again!<br>";
    echo "<a href='javascript: history.go(-1)'><font color='red'>Go back</a></font>";
}

Upvotes: 1

Horen
Horen

Reputation: 11382

Your while loop doesn't make any sense.
You actually loop over all users (all rows in your db) and every time the new user doesn't match the current row in your while loop you add the new user to the database and send the email each time.

This is what you should do:
Your query

$sql = "SELECT * FROM members";

is way to generic.
Use MySql for what it's good for and let the database find the match not your php script by iterating over the result set.
Use a query like this:

$sql = "SELECT count(*) as count FROM members WHERE username LIKE '$username'";
$result = mysql_query($sql);

and then check if the $result['count'] equals 0. If that's the case the new user doesn't exist yet and you can create the new user and send your email.

Upvotes: 1

web2students.com
web2students.com

Reputation: 307

Your mail function is within while loop, so it's sending so many emails. please cut that code and place it above or below loop. Second, query is wrong, $sql = "SELECT * FROM members"; will select all members, use $sql = "SELECT * FROM members where ....."; i don't know column names. read, http://www.w3schools.com/php/php_mysql_where.asp

Upvotes: 0

Richard
Richard

Reputation: 4415

You're looping though all of your members if if the usernames don't match, but the passwords do, you add a user and send an e-mail. Usernames will almost never be identical and passwords might...

You should change your query to only query the database for that particular user, e.g.

$sql = "SELECT * FROMmembersWHERE username LIKE \"" . $username . \"";

Not an answer to your question, but you can shorten the first lines of your code to this:

foreach($_POST AS $k => $v){
  $$k = mysql_real_escape_string($v);
}
$username = strtoupper($username);

A lot shorter.

Upvotes: 0

George Cummins
George Cummins

Reputation: 28906

You are executing mail() in a while() loop that includes all of the users in your database.

Based the if statement in that condition, you are doing an insert and sending the email every time the user-supplied username doesn't match the current row and the password matches. Presumably, several of your users a lot of the same passwords.

You will need to update your query to include conditions to excludes non-matching users from the result set.

Upvotes: 0

Related Questions