Статьи о почте

Новости

Все новости

Разное в мире IT

Все заметки

mailinfo.ru - Статьи о почте

Чтение почты через Web-интерфейс на perl

Прислал(а) Александр Сухинин [11 января 2002]

раздел: [Исходники]

В последнее время довольно популярными стали почтовые системы с Web-интерфейсом.
Надо заметить, это довольно удобно, особенно для пользователей, которые выходят в интернет с разных машин.
Для написания оной программы необходима библиотека
Mail::POP3Client
Назначение библиотеки очевидно - видно из названия. В ней содержатся методы доступа к почтовому ящику POP3.
Простейший набор кода для проверки почтового ящика на наличие сообщений выглядит так:

use Mail::POP3Client;
    login = "mailuser";
    $password = "parol";
    $mailserver = "mail.server";
    $pop = new Mail::POP3Client( USER => $login,
        PASSWORD => $password,
         HOST => $mailserver );
print "В вашем почтовом ящике ",$pop->Count()," сообщений.
n";

Все вообщем, просто:

  1. Создать соединение;
  2. Посчитать количество писем.
Первый пункт реализуем созданием объекта $pop, второй - вызовом метода Count() сего объекта.
Метод Count() еще имеет одну особенность - если он возвращает -1, то соединение не было создано, иными словами, не удалось соединиться с сервером.
Если мы в вышеуказанном коде последнюю строчку заменим на

if ($pop->Count() == -1 ) {
    print "Не удалось соединиться с сервером!
n";
    } else {
       print "В вашем почтовом ящике ",$pop->Count()," сообщений.
n";
}

, то выглядеть наш скрипт будет несколько приличнее (как-никак, обработка нештатной ситуации:).
Если этот код заработал, то нужно развивать успех. Итак, методы класса POP3Client:

