[linux] Re: Regex check email adres?

Kees Theunissen theuniss op rijnh.nl
Zo Feb 19 11:29:49 CET 2006


On Sat, 18 Feb 2006, Hugo van der Kooij wrote:

>
>Hoi,
>
>Ik zie na jaren dezelfde regex te hebben gebruik dat er mensen zijn die
>nu een probleem hebben als hun email adres wordt gecontroleerd met de
>volgende case-insensitive check op
>^[_a-z0-9-]+(\.[_a-z0-9-]+)*\+*@[a-z0-9-]+(\.[a-z0-9-]+)*$
>
>De check in PHP is met eregi() gedaan.
>
>Kan het zijn dat er een browser is in linux land die zelf spontaan email
>adressen in forms verbouwd?

Ik denk dat jouw regex te veel beperkingen stelt aan het deel voor
de "@".

Het gaat te ver om hier de volledige specificatie uit te gaan pluizen,
maar twee citaatjes uit rfc2822 moet kunnen.

3.4.1. Addr-spec specification

   An addr-spec is a specific Internet identifier that contains a
   locally interpreted string followed by the at-sign character ("@",
   ASCII value 64) followed by an Internet domain.  The locally
   interpreted string is either a quoted-string or a dot-atom.  If the
   string can be represented as a dot-atom (that is, it contains no
   characters other than atext characters or "." surrounded by atext
   characters), then the dot-atom form SHOULD be used and the
   quoted-string form SHOULD NOT be used. Comments and folding white
   space SHOULD NOT be used around the "@" in the addr-spec.

Als de "locally interpreted string" in de quoted-string vorm is dan
moet je nagenoeg alles accepteren waar dubbele quotes omheen staan.
De "dot-atom" vorm is beperkter (it contains no characters other than
atext characters or "." surrounded by atext characters) maar staat
toch nog veel meer tekens toe dan waarop jouw regex test.
De definitie van "atext characters" in paragraaf 3.2.4 van rfc2822 is:

atext           =       ALPHA / DIGIT / ; Any character except controls,
                        "!" / "#" /     ;  SP, and specials.
                        "$" / "%" /     ;  Used for atoms
                        "&" / "'" /
                        "*" / "+" /
                        "-" / "/" /
                        "=" / "?" /
                        "^" / "_" /
                        "`" / "{" /
                        "|" / "}" /
                        "~"

Je mag best twijfels hebben omtrent de goede bedoelingen van een afzender
die "|", "&", "$" of "`" (om er maar een paar uit te pikken) gebruikt
in een email adres, maar het zijn _wel_ legale tekens in een adres.
Als dat soort tekens in een email-bestemming staan dan kan je dat
onmiddellijk blokkeren want je hebt natuurlijk geen users of aliases
met die tekens neem ik aan. Maar wat doe je (en daar heb je het nu over)
met dit soort tekens in een afzender-adres? Moeilijk probleem.
Bij tekens als "|", "&", "$" of "`" moet je altijd rekening houden met
de mogelijkheid dat de afzender probeert bugs in een MTA, een MUA, een
webmail programma of een log-interpreter te exploiteren.
Blokkeren en loggen is geen oplossing als het gaat om exploitatie van
bugs in log-interpreters. (Natuurlijk gebruik je geen log-interpreter
met known bugs.)
Misschien heb je te maken met gebruikers die proberen interessant te doen
met nodeloos ingewikkelde email adressen, misschien zijn het ook alleen
maar naïve gebruikers die iets proberen als "jan|marie op ..." of
"willem/mien op ...".


Hugo, je bent niet duidelijk over wat je wilt met je filter.
Als je alles wilt doorlaten wat een legaal adres is lees dan rfc2822 en
pas je regexp aan. Je regexp zal een stuk ingewikkelder worden dan hij nu
is, maar het lijkt me wel te doen. De vraag is of dat je dit wilt. Als
je zo ongeveer alles gaat accepteren omdat het uiteindelijk een legaal
adres blijkt te zijn dan kan je net zo goed niet filteren.

