Содержание


Реальные веб-проекты на PHP и MySQL. Разработка почтовой службы с веб-интерфейсом

Часть 5. Просмотр содержимого почтового ящика. Чтение и удаление сообщений

Comments

Серия контента:

Этот контент является частью # из серии # статей: Реальные веб-проекты на PHP и MySQL. Разработка почтовой службы с веб-интерфейсом

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Реальные веб-проекты на PHP и MySQL. Разработка почтовой службы с веб-интерфейсом

Следите за выходом новых статей этой серии.

1. Введение

В предыдущих статьях многократно описывались вопросы настройки и запуска в эксплуатацию самых разнообразных почтовых служб, - таких как sendmail, postfix, exim, Communigate, qmail, использующих в качестве платформы самый широкий спектр современных Linux- и BSD-систем. В настоящее время, по мере развития Всемирной Паутины все чаще возникает вопрос об актуальности использования услуг электронной почты, основанной на веб.

В предыдущих частях цикла статей были рассмотрены вопросы относительно общего плана построения почтовой системы с веб-интерфейсом, создания базы данных под учебный проект и обзора общей библиотеки функций для решения задач обработки почты. Кроме того, мы изучили: главный управляющий сценарий, процесс создания пользователей системы и манипулирование их учетными записями, реализацию входа и выхода. В пятой статье цикла будут рассмотрены вопросы реализации механизмов просмотра содержимого почтового ящика и чтения/удаления сообщений.

Перед началом работы в системе пользователь должен настроить одну или несколько учетных записей электронной почты.

Просмотр содержимого почтового ящика

Возможность просмотра содержимого почтового ящика обеспечивает функция display_list($auth_user, $accountid).

С ее помощью отображается список всех почтовых сообщений, которые находятся в ящике пользователя. Код функции приводится ниже:

function display_list($auth_user, $accountid)
{
  // Отображает список сообщений, находящихся в данном почтовом ящике
  
  global $table_width;
    
  if(!$accountid)
  {
    echo 'Почтовый ящик не выбран<br /><br /><br /><br /><br /><br />.';
  }
  else
  {
    $imap = open_mailbox($auth_user, $accountid);
  
    if($imap)
    {
      echo "<table width=$table_width' cellspacing='0'
                   cellpadding='6'  border='0'>";

      $headers = imap_headers($imap);
      // Мы можем переформатировать эти данные либо получить другую 	
	  //информацию
      // с помощью imap_fetchheaders, но и так совсем не плохо получается )), 	
	  //поэтому просто воспользуемся оператором echo
      $messages = sizeof($headers);
      for($i = 0; $i<$messages; $i++)
      {
        echo '<tr><td bgcolor = "';
        if($i%2)
          echo '#ffffff';
        else 
          echo '#ffffcc';
        echo '"><a href="index.php?action=view-message&messageid='.($i+1).'">';
        echo $headers[$i];
        echo "</a></td></tr>\n";
      }
      echo '</table>';
    } 
    else 
    {
      $account = get_account_settings($auth_user, $accountid);
      echo 'Невозможно открыть почтовый ящик '.$account['server'].
           '.<br /><br /><br /><br />';
    }  
  }
}

Здесь используются IMAP-функции языка PHP. Ключевыми моментами являются открытие почтового ящика и чтение заголовков сообщений.

Почтовый ящик для пользователя может быть открыть с помощью функции open_mailbox($auth_user, $accountid):

function open_mailbox($auth_user, $accountid)
{
  
  // Выбрать почтовый ящик, если он единственный
  if(number_of_accounts($auth_user)==1)
  {
    $accounts = get_account_list($auth_user); 
    $_SESSION['selected_account'] = $accounts[0]; 
    $accountid = $accounts[0];
  }

  // Подключиться к POP3- или IMAP-серверу, выбранному пользователем
  $settings = get_account_settings($auth_user, $accountid);
  if(!sizeof($settings)) return 0;
  $mailbox = '{'.$settings[server];
  if($settings[type]=='POP3')
    $mailbox .= '/pop3';
  
  $mailbox .= ':'.$settings[port].'}INBOX';

  // Подавить вывод предупреждающих сообщений, 
  // не забыть проверить возвращаемое значение
@ $imap = imap_open($mailbox, $settings['remoteuser'], 
                    $settings['remotepassword']);

  return  $imap;
}

Открытие почтового ящика производится с помощью функции imap_open(). В функцию передаются следующие параметры:

  1. mailbox – содержит имя сервера и имя почтового ящика, кроме того, в необязательном порядке может содержать номер порта и протокола. Если протокол не указан, то по умолчанию используется IMAP. При выборе пользователем протокола POP3 параметры этого протокола начинают фигурировать в коде, в месте задания протокола;
  2. username – имя пользователя, под которым осуществляется доступ к почтовому ящику;
  3. password – пароль для доступа к учетной записи.

Кроме этого, допускается передача необязательных параметров для указания опций, таких как режим открытия почтового ящика. Например, параметр ‘open mailbox in read-only’ открывает почтовый ящик в режиме только для чтения.

