Zpracování přílohy emailu v PHP přes IMAP

Petr Wiedemann, 26. prosinec 2009

Následující krátký kód používám pro strojové zpracování příloh z emailu. Tento kód si neklade za cíl být univerzální. V mém případě zpracovává zprávy, které mají vždy stejnou strukturu.

Zprávy, ve kterých hledám informace nejprve třídí mailserver podle pravidel. V mém případě do podložky složky INBOX.

<?php

// Pripojeni k IMAP serveru.
$mbox = imap_open('{localhost:143/notls}INBOX/Data', 'username', 'password');
if ($mbox === false)
{
  echo imap_last_error();
  die();
}

// Vyhledani vsech nesmazanych zprav v otevrene slozce.
$mfound = imap_search($mbox, 'ALL UNDELETED', SE_UID);
if ($mfound === FALSE)
{
  echo 'Zadne nesmazane zpravy ve slozce <strong>INBOX/Data</strong>.';
}
else
{
  // Mame k dispozici pole s ID zprav. Pro kazdou nacteme jeji strukturu.
  foreach ($mfound as $msg_id)
  {
    $msg_struct = imap_fetchstructure($mbox, $msg_id, FT_UID);

    // Zajimaji nas pouze zpravy, ktere maji 2 a vice casti.
    // Tyto zpravy mohou obsahovat prilohy.
    if (isset($msg_struct->parts) && count($msg_struct->parts) >= 2)
    {
      // Vyhledani priloh v kazde casti zpravy.
      for ($part_no = 0; $part_no < count($msg_struct->parts); $part_no++)
      {
        // Kontrola, jestli tato cast zpravy obsahuje parametry pro dalsi hledani.
        if ($msg_struct->parts[$part_no]->ifdparameters)
        {
          // Prohledani parametru. Zajima nas atribut s nazvem 'filename'.
          foreach ($msg_struct->parts[$part_no]->dparameters as $part_param)
          {
            // Tato cast obsahuje informaci o jmenu souboru v priloze.
            if (mb_strtolower($part_param->attribute, 'utf-8') == 'filename')
            {
              // Kontrola, jestli ma soubor pozadovanou priponu.
              if (pathinfo($part_param->value, PATHINFO_EXTENSION) == 'zpt')
              {
                // Nacteni obsahu casti mailu.
                $part_content = imap_fetchbody($mbox, $msg_id, $part_no + 1, FT_UID);

                // Dekodovani obsahu pokud je v BASE64 nebo jako QUOTED-PRINTABLE
                switch ($msg_struct->parts[$part_no]->encoding)
                {
                  case 3:
                    $part_content = base64_decode($part_content);
                    break;
                  case 4:
                    $part_content = quoted_printable_decode($part_content);
                    break;
                }

                // V promenne $part_content je obsah souboru v priloze.
                // Na tomto miste by melo byt volani funkce pro zpracovani dat.
              }
            }
          }
        }
      }
    }
    // Oznaceni zpravy ke smazani
    imap_setflag_full($mbox, $msg_id, '\\Deleted', ST_UID);
  }
}

imap_close($mbox);
?>

Po spuštění skript vyhledá ve složce všechny zprávy, které nejsou označeny ke smazání. U každé nalezené zprávy načte její strukturu. V případě, že zpráva obsahuje 2 nebo více částí, pokračuje v prohledání všech částí. Tento skript hledá data pouze v poli dparameters. Pokud nalezne parametr filename, načte jeho hodnotu, kterou je název souboru v příloze. V případě, že se jedná o hledaný typ souboru, načte obsah této části zprávy, kterou následně dekóduje, pokud je ve zprávě uložena jako BASE64 nebo QUOTED-PRINTABLE. Tento obsah následně předá třídě, která data dále zpracuje. Poslední věcí, kterou skript se zprávami provede, je jejich označení ke smazání.