Page 1 sur 2

formulaire d'inscription avec envoi + validation d'email

Posté : 01 avr. 2009, 18:52
par Niico
Bonjour à tous !

Mon problème depuis ce matin (je sais j'avance pas vite :P ) est que je voudrais faire une base d'utilisateurs identifiés par leur adresse email sans erreur possible (pour cela j'ai pensé à utiliser l'adresse que leur donne leur université : elle est unique, et normalement sûre et rend donc mon formulaire moins ouvert au piratage).

-J'ai commencé par un formulaire dans 'register.php' qui envoie ses données par POST dans 'sendmail.php'.
-Sendmail fait un contrôle basique de remplissage des champs, contrôle que l'email donné ne soit pas déjà dans la base de donnée, auquel cas on redirige l'utilisateur vers 'forgotten.php' et envoie un email avec un lien html sous forme "http://entreprise.com/validation.php?ID=[nombre]" (ID étant l'index auto-incrémenté) qui dans la théorie, une fois cliqué permettrait d'entrer un beau "validé" dans la table des utilisateurs.

Les problèmes :
-je suis VRAIMENT débutant en php mais je me soigne à l'aide du livre de Jean Carfantan "PHP & MySQL, versions 4 et 5", éditions Micro Applications, avril 2008.
-ma demande de $ID que je fais sous la partie "I try to get the user's ID" m'affiche la même chose depuis que j'ai rajouté cette ligne, c'est à dire "Resource id #4". La première fois que j'ai fait le test, c'était vrai,mais depuis je n'ai plus réussi à afficher la bonne variable. Ce problème me coince pour faire avancer le reste du site.
-quelqu'un pourrait me corriger mon script d'effaçage des données non validées depuis plus de 5 jours ? Il ne semble pas fonctionner non plus...

Je m'excuse de vous donner toutes ces lignes de code mais comme je suis vraiment débutant, je ne sais pas vraiment où se situe le problème (et puis c'est pas trop mal commenté encore...).

Je vous remercie de vous pencher sur ce code qui doit piquer les yeux des plus avertis !
<?
///We control that the email address doesn't already exist
include "common/connection.inc.php";
$email=htmlentities($_POST['prefix'])."@".htmlentities($_POST['subdomain']).".ac.uk"; //The email we are sending this text to
$sql1="select ID from safereg where email='$email'";
$result=mysql_query($sql1,$id_link);
$number=mysql_num_rows ($result);
if ($number >0){
$auth=1;
//$url='register.php';
//http_redirect($url);
include "register.php";
exit;
}
?>
<?
//We control that the fields are not exmpty
if(!empty($_POST['name']) and !empty($_POST['surname']) and !empty($_POST['mobile'])
and !empty($_POST['prefix']) and !empty($_POST['subdomain']) and !empty($_POST['residence'])
and !empty($_POST['room']) and !empty($_POST['question']) and !empty($_POST['answer'])){

/************ if the fields are not empty we write this on the screen*************/
echo '<h2 class="pagetitle"><br>Thank you!</h2>';
echo '<P class="text"><br>An email has been sent to ' . $email . '</p>';
echo '<p class="text">Please follow the link in this email to complete step 2 and validate your registration!</p>';

/*****************Here we feed the data into the database*************************/
$name=$_POST['name'];
$surname=$_POST['surname'];
$mobile=$_POST['mobile'];
$residence=$_POST['residence'];
$room=$_POST['room'];
$question=$_POST['question'];
$answer=$_POST['answer'];
$date=date(Ymd);
$sql2="INSERT INTO safereg (name, surname, mobile, email, residence, room, question, answer, date) VALUES ('$name', '$surname', '$mobile', '$email', '$residence', '$room', '$question', '$answer', '$date')";
mysql_query($sql2,$id_link) or die('Erreur SQL : '.mysql_error());

/********I try to get the user's ID******************/
$sql3="select ID from safereg";
$ID=mysql_query($sql3,$id_link) or die('Erreur SQL : '.mysql_error());
echo "$ID";

/*****************The email that is going to be sent*********************/
$mailheaders  = "From: \"entreprise\" <[email protected]>\n";
$mailheaders .= "X-Sender: <[email protected]>\n";
$mailheaders .= "X-Mailer: PHP\n"; //mailer
$mailheaders .= "X-Priority: 1\n";
$mailheaders .= "Return-Path: <[email protected]>\n";
$mailheaders .= "Content-Type: text/html; charset=iso-8859-1\n";
/*****************Email text*******************/
$emailcontent = "Hello $name $surname,\n\n

Please click this link to complete the last step of your validation:\n
<a href=\"http://www.entreprise.com/activation.php?ID='$ID'\">Go to step 3</a>\n
If validation is not completed within 5 days your details will be deleted.

We thank you for your time,\n
Best regards / enjoy your safe,\n
The entreprise Team.";
/************End of email text*****************/
$emailcontent = nl2br($emailcontent);//formatting the text in html
$emailtext = "<HTML>\n";
$emailtext .= "<HEAD>\n";
$emailtext .= "<META NAME=\"GENERATOR\" Content=\"Microsoft DHTML Editing Control\">\n";
$emailtext .= "<TITLE>Step 2 - Registration</TITLE>\n";
$emailtext .= "</HEAD>\n";
$emailtext .= "<BODY><FONT face=Arial color=#68D263 size=4>\n";
$emailtext .= "<P><div align=\"center\"><STRONG>
Step 2 - registration with entreprise</STRONG></div></P></FONT>
<P><FONT color=#000000 face=Arial, Helvetica, sans-serif\" size=\"2\">\n";
$emailtext .= $emailcontent;
$emailtext .= "</FONT></P>\n";
$emailtext .= "</BODY>\n";
$emailtext .= "</HTML>\n";
/************Email function************************/
mail(
"[email protected],$email", /*And we send a nice email to the person here.
To add an email, just enter a coma, then the new email. No space between the two emails*/
'Step 2 - Safe registration with entreprise', // mail object
"$emailtext",
"$mailheaders");
/************End of email function*****************/

/***********We clear all unactivated DB entries that are older than 5 days********/
$5daysago = date("Y-m-d", mktime(0,0,0,date("Y"),date("m"),date("d")-5));
$sql4 = "DELETE FROM safereg WHERE activation='' AND date < $5daysago";
@mysql_query($sql4,$id_link);
}

else{
echo '<h2 class="pagetitle"><br>Error!</h2>'; // and that's what happend on the screen if the fields were empty
echo '<p class="text"><br>You have to fill in all the fields.</p>';
echo '<p class="text">Please go back to the precedent page...';
}
?>

Re: formulaire d'inscription avec envoi + validation d'email

Posté : 01 avr. 2009, 19:12
par Ryle
-ma demande de $ID que je fais sous la partie "I try to get the user's ID" m'affiche la même chose depuis que j'ai rajouté cette ligne, c'est à dire "Resource id #4". La première fois que j'ai fait le test, c'était vrai,mais depuis je n'ai plus réussi à afficher la bonne variable. Ce problème me coince pour faire avancer le reste du site.
La fonction mysql_query() exécute la requête que tu lui spécifies en argument, et retourne une ressource MySQL. Si tu te contentes d'afficher cette ressource directement, php ne saura pas l'interpréter et va t'afficher "Resource id #x". Afin de pouvoir exploiter cette ressource et accéder aux données retournées par ta requête il te faut utiliser une fonction du style mysql_fetch_assoc() et compagnie :
$sql3="select ID from safereg"; 
$res = mysql_query($sql3,$id_link) or die('Erreur SQL : '.mysql_error()); 
if ($row = mysql_fetch_assoc($res) ) { // Si ma ressource contient des résultat, je stocke le premier enregistrement dans $row
  echo $row['ID']; // j'affiche la valeur du champ "ID" de l'enregistrement en base.
}
A noter que ta requête, telle quel, va retourner tous les ID de ta base et pas seulement celui d'un user en particulier, il faut pour cela ajouter un WHERE et des critères pour trouver celui dont tu as besoin :)
-quelqu'un pourrait me corriger mon script d'effaçage des données non validées depuis plus de 5 jours ? Il ne semble pas fonctionner non plus...
Alors déjà, $5daysago, c'est pas un nom de variable propre... il ne devrait pas commencer par un chiffre. Quant à la manipulation des dates, tu ne passes pas les arguments dans le bon ordre à la fonction mktime() : "0,0,0, mois, jour, année"
Tu peux aussi faire le calcul directement en sql avec la fonction date_sub : DATE_SUB(NOW(), INTERVAL 5 DAY)
A lire pour plus d'infos : Quelques petites manipulations avec les dates (PHP/MySQL)

Posté : 01 avr. 2009, 19:27
par Niico
Merci Ryle ! (pour les corrections et les liens)

Je vais corriger mon code dans les directions indiquées.

Mais je me pose une question : Est-ce fantasmer que de penser que je peux récupérer les données que je viens d'entrer sur la table au début de la même page ? Parce que l'idée (si c'est possible) c'est d'envoyer à l'utilisateur son petit lien d'activation par email en lui demandant le moins d'efforts et de clics possibles.
Si c'est possible, que penses-tu de :
$sql3="select ID from safereg WHERE email='$email'";
c'est la seule entrée de la base qui est unique à part l'ID, donc ça doit être la seule possibilité..?

Autrement en général, que penses-tu de mon idée de lien d'activation par email ? Aurait pu faire plus simple ?

Edit2:
trouver l'ID de l'entrée dans la table:
$sql3="select ID from safereg WHERE email='$email'";
$res = mysql_query($sql3,$id_link) or die('Erreur SQL : '.mysql_error()); 
if ($row = mysql_fetch_assoc($res) ) { // Si ma ressource contient des résultat, je stocke le premier enregistrement dans $row
  echo $row['ID']; // j'affiche la valeur du champ "ID" de l'enregistrement en base.
Merci bien Ryle !! C'est ton code quasiment pas retouché !

script d'effaçage de la BD :
$sql4 = "DELETE from safereg WHERE validation='' AND DATE_SUB(NOW(), INTERVAL 5 DAY)";
mysql_query($sql4,$id_link) or die('SQL error : '.mysql_error());
Problème : ca vide toute ma base :P arf ! Visiblement je n'utilise pas la bonne méthode. Je vais encore lire un peu le lien que Ryle m'a donné, mais si quelqu'un connaît la bonne fonction, c'est volontiers :P

Posté : 02 avr. 2009, 04:45
par AB
... Parce que l'idée (si c'est possible) c'est d'envoyer à l'utilisateur son petit lien d'activation par email en lui demandant le moins d'efforts et de clics possibles.
Il y a un sujet qui parle de cela ici http://www.phpfrance.com/forums/viewtop ... nscription

Posté : 02 avr. 2009, 19:21
par Niico
Merci à tous !
J'ai réussi à résoudre mes problèmes, et à présent ça marche du tonnerre !

Voici les petits bouts de code pour effacer les données non validées qui ont plus de 5 jours :
$fivedays = date("Ymd", mktime(0,0,0,date("m"),date("d")-5,date("Y")));
$sql4 = "DELETE FROM safereg WHERE validation='0' AND date<$fivedays";
mysql_query($sql4,$id_link);
Et (merci AB !) voici la petite ligne qui inclut le lien d'activation par email :
$emailcontent="Please click this link to complete the last step of your validation:\n
<a href=\"http://www.entreprise.com/validation.php?ID=$ID&name=$name&surname=$surname\">I validate my email!</a>\n
If validation is not completed within 5 days your details will be deleted."
La variable ID étant tirée d'une demande sql :
$sql3="select ID from safereg WHERE email='$email'";
$res = mysql_query($sql3,$id_link); 
if ($row = mysql_fetch_assoc($res) ) {//If the resource contents some results, I feed the first result to $row
  $ID=$row['ID'];

Posté : 02 avr. 2009, 19:35
par AB
Si tu utilises $name et $surname pour récupérer les données provenant du lien d'activation, tu risques d'avoir des problèmes si l'une ou l'autre des deux variables a un espace (nom composé) ou une quote (') bref avec tout caractère qui ne passe pas correctement dans l'URL.
Pour résoudre cet éventuel pb tu peux utiliser rawurlencode() puis rawurldecode().

Posté : 02 avr. 2009, 21:06
par Niico
ah oui mince j'avais complètement passé à côté de cela!
mais comment dois-je l'écrire ?
quand je fais comme ca, j'ai une belle erreur php :(
Please click this link to complete the last step of your validation:\n
<a href=\"http://www.entreprise.com/validation.php?";

rawurlencode(ID=$ID&name=$name&surname=$surname);

$emailcontent .= "\">I validate my email!</a>\n
If validation is not completed within 5 days your details will be deleted.
et l'erreur php :

Parse error: parse error, unexpected '=' in /home/e/n/entreprise/public_html/sendmail.php on line 143

la ligne 143 étant bien sûr mon rawurlencode....

Et si aussi tu pouvais m'expliquer comment je dois décoder mon url quand je fais mon $_GET, ça serait sympa... car j'ai pas bien compris dans la documentation officielle sur http://uk2.php.net/manual/fr/function.rawurldecode.php...

Posté : 02 avr. 2009, 21:20
par AB
Il faut encoder tes variables par exemple
$encode_surnom = rawurlencode($surnom);
$encode_nom = rawurlencode($nom);
//... puis ...
echo '<a href="http://www.hotechedge.com/validation.php?surname='.$encode_surnom.'&name='.$encode_nom.'">lien</a>';

Posté : 02 avr. 2009, 21:23
par AB
Ah oui pour la réception il suffit de faire :
$surname = isset($_GET['surname']) ? rawurdecode($_GET['surname']) : '';

Posté : 03 avr. 2009, 13:25
par Niico
Merci AB ;)

Seulement j'ai encore un problème, et je ne sais pas de quoi ca vient...
(merci pour ce bel opérateur ternaire, ça m'a fait chercher un moment dans mon bouquin pour comprendre ce que ça voulait dire :P)

J'essaie avec les fonctions rawurlencode() et urlencode() (et xxdecode aussi pour la réception, évidemment) mais je n'obtiens toujours pas la même chose à l'arrivée, et ça m'embête car ça n'active pas le compte comme ça devrait :D

L'url dans mon mail:
http://www.validation.com/validation.ph ... %5C%27test

et voici mon code pour encoder:
$encode_name  = urlencode($name);//We encode the name,so that - et ' are ok in names
$encode_surname= urlencode($surname);

/********notre petit email***********/
$emailcontent = "Hello $encode_name $encode_surname,\n\n

Please click this link to complete the last step of your validation:\n
<a href=\"http://www.entreprise.com/validation.php?ID=$ID&name=$encode_name&surname=$encode_surname\">I validate my email!</a>\n";
Comme tu peux aussi l'imaginer, le nom dans l'email apparaît tronqué au possible... Je vais le remplacer avec $name et $surname. Ca n'est pas le plus efficace, mais au moins ca marchait bien !

et mon code pour décoder :
include 'common/connection.inc.php';
$name = isset($_GET['name']) ? urldecode($_GET['name']) : ''; 
$surname = isset($_GET['surname']) ? urldecode($_GET['surname']) : ''; 
$sql="UPDATE safereg SET validation='1' WHERE ID='".$_GET[ID]."' AND name=$name AND surname=$surname";
mysql_query($sql,$id_link);
Et si j'ai bien compris l'opérateur ternaire, on traduit par : si la valeur de $name existe on lui donne la valeur de $_GET'name' et si elle n'existe pas, on ne lui attribue rien. C'est correct ? :roll:

Edit:
ah oui, et comme résultat lorsque je décode j'ai :
test test test\\\'test
je ne sais pas quelle partie du code remplit ce doux nom d'antislash....

Posté : 03 avr. 2009, 13:36
par AB
Il ne faut encoder que les variables qui sont destinées à passer dans l'URL (donc dans le href) mais évidemment pas celles qui doivent s'afficher normalement dans ton message.

Sinon pour l'opérateur ternaire tu as compris le fonctionnement. Le point d'interrogation suit la condition requise; ce qui suit le point d'interrogation est l'instruction qui sera exécutée si la condition est vraie; ce qui suit les deux point est l'instruction qui sera exécutée si la condition est fausse.

Posté : 03 avr. 2009, 13:39
par AB
Je n'avais pas vu ton EDIT.
Merci AB ;)Edit:
ah oui, et comme résultat lorsque je décode j'ai :
test test test\\\'test
je ne sais pas quelle partie du code remplit ce doux nom d'antislash....
ça cela vient des magic quotes qui sont activées sur ton serveur. Je viens d'en parler ici http://www.phpfrance.com/forums/voir_re ... php#285461

Posté : 03 avr. 2009, 15:45
par Niico
tiens j'avais toujours entendu parler de ces magic quotes mais je ne savais pas ce que c'était :P

bon alors j'ai inclu ma fonction et l'ai mise devant mon POST, pour qu'il traite les éventuelles magicquotes. Mais maintenant j'ai un autre problème :
1.- l'ID n'est plus dans le lien reçu par l'email (donc la fonction magicquotes influe sur ma requête sql et renvoie une erreur ??)
2.- le nom de famille n'apparaît pas sur la page de validation... mais où part-il ? mon url est mal encodée ?

J'ai bien cherché, mais je ne vois pas de quoi ça peut provenir... (flûte, au moins la fonction des magicquotes marche bien :lol: )

l'URL dans le mail :
http://www.entreprise.com/validation.ph ... est%27test

mon code dans sendmail.php:
function verif_magicquotes ($chain)//Murphy's law: the server config is for older scripts!!
{
if (get_magic_quotes_gpc()) $chain = stripslashes($chain);

return $chain;
}  

///We control that the email address doesn't already exist
include "common/connection.inc.php";
$email=htmlentities($_POST['prefix'])."@".htmlentities($_POST['subdomain']).".ac.uk"; //The email we are sending this text to
$sql1="select ID from safereg where email='$email'";
$result=mysql_query($sql1,$id_link);
$number=mysql_num_rows ($result);
if ($number >0){
$auth=1;
include "register.php";
exit;
}

//....

//We control that the fields are not empty
if(!empty($_POST['name']) and !empty($_POST['surname']) and !empty($_POST['mobile'])
and !empty($_POST['prefix']) and !empty($_POST['subdomain']) and !empty($_POST['residence'])
and !empty($_POST['room']) and !empty($_POST['question']) and !empty($_POST['answer'])){

/*****************Here we feed the data into the database*************************/
$name=verif_magicquotes($_POST['name']);
$surname=verif_magicquotes($_POST['surname']);
$mobile=$_POST['mobile'];
$residence=$_POST['residence'];
$room=$_POST['room'];
$question=$_POST['question'];
$answer=verif_magicquotes($_POST['answer']);
$date=date(Ymd);
$sql2="INSERT INTO safereg (name, surname, mobile, email, residence, room, question, answer, date) VALUES ('$name', '$surname', '$mobile', '$email', '$residence', '$room', '$question', '$answer', '$date')";
mysql_query($sql2,$id_link);

/*****************I get the user's ID*************************/
$sql3="select ID from safereg WHERE email='$email'";
$res = mysql_query($sql3,$id_link); 
if ($row = mysql_fetch_assoc($res) ) {//If the resource contents some results, I feed the first result to $row
  $ID=$row['ID'];
}

/*****************The email that is going to be sent*********************/
$encode_name  = rawurlencode($name);//We encode the name,so that - and ' inside are OK
$encode_surname= rawurlencode($surname);

//...

$emailcontent = "Hello $name $surname,\n\n

<a href=\"http://www.entreprise.com/validation.php?ID=$ID&name=$encode_name&surname=$encode_surname\">I validate my email!</a>\n";
et mon code dans validation.php, à nouveau la fonction sur tout, au cas où :
$name = verif_magicquotes($_GET['name']);
$surname = verif_magicquotes($_POST['surname']);
//$name = isset($_GET['name']) ? rawurldecode($_GET['name']) : '';
//$surname = isset($_GET['surname']) ? rawurldecode($_GET['surname']) : '';
$name = rawurldecode($name);
$surname = rawurldecode($surname);
$sql="UPDATE safereg SET validation='1' WHERE ID='".$_GET[ID]."' AND name=$name AND surname=$surname";
mysql_query($sql,$id_link);
merci pour le coup de main ! :wink:

Posté : 03 avr. 2009, 16:11
par Ryle
Dans ton lien, on voit que $ID est vide.. donc qu'il n'a pas trouvé l'id de l'objet que tu viens d'insérer ou qu'il y a eut une erreur lors de l'exécution de la requête...

A noter que tu peux remplacer tout ceci :
/*****************I get the user's ID*************************/ 
$sql3="select ID from safereg WHERE email='$email'"; 
$res = mysql_query($sql3,$id_link);  
if ($row = mysql_fetch_assoc($res) ) {//If the resource contents some results, I feed the first result to $row 
  $ID=$row['ID']; 
} 
par
/*****************I get the user's ID*************************/ $ID = mysql_insert_id();
pour récupérer l'identifiant que MySQL a utilisé pour l'insertion :)

Edit : Ah ! Et pour la purge des anciens enregistrement avec MySQL t'avait presque bon. En fait, DATE_SUB(NOW(), INTERVAL 5 DAY) te retourne juste la date d'il y a 5 jours. Manquait donc simplement un "date <" dans ta requête. Mais la version php fonctionne très bien également ;)

Posté : 09 avr. 2009, 11:53
par Niico
Bon après m'être cassé la tête sur ces magicquotes que je n'ai finalement pas réussi à enlever, j'ai décidé de simplement éviter le problème en activant le compte des mes utilisateurs à l'aide de leur ID dans la table, et leur adresse email. Ca me semble déjà assez sécurisé comme ça ;)

Voici le code qui crée l'URL à cliquer pour la validation du compte, qu'on envoie dans l'email:
/*à la première ligne, le code va envoyer des magicquotes si la personne a une apostrophe dans le nom... je n'ai pas réussi à les enlever, ni dans le mail, ni dans ma page de validation*/
$emailcontent = "Hello $name $surname,\n\n

You requested a safe validation from the entreprise website with this email address. If not, please ignore this email.\n

Please click this link to complete the last step of your validation:\n
<a href=\"http://www.entreprise.com/validation.php?ID=$ID&email=$email\">I validate my email!</a>\n
If validation is not completed within 5 days your details will be deleted.\n
For the record, your answer to the security question was \"$answer\" and the room number you indicated was $room.\n\n

We thank you for your time,\n
Best regards,\n
The Entreprise Team.";
@Ryle : Merci d'avoir corrigé mon code MySQL ;)
Autrement pour la requête du numéro ID, je n'ai pas essayé, mais je pensais que j'étais obligé de spécifier quelle ligne je voulais... car ID est ma colonne de clés dans ma table safereg, et si je fais une requête aussi générale que ce que tu me proposes, je risque de recevoir toutes les clés, non ?

Anyway, merci pour votre aide à tous, maintenant ca marche bien, même si je suis déçu de pas avoir mieux compris le problème des magicquotes...