Три письма на Perl

<P class=text1><B>Те, кто имел дело с Perl, знают, что написание на этом
мощном языке программирования скрипта для создания и отправки писем - для начинающего
дело достаточно сложное. Мы рассмотрим три варианта таких скриптов</B><BR>
<H4>Вариант первый</H4>
<P>Итак, первый вариант такого скрипта, самый простой:</P>
<PRE>1.| open (SENDMAIL, "|/usr/sbin/sendmail -t")
2.|    or die "sendmail not ready";
3.| print SENDMAIL "From: John Doe <jd\@domain.com>\n";
4.| print SENDMAIL "To: Frank Smith <fs\@domain.com>\n";
5.| print SENDMAIL "Reply-To: Frank Smith <BR>    <fs\@domain.com>\n";
6.| print SENDMAIL "Subject: Test.\n\n";
7.| print SENDMAIL "It's just test!!!";
8.| close (SENDMAIL) <BR>    or warn "sendmail didn't close nicely";</PRE>
<P>На первый взгляд, ничего сложного. Но давайте присмотримся повнимательнее.</P>
<P>Вначале открываем файл sendmail как поток. Другими словами, подготавливаем
программу sendmail к приему данных и присваиваем ей handle SENDMAIL. Надеюсь, вы заметили,
что в конце строки нет точки с запятой. Она стоит на следующей строке, так как там стоит
условие аварийного завершения скрипта в случае ошибки открытия файла.</P>
<P>В третьей строке мы передаем в sendmail строку "From: your\@email.com\n".
Что это значит? Давайте разбирать по порядку. Данная строка содержит информацию, сообщающую
почтовому серверу, от кого получено данное письмо. При формировании письма почтовый сервер
поместит в поле От: имя и адрес, взятые из этой строки.</P>
<P>Четвертая, пятая и шестая строки, как вы, наверное, догадались, указывают
серверу адресата (то есть того, кому нужно ответить на данное письмо) и тему письма.</P>
<P>Седьмая строка скрипта содержит тело сообщения - собственно содержание
письма. Таких строк может быть несколько.</P>
<P>Наконец, последняя строка является признаком конца письма и закрывает
программу sendmail. В случае некорректного закрытия скрипт запишет предупреждение в лог-файл
сервера.</P>
<P>Обратите внимание на то, что перед символом @ обязательно должна стоять
обратная косая черта (\). Иначе знак @ будет ошибочно принят за признак массива, что вызовет
аварийное завершение скрипта.</P>
<P>Вот и все - письмо отослано. Но вот вопрос: что за \n стоит в конце
каждой строки, а в шестой строке - даже дважды? Эта последовательность обозначает перевод
строки в Unix-подобных системах. В данном же случае она представляет собой ни что иное
как конец команды. В шестой она повторяется дважды, чтобы сообщить серверу, что команды
закончились и дальше идет тело письма.</P>
<P><B>Вариант второй</B></P>
<P>Второй вариант скрипта для отправки писем является модульным. Его несколько сложнее
устанавливать, зато удобнее использовать.</P>
<P>Для того чтобы пользоваться этим скриптом дома, вам необходимо установить
модуль MIME::Lite, который, как и многие другие модули для Перла, можно скачать из архива
по адресу <A href="http://search.cpan.org/" >http://search.cpan.org/</A>. </P>
<P>Скачав и установив MIME::Lite, приступаем к разбору скрипта:</P>
<PRE>1.| use MIME::Lite;
2.| $msg = MIME::Lite->new (
3.|    From =>'John Doe <jd@domain.com>',
4.|    To =>'Frank Smith <fs@domain.com>',
5.|    Subject =>'Test.',
6.|    Data =>"It's just test!!!"
7.|    );
8.| $msg->send;</PRE>
<P>Первая строка подключает необходимый нам модуль MIME::Lite. Вторая
создает объект сообщения с параметрами, указанными в строках 3-7.</P>
<P>Назначение третьей, четвертой, пятой и шестой строк нам уже известно
из предыдущего скрипта. С небольшими изменениями: строки взяты не в двойные, а в одинарные
кавычки. Впрочем, это не принципиально. Кроме того, отсутствует обратная косая черта перед
символом @ (если строки взяты в двойные кавычки, ее нужно поставить), и в конце строк
нет \n. Вот и вся разница.</P>
<P>Но за все приходится платить. Этот вариант нагляднее - но у нас появилась
восьмая строка. В ней модулю даются указания о том, что письмо сформировано и что нужно
его отправить.</P>
<P>Иногда возникает необходимость отправить сообщение без sendmail, с
помощью сторонней программы. В этом случае скрипт нужно несколько изменить. Например,
можно использовать nms_sendmail. На его примере и покажем, как это сделать.</P>
<PRE>8. | $^X =~ /(.+)/ or die;
9. | $mailprog = qq|$1 -wT "nms_sendmail" -oi -t|;
10.| open (SENDMAIL, "|$mailprog");
11.| $msg->print (\*SENDMAIL);
12.| close (SENDMAIL);</PRE>
<P>Вместо восьмой строки пишем код, указанный выше. И добавляем строки
из документации к nms_sendmail. Как видим, все просто.</P>
<H4>Третий вариант</H4>
<P>Наконец, рассмотрим последний вариант. Иногда хочется (или приходится)
работать с сервером напрямую, без промежуточных программ. Тогда можно применить способ,
описанный ниже.</P>
<PRE>1. | use IO::Socket;
2. | my $socket = IO::Socket::INET->new ("127.0.0.1:25");
3. | defined $socket or die "ERROR: $!";
4. | $socket->print ("HELO1512");
5. | $r = <$socket>;
6. | $socket->print ("MAIL FROM:John Doe <BR>     <jd\@domain.com>1512");
7. | $r = <$socket>;
8. | $socket->print ("RCPT TO:Frank Smith <BR>     <fs\@domain.com>1512");
9. | $r = <$socket>;
10.| $socket->print ("DATA1512");
11.| $r = <$socket>;
12.| $socket->print ("From:John Doe <BR>     <jd\@domain.com>\nTo:Frank Smith
     <fs\@domain.com>\nSubject:Test.<BR>     \n\nIt's just test!!!1512");
13.| $r = <$socket>;
14.| $socket->print ("\.1512");
15.| $r = <$socket>;
16.| $socket->print ("QUIT1512");
17.| $r = <$socket>;</PRE>
<P>Данный листинг демонстрирует работу с соккетами. Процедура эта непростая,
так что обычно стараются обойтись без нее. Но мы для полноты картины рассмотрим и этот
вариант отправки писем. Итак, приступим.</P>
<P>Первая строка аналогична предыдущему примеру - с той лишь разницей,
что мы используем другой модуль.</P>
<P>Вторая строка создает объект соккета, т. е. соединение с компьютером,
IP-адрес которого 127.0.0.1, на 25-й порт. Третьей строкой мы проверяем, установлено ли
соединение. Если соединение не установлено, происходит аварийное завершение скрипта.</P>
<P>Теперь - самое главное. В предыдущих примерах мы не формировали заголовок
письма - это автоматически делала программа sendmail. Но здесь придется все прописывать
собственноручно, в том числе и заголовок.</P>
<P>В четвертой строке серверу передается текст "HELO1512". Это означает,
что мы готовы к передаче данных. В пятой строке читаем ответ сервера. Это необходимо для
корректного общения с сервером и обработки ошибок (здесь мы это рассматривать не станем
- все подробно описано в спецификации протокола). Такая же процедура выполняется после
каждой команды серверу.</P>
<P>В шестой строке серверу передается информация о том, от кого поступило
письмо; в восьмой - кому это письмо нужно отослать. Внимательно посмотрите на эти строки.
Они отличаются от тех, что мы использовали ранее,- потому что мы общаемся с сервером на
прямую.</P>
<P>В десятой строке серверу сообщается о том, что мы готовы передавать
тело письма. Под телом письма подразумевается не только то, что будет отображаться на
экране получателя, но и заголовок. Давайте разобьем эту строку на несколько частей и рассмотрим
их более подробно:</P>
<PRE>From:John Doe <jd\@domain.com>\n
To:Frank Smith <fs\@domain.com>\n
Subject:Test.\n\n
It's just test!!!1512</PRE>
<P>Теперь более или менее понятно, что есть что. Единственное замечание:
перед собственно письмом должно стоять два \n (обязательно два - иначе сервер не поймет,
что здесь начинается письмо).</P>
<P>В строке 14 серверу сообщается об окончании письма. Наконец, в шестнадцатой строке
разрывается соединение.</P>
<P>И еще один немаловажный момент. В конце каждой команды ставится последовательность
1512, которая сообщает серверу об окончании данной команды.</P>

По материалам:  Дмитрий ЛЯЛЮЕВ, Комиздат

Возврат к списку