Результатом вызова функции является поток информации по протоколу IMAP, если почтовый ящик был успешно открыт или значение false, если попытка открытия ящика закончилась неудачей. После обработки информации, переданной вызванной функцией, поток информации можно закрыть, используя функцию imap_close(“imap_flow”). В данном случае поток IMAP передается обратно в главный сценарий, после чего вызывается функция imap_headers(), извлекающая почтовые заголовки для их последующего отображения. Она возвращает информацию о заголовках для всех почтовых сообщений выбранного ящика. Информация, которую она передает, подается в виде массива данных, в котором каждая строка соответствует почтовому сообщению. При этом сообщения отображаются построчно.

Чтение почтовых сообщений

Вывод, который обеспечивает функция display_list(), представляет собой совокупность строк, каждая из которых представляет собой ссылку на определенное сообщение электронной почты. При этом ссылка на сообщение выглядит как:

index.php?action=view-message&messageid=6

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

При передаче параметров в главный управляющий сценарий index.php выполняется следующий фрагмент кода:

	case 'show-headers' :
      case 'hide-headers' :
      case 'view-message' :
      {
        // Если только что выбрано сообщение из списка, либо же
        // оно просматривается и выбрана опция сокрытия или
        // показа заголовков, загрузить сообщение
        $fullheaders = ($action=='show-headers');
        display_message($_SESSION['auth_user'],
                        $_SESSION['selected_account'],
                        $messageid, $fullheaders);
        break;
      }

В данном случае значение переменной action проверяется на равенство строке ‘show_headers’. Проверка дает результат false и значение переменной $fullheaders тоже устанавливается в false. После чего следует вызов функции display_message(). Она реализует обычный HTML-вывод содержимого и ее код представлен ниже:

function display_message($auth_user, $accountid, $messageid, $fullheaders)
{
  // Выводит сообщение электронной почты

  global $table_width;
  
    
  $buttons = array();
  $buttons[0] = 'reply';
  $buttons[1] = 'reply-all';
  $buttons[2] = 'forward';
  $buttons[3] = 'delete';
  if($fullheaders)
    $buttons[4] = 'hide-headers';
  else
    $buttons[4] = 'show-headers';
  
  $message = retrieve_message($auth_user, $accountid, $messageid, $fullheaders);
  if(sizeof($message)==0)
  {
    echo "Невозможно прочитать сообщение номер $messageid".'.<br /><br /><br /><br /
	><br />';
  }
  else
  {
    $message = pretty_all($message);
?>
  <table width = <?php echo $table_width; ?> cellpadding = 4 
  cellspacing = 0  border = 0>
  <tr>
    <td bgcolor = '#cccccc'>
      <b> Тема: </b>
    </td>
    <td bgcolor = '#cccccc'>
      <b> <?php echo $message[subject];?> </b>
    </td>
  </tr>
  <tr>
    <td bgcolor = '#cccccc'>
      <b> От: </b>
    </td>
    <td bgcolor = '#cccccc'>
      <b> <?php echo $message[fromaddress];?> </b>
    </td>
  </tr>
  <tr>
    <td bgcolor = '#cccccc'>
      <b> Кому: </b>
    </td>
    <td bgcolor = '#cccccc'>
      <b> <?php echo $message[toaddress];?> </b>
    </td>
  </tr>
  <tr>
    <td bgcolor = '#cccccc'>
      <b> CC: </b>
    </td>
    <td bgcolor = '#cccccc'>
      <b> <?php echo $message[ccaddress];?> </b>
    </td>
  </tr>
  <tr>    
    <td bgcolor = '#cccccc'>
      <b> Получено: </b>
    </td>
    <td bgcolor = '#cccccc'>
      <b> <?php echo $message[date]; ?> </b>
    </td>
  </tr>
  </table>
  
  <?php display_toolbar($buttons, "&messageid=$messageid");?>
  <table width = <?php echo $table_width; ?> cellpadding = 4 
  cellspacing = 0  border = 0>
  <tr>
    <td bgcolor = '#cccccc'>
  
    <?php echo $message[fullheaders]; ?>
  
    </td>
  </tr>
  </table>
  
  <table width = <?php echo $table_width; ?> cellpadding = 4 
  cellspacing = 0  border = 0>
  <tr>
    <td>
  
    <?php echo $message[body]; ?>
  
    </td>
  </tr>
  </table>
<?php
  }
}

Она обращается к функции retrieve_message($auth_user, $accountid, $messageid, $fullheaders) для извлечения требуемого сообщения из почтового ящика.

Код функции retrieve_message($auth_user, $accountid, $messageid, $fullheaders):