Een tweede benadering is: accepteer alleen maar die adressen die veilig
zijn. Je zult dan een hoop adressen moeten afwijzen die op zich wel
legaal zijn. Je regexp wordt er dan niet simpeler op en er liggen
eindeloze discussies op de loer over wat nog net wel veilig is en wat
net niet meer. Als je alleen mail ontvangt voor jezelf en voor huisgenoten
dan zullen die eindeloze discussies mogelijk nog wel te overzien en
beheersbaar zijn.

Een derde, pragmatische, benadering gaat uit van het filter dat je nu hebt
en dat je al jaren, naar het schijnt probleemloos, gebruikt hebt. Blijf dat
filter gebruiken, eventueel met aanpassingen, maar blijf je ervan bewust
dat je adressen blokkeert die op zich wel legitiem zijn hoewel het geen
gangbare adressen zijn. Je zult dan ook logs en/of quarantaine actief in
de gaten moeten houden of er geen mail ten onrechte wordt geweerd.
Relaties waarmee je wilt blijven communiceren zul je dan moeten attenderen
op het feit dat ze een lastig email adres hebben. En uiteindelijk zal je
dan halsstarrige relaties met een lastig adres, maar waarmee je toch
in contact wilt blijven, misschien in een whitelist moeten zetten.

Natuurlijk kan je ook kiezen voor niet filteren, er op vertrouwen dat al
je programma's up-to-date en veilig zijn en dat je spam- en virusfilers
de ergste troep wel tegenhouden. Volgens mij bestaat er geen simpele regex
die nu werkt en waar je nooit niet meer naar hoeft om te kijken.

Nog één opmerking bij je huidige regex:
^[_a-z0-9-]+(\.[_a-z0-9-]+)*\+*@[a-z0-9-]+(\.[a-z0-9-]+)*$
Als ik dit goed interpreteeer dan accepteer je hiermee "+"-tekens in
een adres alleen maar als er nul of meer van die tekens direct voor het
"@"-teken staan: "\+*@". Dit zou je moeten aanpassen denk ik. Als een
"+" gebruikt wordt in een "normaal" (niet vijandig) adres dan zal die
vrijwel nooit direct voor de "@" staan. Sendmail kent een specifieke
betekenis toe aan het "+"-teken. Sendmail, draaiend als mailserver voor
"some.domain" zal mail voor "user+something op some.domain" als volgt
behandelen:
-- Als er een user of een alias is "user+something" lever die mail dan af
   bij die user of dat alias,
-- Als die user of dat alias niet bestaan probeer de mail dan af te leveren
   bij "user".
Op deze manier kan een user, die maar één adres "user" heeft zich met
verschillende virtuelen adressen "user+nogwat" registreren op websites en
mailinglists. Ik weet niet of dit sendmail-specifiek is, en ik denk ook
niet dat deze constructie algemeen gebruikt wordt. Maar, met name op
mailinglists, kom ik toch nog wel eens zo'n "+"-adres tegen. Het is iets
waar je zeker rekening mee moet houden als je filtert op afzender-adressen
in binnenkomende mail of bestemminen in uitgaande mail. Houdt er bij filters
voor binnenkomende mail (met name als je ook mail voor derden verwerkt)
bij de recepient-addresses ook rekening mee dat deze constructie bestaat.

En voordat iedereen nu zijn inschrijving op deze mailinglist gaat
veranderen in iets als "pietje+linuxlist op mijn.domein": controleer eerst
of het voor jou zal gaan werken. Als je je eigen mailserver draait op
je eigen domain dan heb je de dingen zelf in de hand. Met sendmail zal
het wel werken tenzij je een heel bijzondere configuratie hebt ingesteld.
Hoe dat met andere MTA's zit weet ik niet. Als je je mail ophaalt met
POP of IMAP uit een mailbox bij een provider dan hangt het van de provider
af of zo'n "+"-constructie zal gaan werken. Met een simpel mailtje naar
"jouw.naam+test op jouw.domein" kan je dat testen.


Groeten,

Kees.


-- 
Kees Theunissen
F.O.M.-Instituut voor Plasmafysica "Rijnhuizen", Nieuwegein
E-mail: theuniss op rijnh.nl,     Tel: 030-6096724,     Fax: 030-6031204




More information about the Linux mailing list