В этой статье будет рассказано о том, как используя модули Perl LWP::UserAgent и MIME::Lite скачать HTML страницу и отослать ее в письме вместе со всеми вложенными изображениями.
Применяя изложенный метод я ежедневно получаю свежие анекдоты в свой почтовый ящик - ну лень мне каждый день лазить в Инет :-)
Для работы нам потребуются следующие модули (взять их можно на CPAN
Для примера разберем, как выкачиваются все истории за день с сайта "Анекдоты из России"
Сайт постоянно обновляется, поэтому имеет смысл выкачивать все истории за вчера, там содержимое уже меняться не будет.
Адрес нужной нам страницы строится следующим образом :
сайт анекдотов/an/an год месяц/o год месяц день .html
причем от года берутся только 2 последние цифры, а месяц и день дополняется до 2 символов нулями слева, если это необходимо.
Таким образом, страница
Небольшое лирическое отступление для тех, кто только начал осваивать Perl.
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();
Техническую реализацию скрипта я буду описывать схематически, если что будет не понятно - смотрите исходник.
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/lwp_mime.html
Исходник программы http://takiedela.narod.ru/press/html_on_email3.pl
Размещать статью полностью и или частично можете где угодно, только не забывайте меня упомянуть как автора ;-)
31-07-2002
Vladimir Maximenko
E-Mail :
home page : http://takiedela.narod.ru