PDA

Просмотр полной версии : E-mail


Programmist
28.06.2008, 18:46
Самый первый косяк в том что электронный адрес нужно проверить!
В книге PHP рецепты программирования Д. Скляр A. Трахнтенбрегр
Глава 9 Форма, пункт 9.5:
Проверка корректности в вода в форме: Адреса электронной почты стр 254
Есть сылка на скрипт, проверки формы неким Калом Хендерсоном(Cal Henderson), он использует правила граматики извлеченные из RFC

Сам скрипт доступен для загрузки по адресу iamcal.com (http://code.iamcal.com/php/rfc822/rfc822.phps)
Скачав эту мегу функции, ничего не нужно настраивать, я скопировал в скрипт и запустил.
Был предложен списк емейлов и результат проверки, некоторые результаты меня поставили под сомнения написания этого чудо скрипта. Поиск в помощь, в сети нашел регулярное выражения проверки емейлов смонтировал со скриптом. И вписал в скрипт условие если функция и регулярное выражения приносят положитеьный резульаты то призновать в веденный электронный адрес правильным, вот что у меня получилось:


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body bgcolor="cacaca" text="0000ff">
<?php

#
# RFC822 Email Parser
#
# By Cal Henderson <cal@iamcal.com>
# This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
# http://creativecommons.org/licenses/by-sa/2.5/
#
# $Revision: 1.1 $
#

################################################## ################################

function is_valid_email_address($email){

$qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';

$dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';

$atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
'\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';

$quoted_pair = '\\x5c[\\x00-\\x7f]';

$domain_literal = "\\x5b($dtext|$quoted_pair)*\\x5d";

$quoted_string = "\\x22($qtext|$quoted_pair)*\\x22";

$domain_ref = $atom;

$sub_domain = "($domain_ref|$domain_literal)";

$word = "($atom|$quoted_string)";

$domain = "$sub_domain(\\x2e$sub_domain)*";

$local_part = "$word(\\x2e$word)*";

$addr_spec = "$local_part\\x40$domain";

return preg_match("!^$addr_spec$!", $email) ? 1 : 0;
}

################################################## ################################

function test($email){
$e='x00';
if(!preg_match("/[0-9a-z_]+@[0-9a-z_^\.]+\.[a-z]{2,3}/i", $email)) {$t='<b>[-]Ошибка</b>';} else {$t='[+]Верно';$e[1]=1;};
(is_valid_email_address($email)?$e[2]=1:$e[2]=0);
if ($e=='x11'){$e='[+]Верно'; $bg=' bgcolor="#ffffff" ';} else {$e='<b>[-]Ошибка</b>'; $bg=' bgcolor="#FFB594" ';}
echo "<tr $bg><td><b>".HtmlEntities($email)."</b></td>";
echo "<td>".(is_valid_email_address($email)?'[+]Верно':'<b>[-]Ошибка</b>')."</td><td>$t</td><td>$e</td></tr>";
}

################################################## ################################

?>

<table border="0" bgcolor="#cacafa" align="center">
<tr>
<th width="410">Вводной E-mail</th>
<th width="90">Функция Кала:</th>
<th width="90">Рег. выр-ние:</th>
<th width="90">Итог:</th>
</tr>
<?php test('cal@iamcalx.com'); ?>
<?php test('cal+henderson@iamcalx.com'); ?>
<?php test('cal henderson@iamcalx.com'); ?>
<?php test('"cal henderson"@iamcalx.com'); ?>
<?php test('cal@iamcalx'); ?>
<?php test('cal@iamcalx com'); ?>
<?php test('cal@hello world.com'); ?>
<?php test('cal@[hello world].com'); ?>
<?php test('cal@[hello\\ world].com'); ?>
<?php test('abcdefghijklmnopqrstuvwxyz@abcdefghijklmnopq rstuvwxyz'); ?>

<?php test('woo\\ yay@example.com'); ?>
<?php test('woo\\@yay@example.com'); ?>
<?php test('woo\\.yay@example.com'); ?>

<?php test('"woo yay"@example.com'); ?>
<?php test('"woo@yay"@example.com'); ?>
<?php test('"woo.yay"@example.com'); ?>
<?php test('"woo\\"yay"@test.com'); ?>

<?php test('webstaff@redcross.org'); ?>

</table>

Результат выполнения этого скрипта:
http://forum.clubelit.ru/attachment.php?attachmentid=2737&stc=1&d=1214664207

Вообщем не плохо получилось.

Programmist
28.06.2008, 18:53
<?php
function show_form()
{
?>
<form action="" method=post enctype="multipart/form-data">
<div align="center">
<br />Имя*<br />
<input type="text" name="name" size="40">
<br />Контактный телефон<br />
<input type="text" name="tel" size="40">
<br />Контактный email*<br />
<input type="text" name="email" size="40">
<br />Teма<br />
<input type="text" name="title" size="40">
<br />Сообщение*<br />
<textarea rows="10" name="mess" cols="30"></textarea>
<br />Файл<br />
<input name="attachfile" type="file" size="28">
<br />Изображение<br />
<input name="attachimage" type="file" size="28">
<br /><br /><input type="submit" value="Отправить" name="submit">
</div>
</form>
* Помечены поля, которые необходимо заполнить
<?
}

function complete_mail() {
// $_POST['title'] содержит данные из поля "Тема", trim() - убираем все лишние пробелы и переносы строк, htmlspecialchars() - преобразует специальные символы в HTML сущности, будем считать для того, чтобы простейшие попытки взломать наш сайт обломались, ну и substr($_POST['title'], 0, 1000) - урезаем текст до 1000 символов. Для переменных $_POST['mess'], $_POST['name'], $_POST['tel'], $_POST['email'] все аналогично
$_POST['title'] = substr(htmlspecialchars(trim($_POST['title'])), 0, 1000);
$_POST['mess'] = substr(htmlspecialchars(trim($_POST['mess'])), 0, 1000000);
$_POST['name'] = substr(htmlspecialchars(trim($_POST['name'])), 0, 30);
$_POST['tel'] = substr(htmlspecialchars(trim($_POST['tel'])), 0, 30);
$_POST['email'] = substr(htmlspecialchars(trim($_POST['email'])), 0, 50);
// если не заполнено поле "Имя" - показываем ошибку 0
if (empty($_POST['name']))
output_err(0);
// если неправильно заполнено поле email - показываем ошибку 1
if(!preg_match("/[0-9a-z_]+@[0-9a-z_^\.]+\.[a-z]{2,3}/i", $_POST['email']))
output_err(1);
// если не заполнено поле "Сообщение" - показываем ошибку 2
if(empty($_POST['mess']))
output_err(2);
// обратите внимание, теперь мы можем писать красивые письма, с помощью html тегов ;-)
$mess = '
<b>Имя отправителя:</b>'.$_POST['name'].'<br />
<b>Контактный телефон:</b>'.$_POST['tel'].'<br />
<b>Контактный email:</b>'.$_POST['email'].'<br />
'.$_POST['mess'];

// подключаем файл класса для отправки почты
require 'class.phpmailer.php';

$mail = new PHPMailer();
$mail->From = 'test@test.ru'; // от кого
$mail->FromName = 'www.php-mail.ru'; // от кого
$mail->AddAddress('to@yandex.ru', 'Имя'); // кому - адрес, Имя
$mail->IsHTML(true); // выставляем формат письма HTML
$mail->Subject = $_POST['title']; // тема письма

// если был файл, то прикрепляем его к письму
if(isset($_FILES['attachfile'])) {
if($_FILES['attachfile']['error'] == 0){
$mail->AddAttachment($_FILES['attachfile']['tmp_name'], $_FILES['attachfile']['name']);
}
}
// если было изображение, то прикрепляем его в виде картинки к телу письма.
if(isset($_FILES['attachimage'])) {
if($_FILES['attachimage']['error'] == 0){
if (!$mail->AddEmbeddedImage($_FILES['attachimage']['tmp_name'], 'my-attach', 'image.gif', 'base64', $_FILES['attachimage']['type']))
die ($mail->ErrorInfo);
$mess .= 'А вот и наша картинка:<br /><img src="cid:image.gif" border=0><br />я показал как ее прикреплять, соответственно Вам осталось вставить ее в нужное место Вашего письма ;-) ';
}
}
$mail->Body = $mess;

// отправляем наше письмо
if (!$mail->Send()) die ('Mailer Error: '.$mail->ErrorInfo);
echo 'Спасибо! Ваше письмо отправлено.';
}

function output_err($num)
{
$err[0] = 'ОШИБКА! Не введено имя.';
$err[1] = 'ОШИБКА! Неверно введен e-mail.';
$err[2] = 'ОШИБКА! Не введено сообщение.';
echo '<p>'.$err[$num].'</p>';
show_form();
exit();
}

if (!empty($_POST['submit'])) complete_mail();
else show_form();
?>

Cрипт хорош для того что бы разобратся как он работает, но для реального использования требует даработок.
Источник: Сайт (http://www.php-mail.ru/?id=4) , также на нем есть интересные коментарии.
Также понравился сайт (http://www.netangels.ru/support/articles/php-mail/) , давольно плавно вводить в профессиональные дебри по вопросу отправка почти.

Powar
28.06.2008, 22:01
return preg_match("!^$addr_spec$!", $email) ? 1 : 0;Это конечно хорошо, но где проверка на существование адреса ? =)
Я делаю как минимум проверку на существование домена, функцией getipbyaddr(), соотвественно отрезав предварительно домен от всего адреса.
Видел в сети скрипт который вроде как может проверять и существование почтового ящика, правда хз не проверял. В теории это возможно.

Programmist
29.06.2008, 00:54
This is the full RFC 2822 regular expression for matching
email addresses, with comments already stripped.

It weighs in at a tiny 3768 bytes.

(((((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d
\x0a)[\x20\x09]+)*))*?(([\x41-\x5a\x61-\x7a]|[\x30-\x39]|[\x
21\x23-\x27\x2a\x2b\x2d\x2e\x3d\x3f\x5e\x5f\x60\x7b-\x7e])+(
\x2e([\x41-\x5a\x61-\x7a]|[\x30-\x39]|[\x21\x23-\x27\x2a\x2b
\x2d\x2e\x3d\x3f\x5e\x5f\x60\x7b-\x7e])+)*)((([\x20\x09]*(\x
0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))
*?)|(((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x
0d\x0a)[\x20\x09]+)*))*?\x22(((([\x20\x09]*(\x0d\x0a))?[\x20
\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))?(([\x01-\x08\
x0b\x0c\x0e-\x1f\x7f]|[\x21\x23-\x5b\x5d-\x7e])|(\x5c([\x01-
\x09\x0b\x0c\x0e-\x7f]|(\x0a*\x0d*([\x00-\x09\x0b\x0c\x0e-\x
7f]\x0a*\x0d*)*))|(\x5c[\x00-\x7f]))))*((([\x20\x09]*(\x0d\x
0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))?\x2
2((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x
0a)[\x20\x09]+)*))*?)|(((((([\x20\x09]*(\x0d\x0a))?[\x20\x09
]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?([\x41-\x5a\x61-
\x7a]|[\x30-\x39]|[\x21\x23-\x27\x2a\x2b\x2d\x2e\x3d\x3f\x5e
\x5f\x60\x7b-\x7e])+((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|(
[\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?)|(((([\x20\x09]*(\x0
d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*
?\x22(((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\
x0d\x0a)[\x20\x09]+)*))?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|[
\x21\x23-\x5b\x5d-\x7e])|(\x5c([\x01-\x09\x0b\x0c\x0e-\x7f]|
(\x0a*\x0d*([\x00-\x09\x0b\x0c\x0e-\x7f]\x0a*\x0d*)*))|(\x5c
[\x00-\x7f]))))*((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x2
0\x09]+((\x0d\x0a)[\x20\x09]+)*))?\x22((([\x20\x09]*(\x0d\x0
a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?))(
\x2e((((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\
x0d\x0a)[\x20\x09]+)*))*?([\x41-\x5a\x61-\x7a]|[\x30-\x39]|[
\x21\x23-\x27\x2a\x2b\x2d\x2e\x3d\x3f\x5e\x5f\x60\x7b-\x7e])
+((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x
0a)[\x20\x09]+)*))*?)|(((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+
)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?\x22(((([\x20\x09]
*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+
)*))?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|[\x21\x23-\x5b\x5d-\
x7e])|(\x5c([\x01-\x09\x0b\x0c\x0e-\x7f]|(\x0a*\x0d*([\x00-\
x09\x0b\x0c\x0e-\x7f]\x0a*\x0d*)*))|(\x5c[\x00-\x7f]))))*(((
[\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[
\x20\x09]+)*))?\x22((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([
\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?)))*))\x40((((([\x20\x
09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x0
9]+)*))*?(([\x41-\x5a\x61-\x7a]|[\x30-\x39]|[\x21\x23-\x27\x
2a\x2b\x2d\x2e\x3d\x3f\x5e\x5f\x60\x7b-\x7e])+(\x2e([\x41-\x
5a\x61-\x7a]|[\x30-\x39]|[\x21\x23-\x27\x2a\x2b\x2d\x2e\x3d\
x3f\x5e\x5f\x60\x7b-\x7e])+)*)((([\x20\x09]*(\x0d\x0a))?[\x2
0\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?)|(((([\x20
\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\
x09]+)*))*?\x5b(((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x2
0\x09]+((\x0d\x0a)[\x20\x09]+)*))?(([\x01-\x08\x0b\x0c\x0e-\
x1f\x7f]|[\x21-\x5a\x5e-\x7e])|(\x5c([\x01-\x09\x0b\x0c\x0e-
\x7f]|(\x0a*\x0d*([\x00-\x09\x0b\x0c\x0e-\x7f]\x0a*\x0d*)*))
|(\x5c[\x00-\x7f]))))*((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)
|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))?\x5d((([\x20\x09]*(\
x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*)
)*?)|((((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((
\x0d\x0a)[\x20\x09]+)*))*?([\x41-\x5a\x61-\x7a]|[\x30-\x39]|
[\x21\x23-\x27\x2a\x2b\x2d\x2e\x3d\x3f\x5e\x5f\x60\x7b-\x7e]
)+((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\x0d\
x0a)[\x20\x09]+)*))*?)(\x2e(((([\x20\x09]*(\x0d\x0a))?[\x20\
x09]+)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?([\x41-\x5a\x
61-\x7a]|[\x30-\x39]|[\x21\x23-\x27\x2a\x2b\x2d\x2e\x3d\x3f\
x5e\x5f\x60\x7b-\x7e])+((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+
)|([\x20\x09]+((\x0d\x0a)[\x20\x09]+)*))*?))*)))


If you want to strip comments too, you'll need to run this
recursivley until it fails to match:

(\x28(((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x20\x09]+((\
x0d\x0a)[\x20\x09]+)*))?(|(\x5c([\x01-\x09\x0b\x0c\x0e-\x7f]
|(\x0a*\x0d*([\x00-\x09\x0b\x0c\x0e-\x7f]\x0a*\x0d*)*))|(\x5
c[\x00-\x7f]))))*((([\x20\x09]*(\x0d\x0a))?[\x20\x09]+)|([\x
20\x09]+((\x0d\x0a)[\x20\x09]+)*))?\x29)




$name = '[^@\s]+';
$sub_domain = '[-a-z0-9]+\.';

// country codes
$cc = '[a-z]{2}';

// top level domains
$tlds = "$cc|com|net|edu|org|gov|mil|int|biz|pro|info|arpa| aero|coop|name|museum";

$email_pattern = "/^$name@($sub_domain)+($tlds)$/ix";
preg_match($email_pattern, $email);





if(checkdnsrr($host, "MX")) {
if (!getmxrr($host, $mxhost, $mxweight)) {
echo "Can't found mail servers records!";
}
}


,в этих записях содержатся назания серверов, отвечающих за обмен почтой.

После того, как записи найдены, мы обращаемся к почтовым серверам с
запросом, существует ли на них, интересующий нас почтовый ящик:

Через сокеты делаем -), я свой adsl модем через сокеты перегружал, а если еще с icq ботом код за конектить, можно сделать вроде умного дома, через мобилу управлять)

$fp = fsockopen($host, 25);

fputs($fp, "HELO {$_SERVER['SERVER_NAME']}\r\n");
fgets($fp, 1024);

fputs($fp, "MAIL FROM: <httpd@{$_SERVER['SERVER_NAME']}>\r\n");
fgets($fp, 1024);

fputs($fp, "RCPT TO: <$email>\r\n");
$line = fgets($fp, 1024);

fputs($fp, "QUIT\r\n");

fclose($fp);


Анализируя ответ от сервера мы можем узнать, существует ящик, или нет:

if (substr($line, 0, 3) != "250") {
// не существует
} else {
// существует
}

Вся функция целиком:


<?php
function isEmail($email, $check_mx = true) {
// all characters except @ and whitespace
$name = '[^@\s]+';

// letters, numbers, hyphens separated by a period
$sub_domain = '[-a-z0-9]+\.';

// country codes
$cc = '[a-z]{2}';

// top level domains
$tlds = "$cc|com|net|edu|org|gov|mil|int|biz|pro|info|arpa| aero|coop|name|museum";

$email_pattern = "/^$name@($sub_domain)+($tlds)$/ix";

if (preg_match($email_pattern, $email, $check_pieces)) {
// check mail exchange or DNS
if ($check_mx) {
$host = substr(strstr($check_pieces[0], '@'), 1);
if (in_array($host, $skip_check)) {
return true;
}

//Check DNS records
if(checkdnsrr($host, "MX")) {
if(!getmxrr($host, $mxhost, $mxweight)) {
return false;
}
} else {
$mxhost[] = $host;
$mxweight[] = 1;
}

$weighted_host = array();
for($i = 0; $i < count($mxhost); $i ++) {
$weighted_host[($mxweight[$i])] = $mxhost[$i];
}
ksort($weighted_host);

foreach($weighted_host as $host) {
if (!($fp = @fsockopen($host, 25, $errno, $errstr))) {
continue;
}

$stopTime = time() + 12;
$gotResponse = FALSE;
stream_set_blocking($fp, FALSE);

while(true) {
$strresp = fgets($fp, 1024);
if(substr($strresp, 0, 3) == "220") {
$stopTime = time() + 12;
$gotResponse = true;
} elseif (($strresp == "") && ($gotResponse)) {
break;
} elseif(time() > $stopTime) {
break;
}
}
if(!$gotResponse) {
continue;
}
stream_set_blocking($fp, true);

fputs($fp, "HELO {$_SERVER['SERVER_NAME']}\r\n");
fgets($fp, 1024);

fputs($fp, "MAIL FROM: <httpd@{$_SERVER['SERVER_NAME']}>\r\n");
fgets($fp, 1024);

fputs($fp, "RCPT TO: <$email>\r\n");
$line = fgets($fp, 1024);

fputs($fp, "QUIT\r\n");

fclose($fp);
if(substr($line, 0, 3) != "250") {
return false;
} else {
return true;
}
}
return false;
}
return true;
}
return false;
}
?>