new( USER => \'user\', PASSWORD => \'password\', HOST => \'host\', PORT => 110, DEBUG => 0, AUTH_MODE => \'BEST\', TIMEOUT => 60 )

Это конструктор класса. Разработчики библиотеки настоятельно рекомендуют пользоваться объекным стилем написания.
Аргументы метода следующие:
  • USER = имя пользователя
  • PASSWORD = пароль
  • HOST = почтовій сервер
  • PORT = порт
  • DEBUG = если этот параметр равен 1, то в STDERR выводится трафик сокета
  • AUTH_MODE = допустимые значения:\'BEST\', \'PASS\' and \'APOP\'
  • TIMEOUT = число по умолчанию - 60 сек.

Head( MESSAGE_NUMBER )

Возвращает заголовок письма с номером MESSAGE_NUMBER. Результат = строка или массив, в зависимости от контекста. Поддерживается не всеми POP3 серверами.

Body( MESSAGE_NUMBER )

Возвращает тело письма с номером MESSAGE_NUMBER. Результат = массив строк или массив, в зависимости от контекста.

Delete( MESSAGE_NUMBER )

Помечает сообщение на удаление. Удаляется после выполнения команды QUIT. До удаления можно отменить методом Reset.

Close

Закрыть соединение.

Count

Возвращает количество сообщений в почтовом ящике.
Нет цели подменять этой статьей описание библиотеки, поэтому ограничимся только этими описаниями. В библиотеке Mail::POP3Client методов примерно в 2 раза больше, и прочитать его описание в первоисточнике несколько полезней, тем более, что для начала работы достаточно и вышеперечисленных методов.
Теперь было бы неплохо просмотреть список сообщений на сервере, от кого, тема. Для этого сосчитаем сообщения и в цикле выведем их заголовки:


    ....
    print "В вашем почтовом ящике ",$pop->Count(),"сообщений
n";
    for( $i = 1; $i <= $pop->Count(); $i++ ) {
    foreach( $pop->Head( $i ) ) {
       /^(From|Subject):s+/i && print $_, "
n";
    }
    } #закрыть соединение $pop-Close();

Если заработала и сия конструкция, значит все делается правильно, и можно переходить к написанию модуля просмотра сообщений. Просмотреть сообщение №КАКОЙ_ТО можно, вытащив его методом Body(№). Поскольку метод нам вернет массив, то обыкновенным циклом foreach просмотрим письмо.
Вот текст процедуры просмотра тела письма:

sub get_body {
    $numb_mess = shift;
    foreach ($pop->Body($numb_mess)) {
    print $_,"
n";
    } }

Ну, а дальше - дело вкуса, как выбирать сообщение. Я предлагаю сделать ссылочку на тему письма для просмотра оного. Полный листинг сего "шедевра" расположен ниже:

use Mail::POP3Client;
print "Content-type:text/htmlnn";
$login = "mailuser";
$password = "parol";
$mailserver = "mail.server"; # Пробуем прочесть переданные параметры # Этот способ работает только с методом GET!!!
$temp=$ENV{\'QUERY_STRING\'}; # Разбор строки параметров
if ($temp ne \'\') {
    @pairs=split(/&/,$temp);
    foreach $item(@pairs) {
    ($key,$content)=split (/=/,$item,2); # Режем на название ключа и значение. # Названия параметров и значения помещаем в хэш
       $data{$key}=$content;
   }
} # Открываем соединение
$pop = new Mail::POP3Client( USER => $login,
        PASSWORD => $password,
        HOST => $mailserver ); # Если был передан параметр view со значением, то просматриваем # сообщение с номером view
   if ($data{\'view\'} ne \'\') {
   &get_body($data{\'view\'});
} else { # Не было параметров
print "В вашем почтовом ящике ",$pop->Count()," сообщений.
n"; for( $i = 1; $i <= $pop->Count(); $i++ ) {
    foreach( $pop->Head( $i ) ) {
        /^(From|Subject):s+/i && print "",$_, "
n";
      }
    } #закрыть соединение
}
      $pop-Close(); #Процедура просмотра сообщения
sub get_body {
        $numb_mess = shift;
        foreach
($pop->Body($numb_mess)) {
        print $_,"
n";
        }
    }

Вот собственно и все. На самом деле я не советую выкладывать сей перл в интернет. Его можно юзать на localhost-е. Почему? Потому что в теле программы находятся значения логинов/паролей, а этого допускать не стоит. Лучше наваять форму с парой полей, и передавать их методом POST этому скрипту. Прочесть строку параметров при передаче методом POST можно кострукцией:

if ($ENV{\'REQUEST_METHOD\'} eq \'POST\') {
         read(STDIN,$temp,$ENV{\'CONTENT_LENGTH\'});
   }

т.е. читать нужно из стандартного потока ввода. Разбор строки точно такой же, как и в методе GET. Для дальнейшей работы с почтовым ящиком пару логин/пароль можно сохранить в скрытом поле или в cookie с периодом устаревания ,например, пол-часа. Далее, первым делом после печати строки Content-type:text/htmlnn, прочтем сей куки:
$cookie = $ENV{\'HTTP_COOKIE\'};

дальше его разбираем, как нам угодно. Я предлагаю следующую реализацию:

if ($data{\'login\'} and $data{\'password\'}) {

# Запомним пароль/логин в куки в виде строки:
     # login::password, время устаревания = 1 час.

     print "Set-Cookie:
login=$form{\'login\'}::$form{\'password\'}; expires=+1H;";
     print "Content-type:text/htmlnn";
     # попытка создать соединение с POP3 сервером
     $pop = new Mail::POP3Client( USER => $data{\'login\'},
         PASSWORD => $data{\'password\'},
         HOST => $mailserver );

} else {
         print "Content-type:text/htmlnn";
         $cookie = $ENV{\'HTTP_COOKIE\'};
     # Разбираем строку, полученную из cookie
      if ($cookie =~ "login") {
      ($nm,$vals) = split(/=/,$cookie);
      ($login,$passwd) = split(/::/,$vals);
      $pop = new Mail::POP3Client( USER => $login,
         PASSWORD => $password,
         HOST => $mailserver );
     # Далее по тексту....
    }

Вот в принципе и все - небольшой простенький mailreader готов. Но есть один существенный недостаток:
"Кириллические" тексты зачастую в письме хранятся в виде mime encoded. Поэтому чтобы их прочесть, нужно использовать соответствующие библиотеки или писать свои конвертеры. Это уже другая тема, и в этой статье обсуждаться не будет.