function retrieve_message($auth_user, $accountid, $messageid, $fullheaders)
{
  $message = array();
  if(!($auth_user && $messageid && $accountid))
    return false;
  
  $imap = open_mailbox($auth_user, $accountid);
  if(!$imap) 
    return false;      
  
  $header = imap_header($imap, $messageid);
  if(!$header) 
    return false;
  
  $message['body'] = imap_body($imap, $messageid);
  if(!$message['body']) 
    $message['body'] = "[Отсутствует тело сообщения]\n\n\n\n\n\n";
  if($fullheaders)
    $message['fullheaders'] = imap_fetchheader($imap, $messageid);
  else
  $message['fullheaders'] = '';
  $message['subject'] = $header->subject;
  $message['fromaddress'] =   $header->fromaddress;
  $message['toaddress'] =   $header->toaddress;
  $message['ccaddress'] =   $header->ccaddress;
  $message['date'] =   $header->date;
    
  // Конечно можно получить более подробную информацию,
  // если вместо полей fromaddress и toaddress воспользоваться
  // полями from и to, однако была выбрано именно эта вариация ввиду ее   
  //полноты
  imap_close($imap); 
  return $message;
}

Здесь вновь для открытия почтового ящика используется функция open_mailbox(). В данном случае потребуется получить определенное сообщение и при этом используются три IMAP-функции – imap_header(), imap_fetchheader() и imap_body(). Причем:

  1. imap_headers() – возвращает список заголовков всех сообщений в почтовом ящике в виде массива. Каждому сообщению соответствует один элемент списка;
  2. imap_header() – возвращает заголовки определенного сообщения в виде объекта;
  3. imap_fetchheader() – возвращает заголовки определенного сообщения в виде строки.

В данном случае функция imap_header() используется для заполнения полей определенного заголовка, а imap_fetchheader() для вывода всех заголовков по требованию.

Функции imap_header() и imap_body() создают массив, содержащий элементы требуемого сообщения. При этом функция imap_header() вызывается таким образом:

$header = imap_header($imap, $messageid);

после чего из объекта можно извлечь все поля, необходимые для дальнейшей обработки:

$message[‘subject’] = $header->subject;

а для добавления тела сообщения в массив используется функция imap_body() следующим образом:

$message[‘body’] = imap_body($imap, $messageid);

затем с помощью функции imap_close() закрывается почтовый ящик и возвращается сформированный массив. После чего с помощью функции display_message() можно вывести поля сообщения при необходимости.

В ранее неоднократно показанном интерфейсе можно заметить кнопку Show Headers, которая активизирует действие show-headers, приводящее к выводу всех заголовков в процессе отображения сообщения. Обработка события view-message захватывает действие show-headers и при выборе этой опции выполняются те же операции, что были описаны ранее. Тем не менее, в функции retrieve_message() производится дополнительный вывод полного текста заголовков, после чего эти заголовки можно будет вывести пользователю.

Удаление почтовых сообщений

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

case 'delete' :
      {
         delete_message($_SESSION['auth_user'],
                        $_SESSION['selected_account'], $messageid);
         // имейте ввиду, что оператор 'break' опущен умышленно -
         // нужно перейти на следующий оператор case
      }
      case 'select-account' :
      case 'view-mailbox' :
      {
        // Если почтовый ящик только что выбран, то отобразить его содержимое
        display_list($_SESSION['auth_user'],
                     $_SESSION['selected_account']);
        break;
      }

Здесь вначале при помощи функции delete_message() сообщение удаляется. После чего отображается обновленное содержимое почтового ящика. Код функции delete_message():

function delete_message($auth_user, $accountid, $message_id)
{
  // удаляет одно сообщение на сервере
  
  $imap = open_mailbox($auth_user, $accountid);
  if($imap)
  {
    imap_delete($imap, $message_id);
    imap_expunge($imap);
    imap_close($imap);
    return true;
  }
  return false;
}

Здесь вызывается совокупность IMAP-функций. Из не рассмотренных ранее можно выделить imap_delete() и imap_expunge(). Функция imap_delete() помечает сообщения как удаленные, при этом фактически не удаляя их. Таким образом, можно помечать какое угодно количество сообщений, не влияя на их состояние в системе. Реальное же удаление сообщений происходит при вызове функции imap_expunge(). При этом помеченные сообщения действительно удаляются.

Выводы

В пятой части цикла, подробно рассмотрены вопросы структуры создаваемой почтовой системы с веб-интерфейсом и порядка ее функционирования. Приведены и описаны фрагменты кода главного управляющего сценария системы электронной почты с веб-интерфейсом, отвечающие за организацию описываемых компонентов системы и их взаимодействия. Рассмотрены функции вывода HTML-форм для просмотра содержимого почтового ящика пользователя, чтения почтовых сообщений, а также функции, отвечающие за удаление имеющихся сообщений из почтового ящика пользователя. Обзорно рассмотрен логический порядок работы частей сценария, показано для чего и как они функционируют, что является источником инициализации тех или иных событий в описываемой работе.

В следующей статье будет подробно изучена реализация механизма, позволяющего пользователям отправлять почту.


Ресурсы для скачивания


Похожие темы


Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=587409
ArticleTitle=Реальные веб-проекты на PHP и MySQL. Разработка почтовой службы с веб-интерфейсом: Часть 5. Просмотр содержимого почтового ящика. Чтение и удаление сообщений
publish-date=11162010