Syntaktická kontrola
V první řadě tu máme syntaktickou kontrolu. Na webu najdete spoustu pokusů, jak tuto kontrolu provádět, já sám jsem se na jedné podílel (příklad), ale dodatečně jsem v ní stejně našel chybu. Proto uvádím řešení, o kterém si aktuálně myslím, že je správné:
<?php
/** Kontrola e-mailové adresy
* @param string $email e-mailová adresa
* @return bool syntaktická správnost adresy
*/
function check_email($email)
{
$atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // znaky tvořící uživatelské jméno
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // jedna komponenta domény
return eregi("^$atom+(\\.$atom+)*@($domain?\\.)+$domain\$", $email);
}
?>
Ověření, zda adresa přijímá zprávy
Dále je možné kontrolovat, zda uvedená doména přijímá e-maily, což zjistí třeba funkce checkdnsrr. Podle RFC 2821 sice doména může poštu přijímat i bez MX záznamu, ale nebývá to zvykem.
Dále je možné server oťukat a zjistit, zda e-mail přijme. To je asi nejdůkladnější automatické řešení:
<?php
/** Ověření funkčnosti e-mailu
* @param string $email adresa příjemce
* @param string $from adresa odesílatele
* @return bool na adresu lze doručit zpráva, null pokud nejde ověřit
*/
function try_email($email, $from)
{
if (!function_exists('getmxrr')) {
return null;
}
$domain = preg_replace('~.*@~', '', $email);
getmxrr($domain, $mxs);
if (!in_array($domain, $mxs)) {
$mxs[] = $domain;
}
$commands = array(
"HELO " . preg_replace('~.*@~', '', $from),
"MAIL FROM: <$from>",
"RCPT TO: <$email>",
);
foreach ($mxs as $mx) {
$fp = @fsockopen($mx, 25);
if ($fp && substr($s = fgets($fp), 0, 3) == '220') {
while ($s{3} == '-') {
$s = fgets($fp);
}
foreach ($commands as $command) {
fwrite($fp, "$command\r\n");
if (substr($s = fgets($fp), 0, 3) != '250') {
return false;
}
while ($s{3} == '-') {
$s = fgets($fp);
}
}
return true;
}
}
return false;
}
?>
Toto řešení ale pochopitelně nebude fungovat u serverů aplikujících greylisting.
Ověření, zda má uživatel adresu pod kontrolou
Pokud zároveň chceme ověřit, že má uživatel adresu pod kontrolou, musíme mu poslat zprávu:
<?php
/** Vygenerování náhodného řetězce
* @param int [$count] délka vráceného řetězce
* @param int [$chars] použité znaky: <=10 číslice, <=36 +malá písmena, <=62 +velká písmena
* @return string náhodný řetězec
*/
function rand_chars($count = 8, $chars = 36) {
$return = "";
for ($i=0; $i < $count; $i++) {
$rand = rand(0, $chars - 1);
$return .= chr($rand + ($rand < 10 ? ord('0') : ($rand < 36 ? ord('a') - 10 : ord('A') - 36)));
}
return $return;
}
$rand_chars = rand_chars();
if (mysql_query("INSERT INTO emaily (email, rand_chars) VALUES ('$_POST[email]', '$rand_chars')")) {
$zprava = "Pokud máte zájem o služby serveru $_SERVER[SERVER_NAME], tak prosím navštivte tento odkaz:
http://$_SERVER[SERVER_NAME]/email_overit.php?id=" . mysql_insert_id() . "&rand_chars=$rand_chars
Pokud o služby serveru zájem nemáte, tak tuto zprávu prosím ignorujte.";
$hlavicky = "MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit";
mail($_POST["email"], "Overeni adresy", $zprava, $hlavicky);
}
// email_overit.php:
mysql_query("UPDATE emaily SET overeno = 1 WHERE id = '$_GET[id]' AND rand_chars = '$_GET[rand_chars]'");
?>
Závěr
Záleží jen na vás, jak moc důkladně chcete kontrolu e-mailové adresy provádět. Nejčastěji se používají krajní varianty – buď pouhá syntaktická kontrola, nebo ověření, zda má uživatel adresu pod kontrolou.