J'utilise is_email()
pour vérifier si une adresse e-mail fournie par l'utilisateur est valide. Par exemple:
$email = $_POST['email'];
if ( is_email( $email ) )
// Do something.
À ma connaissance, rien dans cette fonction n’écrit d’informations dans la base de données. Devrais-je désinfecter $email
avant de le transmettre à la fonction?
En regardant la fonctionnalité is_email()
sur trac, il semblerait que vous n’ayez pas besoin de sanatizie car il ne s’agit que de tester les chaînes. J'irais même jusqu'à dire que si cette fonction renvoie true, vous n'avez pas besoin de la nettoyer avant de l'envoyer à la base de données.
La is_email()
fonction Source est une implémentation typique de WordPress et ne fonctionne pas complètement avec ce que le RFC 6531 permet. Une des raisons pourrait être que le PHP FILTER_VALIDATE_EMAIL
constant par défaut pour filter_var()
n'est pas beaucoup mieux à valider quelque chose selon les IETF®) directives.
Le point important est que la RFC 6531 autorise "Caractères Unicode situés au-delà de la plage ASCII". À savoir, ce sont (pour la partie locale - avant le @
):
- Lettres anglais majuscules et minuscules (a – z, A – Z) (ASCII: 65–90, 97–122)
- Chiffres
0
à9
ASCII: 48–57)- Ces caractères spéciaux:
! # $ % & ' * + - / = ? ^ _ ` { | } ~
- Caractère
.
(point, point, point final) (ASCII: 46) à condition qu'il ne s'agisse pas du premier ou du dernier caractère, mais également qu'il n'apparaisse pas consécutivement (par exemple,[email protected]
n'est pas autorisé).- Les caractères spéciaux sont autorisés avec restrictions. Elles sont:
- Space et
"(),:;<>@[\]
(ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)- Les restrictions pour les caractères spéciaux sont qu’ils ne doivent être utilisés qu’entre des guillemets et que 2 d’entre eux (la barre oblique inversée\et le guillemet "(ASCII: 92, 34)) doivent également être précédés d’une barre oblique inversée
\
(par exemple,"\\"
et"\""
).- Les commentaires sont autorisés avec des parenthèses aux deux extrémités de la partie locale; par exemple.
john.smith(comment)@example.com
et(comment)[email protected]
sont équivalents à"[email protected]"
, maisjohn.(comment)[email protected]
serait invalide.- La RFC 6531 autorise les caractères internationaux supérieurs à
U+007F
, codés au format UTF-8, bien que les systèmes de messagerie puissent restreindre le choix des caractères à utiliser lors de l'attribution de parties locales.
et pour la partie globale/domaine:
La partie nom de domaine d'une adresse électronique doit être conforme à des directives strictes: elle doit correspondre aux exigences d'un nom d'hôte, composé de lettres, de chiffres, de traits d'union et de points. De plus, la partie de domaine peut être un littéral d'adresse IP, entouré d'accolades, telles que
jsmith@[192.168.2.1]
oujsmith@[IPv6:2001:db8::1]
[…].
_ (Source: Wikipedia
Cela peut conduire à des adresses de messagerie étranges, mais valides, comme celles-ci:
[email protected]
(comment)[email protected]
"this is v@lid!"@example.com
"much.more unusual"@example.com
postbox@com
admin@mailserver1
"()<>[]:,;\\@\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org
" "@example.org
Source: php.net / author [email protected] - exemple corrigé par l'auteur de ce post
Il existe également des limites de longueur locales et de domaine:
Le format des adresses électroniques est
local-part@domain
où la partie locale peut contenir jusqu'à 64 caractères et le nom de domaine 253 au maximum, mais le maximum de 256 caractères d'un chemin d'accès direct ou inverse limite la totalité de l'adresse électronique à ne doit pas dépasser 254 caractères. [2] Les définitions formelles figurent dans les RFC 5322 (sections 3.2.3 et 3.4.1) et RFC 5321 - avec un formulaire plus lisible donné dans la RFC 3696 informative [3] et les errata associés.
Source: Wikipedia
Et voici ce que WordPress vérifie:
strlen( $email ) < 3
strpos( $email, '@', 1 ) === false
!preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
preg_match( '/\.{2,}/', $domain )
trim( $domain, " \t\n\r\0\x0B." ) !== $domain
$subs = explode( '.', $domain );
puis 2 > count( $subs )
trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
!preg_match('/^[a-z0-9-]+$/i', $sub )
Source: WP Core v4.0
Tous les cas mentionnés ci-dessus déclencheront is_email()
pour retourner false. Le résultat peut être filtré (un rappel peut être associé) et le filtre aura trois arguments, le dernier argument en étant la raison. Exemple:
return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );
ce qui signifie que vous pouvez remplacer les résultats renvoyés par des contrôles spécifiques.
Cela vous permet d'ajouter des vérifications spéciales, par exemple pour autoriser les domaines Umlaut, les parties de domaine uniquement TLD, etc.
WordPress est sans danger pour la plupart des cas, mais plus restrictif car les serveurs de messagerie doivent en réalité être conformes à la norme RFC. N'oubliez pas que tous les serveurs de messagerie ne s'aligneront pas sur les directives RF 6531.
Sidefact amusant: Il existe deux fonctions liées dans ~/wp-includes/formatting
: is_email()
et sanitize_email()
. Ils ont pratiquement la même fonction. Je ne sais pas pourquoi quelqu'un a décidé que ce serait une bonne idée de copier le contenu de la fonction d'un système à un autre au lieu d'ajouter simplement celui-ci en tant que rappel aux filtres fournis par l'autre. As is_email()
depuis v0.71 et sanitize_email()
depuis v1.5 sont les mêmes, je voudrais personnellement utiliser le plus tard que vous obtenez une chaîne nettoyée. Notez que is_email()
indique même qu'il n'est pas conforme à RFC.
Désinfectez toutes les choses!
L’une des règles essentielles de la sécurité est de ne jamais faire confiance aux données de l’utilisateur. En général, peu m'importe l'implémentation de is_email () ou de toute autre fonction spécifique, ou si cette fonction fait quelque chose de dangereux avec ce que je lui donne. Peut-être que la mise en œuvre changera un jour. Qui sait. Je dois supposer que cela peut être compromis. L'hypothèse devrait toujours être que l'entrée utilisateur est activement hostile, ce qui est d'autant plus vrai pour tout ce qui est destiné à une base de données, et pour effacer chaque entrée d'utilisateur avant de la transférer à une fonction. Ceci est juste bon, l'hygiène de sécurité générale.