В этой статье будет рассказано о том, как
используя модули Perl LWP::UserAgent и MIME::Lite скачать
HTML страницу и отослать ее в письме вместе со
всеми вложенными изображениями.

Применяя изложенный метод я ежедневно
получаю свежие анекдоты в свой почтовый
ящик - ну лень мне каждый день лазить в Инет
🙂

Для работы нам потребуются следующие
модули (взять их можно на CPAN http://www.cpan.org)

  • LWP::UserAgent - класс пользовательских
    агентов WWW

  • MIME::Lite - облегченный MIME кодер/декодер
  • URI::URL - работа с URL
  • HTML::LinkExtor - получение списка всех URL в
    документе

  • Time::Local - преобразует компоненты полного
    времени в секунды

Для примера разберем, как выкачиваются
все истории за день с сайта "Анекдоты из
России" (http://www.anekdot.ru).
Сайт постоянно обновляется, поэтому имеет
смысл выкачивать все истории за вчера, там
содержимое уже меняться не будет. Адрес
нужной нам страницы строится следующим
образом :

сайт анекдотов/an/an год месяц/o год месяц день.html

причем от года берутся только 2 последние
цифры, а месяц и день дополняется до 2
символов нулями слева, если это необходимо.

Таким образом, страница http://www.anekdot.ru/an/an0206/o020629.html
содержит все истории за 29 июня 2002 года. 

Небольшое лирическое отступление для тех,
кто только начал осваивать Perl.

Как скачать WEB страницу ?

require LWP::UserAgent; $ua = LWP::UserAgent->new;
$ua-> proxy(['http', 'ftp'],
'адрес прокси-сервера');
$req = new HTTP::Request('GET' =>
'страница для скачивания');
if ($res->is_success) 
{
$page = $res->content;
}

Как отправить письмо с прикрепленными
файлами?

require MIME::Lite;
$msg = MIME::Lite->new( From =>'Ваш@Адрес.com',
To =>'Адрес@Получателя.com', Subject =>'Тема
сообщения', Type => 'multipart/related');
$msg->attach( Type
=>'text/plain; charset=windows-1251', Data => текст письма);
$msg->attach( Type => 'image/gif', Path => путь к файлу,
Filename =>'img.gif');
$msg->send();

Рассмотрим по шагам работу программы.

  • Определяем URL документа
  • Скачиваем содержимое WEB страницы
  • Ищем и скачиваем все содержащиеся на
    странице изображения

  • Меняем ссылки относительно документа на
    их абсолютное значение

  • Присоединяем внешние файлы CSS,JavaScript
  • Кодируем все изображения и собираем MIME
    объект

  • Отсылаем получившееся письмо по
    электронной почте

Техническую реализацию скрипта я буду
описывать схематически, если что будет не
понятно - смотрите исходник.

C ANEKDOT.RU все истории за вчера. Вычисляем
дату - полночь вчерашнего дня. Дополняем
дату нулями слева.

$sutki=24*60*60;
($tek_day,$tek_month,$tek_year)=(localtime)[3,4,5];
$in1=timelocal(0,0,0,$tek_day,$tek_month,$tek_year);
$in2=$in1-$sutki;
($tek_day,$tek_month,$tek_year)=(localtime($in2))[3,4,5];
$tek_month++; $tek_year+=1900;
if ($tek_month<10)
{
$tek_month="0".$tek_month
}
 if ($tek_day<10)
{
$tek_day="0".$tek_day;
}
  $an_year=substr($tek_year, 2, 2);

Страница для скачивания. Определяем адрес
страницы согласно приведенного шаблона.

$url_page= "http://www.anekdot.ru/an/an".$an_year.$tek_month."
/o".$an_year.$tek_month. $tek_day.".html";

Скачиваем содержимое страницы используя
модуль LWP.

if ($url_page && $url_page=~/^(https?|ftp|file|nntp):\/\//) 
{
my $req = new HTTP::Request('GET' => $url_page);
my $res = $ua->request($req);
$gabarit = $res->content;
}

Подключаем внешний CSS и JavaScript. Тут все
очень упрощенно показано, но разобраться
можно - качаем файл со скриптами и
подставляем его в нужное место HTML документа.

внешний CSS = '<style type="text/css">'."\n".'<!--'."\n".
файл со стилями ."\n-->\n</style>\n";
документ HTML =~s/<link([^<>]*?)href="?([^\" ]*)"?([^>]*)>/
внешний CSS /iegmx; внешний JavaScript = '<script><!--'."\n".
файл со скриптами ."\n-->\n</script>\n";
документ HTML =~s/<script([^>]*)src="?([^\" ]*js)"?([^>]*)>/
внешний JavaScript /iegmx;
 

Проходимся по всем ссылкам и меняем
относительный путь на абсолютный.
Необходимо это для того, чтобы нажав на
ссылку в письме мы попадали именно туда,
куда указывала ссылка с документа,
размещенного в Инете.

my $analyseur = HTML::LinkExtor->new;
$analyseur->parse($gabarit);
my @l = $analyseur->links; foreach my $url (@l)
{
my $urlAbs = URI::WithBase->new($$url[2],$racinePage)->abs;
chomp $urlAbs;
if ( ($$url[0] eq 'a') && ($$url[1] eq 'href') && ($$url[2])
&& (($$url[2]!~m!^http://!) && ($$url[2]!~m!^mailto:!)) )
{
 $gabarit=~s/\s href= [\"']? $$url[2] [\"']?/ href="$urlAbs"/gimx;
}

Выбираем из документа все изображения,
скачиваем картинку, определяем тип и
возвращаем ее, закодированную в MIME.

if ( ((lc($$url[0]) eq 'img') || (lc($$url[0]) eq
'src')) )
{
push(@mail, create_image_part($urlAbs));
}
if (lc($ur)=~/gif$/)
{
$type="image/gif";
}
elsif (lc($ur)=~/jpg$/)
{
$type = "image/jpg";
}
else
{
$type = "application/x-shockwave-flash";
}
my $res2 = $ua->request(new HTTP::Request('GET' => $ur));
$buff1=$res2->content;
$file_name = substr($ur,rindex($ur,"/")+1,length($ur)); 
# кодируем очередную картинку my 
$mail = new MIME::Lite( Data => $buff1, Encoding =>'base64', 'Filename'=>$file_name);
$mail->attr('Content-type'=>$type); $mail->attr('Content-Location'=>$ur);

Создаем MIME объект, указываем от кого и
кому письмо, тему сообщения. Если на
странице изображений нет - тип сообщения text/html,
если есть картинки - multipart/related.

$mail = new MIME::Lite 'From' => 'somebody@somewhere.com',
'To' => $to_email, 'Subject' => $url_page, 'Data' => $html; $mail->attr("Content-type"
=> $content_type);
if (@mail)
{
$mail->replace("Type" => "multipart/related");
# присоеденяем каждую картинку
foreach (@mail) {$mail->attach($_);
}
}

Отсылаем страницу по почте. Можно
использовать SMTP или sendmail.

MIME::Lite->send('smtp', " адрес SMTP
сервера ", Timeout=>60); $mail->send();

Выполнение программы.

Помещаем наш скрипт в каталог, откуда
разрешено выполнение программ и делаем
файл исполняемым

chmod 750 /usr/local/www/cgi-bin/html_on_email3.pl

Для того, чтобы окончательно все
автоматизировать, вешаем наш скрипт на CRON.
Для этого в файл /etc/crontab добавляем строчку

0 9 * * * root /usr/local/www/cgi-bin/html_on_email3.pl

и каждое утро в 9 часов читаем свежие
анекдоты.

Для того, чтобы скрипт работал и в
локальной сети необходимо установить
соединение с Инетом и явно указать адреса
прокси- и SMTP - сервера.

$ua->proxy(['http', 'ftp'], 'http://10.0.0.3:3128/'); MIME::Lite->send('smtp',
"10.0.0.1", Timeout=>60);

В завершение хочу заметить, что все можно
было написать и по-другому, более красиво.
Но программа работает, а большего от нее и
не требуется 🙂

Исходник программы http://takiedela.narod.ru/press/html_on_email3.pl

Check Also

Intel выпустила августовские патчи и обновила прошивки для NUC

Компания Intel представила августовский набор патчей, в том числе устранив уязвимость в не…

Оставить мнение