formulaire d'inscription avec envoi + validation d'email

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : formulaire d'inscription avec envoi + validation d'email

par AB » 09 avr. 2009, 16:32

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...
Si cette clé est une colonne auto incrémentée, mysql_insert_id() retourne le dernier ID généré suite à une requête d'insertion. En toute logique si tu utilises cette fonction juste après ton insertion cela devrait t'éviter ta seconde requête :wink:

par Niico » 09 avr. 2009, 11:53

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...

par Ryle » 03 avr. 2009, 16:11

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 ;)

par Niico » 03 avr. 2009, 15:45

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:

par AB » 03 avr. 2009, 13:39

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

par AB » 03 avr. 2009, 13:36

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.

par Niico » 03 avr. 2009, 13:25

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....

par AB » 02 avr. 2009, 21:23

Ah oui pour la réception il suffit de faire :
$surname = isset($_GET['surname']) ? rawurdecode($_GET['surname']) : '';

par AB » 02 avr. 2009, 21:20

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>';

par Niico » 02 avr. 2009, 21:06

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...

par AB » 02 avr. 2009, 19:35

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().

par Niico » 02 avr. 2009, 19:21

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'];

par AB » 02 avr. 2009, 04:45

... 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

par Niico » 01 avr. 2009, 19:27

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

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

par Ryle » 01 avr. 2009, 19:12

-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)