E-mailový klient pre webmail v PHP – odosielanie, čítanie a sťahovanie

12. března 2004

V tomto článku o tvorbe webmailu si ukážeme ďalšie stránky a funkcie, ktoré webmail ponúka, napríklad funkcie na odosielanie a čítanie e-mailov a na sťahovanie príloh.

V tomto článku nám pribudnú nasledovné súbory:

  • send.php – súbor pre odosielanie mailu
  • read.php – súbor pre čítanie mailu
  • download.php – súbor umožňujúci sťahovanie príloh

Čítanie správ (read.php)

Prvá funkcia, ktorú si ukážeme, bude funkcia read_message() na čítanie prijatej pošty:

function read_message($id)
{
  global $userid;
  $imap = open();
  if(!$imap) return false;
  $header = imap_header($imap, $id);
  $from = $header->from[0];
  $adresa = $from->mailbox.“@“.$from->host;
  $odosielatel = $from->personal;
  // adresa odosielateľa
  if(!empty($odosielatel) && $odosielatel != $adresa) $from_address = „$odosielatel < $adresa >“;
  else $from_address = $adresa;
  $subject = imap_mime_header_decode($header->Subject);
  $subject = $subject[0]->text;
  $from = imap_mime_header_decode($header->fromaddress);
  $from = $from[0]->text;
  $from_address = $from.“ &lt;“.$adresa.“&gt;“;
  $message[‚udate‘] = $header->udate; // dátum a čas
  $message[‚header‘] = imap_fetchheader($imap, $id);
  $message[‚toaddress‘] = $header->toaddress;
  $message[‚ccaddress‘] = $header->ccaddress;
  $message[‚udate‘] = $header->udate;
  $structure = imap_fetchstructure($imap, $id);
  $encoding = $structure->encoding;
  $parts = $structure->parts;
  $num_parts = sizeof($parts); // kolko má správa častí
  // zobrazíme správu
  ?>
  <table cellpadding=“0″ cellspacing=“0″ border=“0″ width=“100%“>
  <tr>
    <td width=“10%“><div class=“middle“ align=“left“>Odosielateľ:</div></td>
    <td width=“25%“><div class=“middle“ align=“left“><?php echo $from_address?></div></td>
  <td></td>
  </tr>
  <tr>
    <td><div class=“middle“ align=“left“>Príjmateľ:</div></td>
    <td><div class=“middle“ align=“left“><?php echo $message[‚toaddress‘]?></div></td>
  <td></td>
  </tr>
  <tr>
    <td><div class=“middle“ align=“left“>Kópia:</div></td>
    <td><div class=“middle“ align=“left“><?php echo $message[‚ccaddress‘]?></div></td>
  <td></td>
  </tr>
  <tr>
    <td><div class=“middle“ align=“left“>Predmet:</div></td>
    <td><div class=“middle“ align=“left“><?php echo $subject?></div></td>
  <td></td>
  </tr>
  <tr>
    <td><div class=“middle“ align=“left“>Dátum:</div></td>
    <td><div class=“middle“ align=“left“><?php echo date(„j.n.Y H:i“,$message[‚udate‘])?></div></td>
  <td></td>
  </tr>
  <?php
  if($num_parts>0):
    echo „<tr><td valign=’top‘><div class=’middle‘ align=’left‘>Časti správy:</div></td>“;
    echo „<td valign=’top‘><div class=’middle‘ align=’left‘>“;
    for($i=1;$i<$num_parts;$i++):
      $info = get_info($parts[$i]);
      $name = $info[‚name‘];
      $mime = $info[‚mime‘];
      $transfer = $info[‚transfer‘];
      $size = $info[‚size‘];
      echo „<a href=’download.php?id=$id&part=“.($i+1).“&mime=$mime&filename=$name&transfer=$transfer‘>“;
      echo $name.“</a> „.$mime.“ „.$size.“ kB“;
      echo „<br />“;
    endfor;
    echo „</div></td>“;
  endif;
  ?>
  <tr>
    <td height=“35″ valign=“middle“ colspan=“3″><div align=“center“ class=“middle“>
    <a href=“reply.php?id=<?php echo $id?>“>Odpovedať</a> ·
    <a href=“forward.php?id=<?php echo $id?>“>Preposlať</a> ·
    <a href=“delete.php?id=<?php echo $id?>“>Vymazať</a>
    </div></td>
  </tr>
  <tr><td height=“15″></td></tr>
  <tr><td colspan=“3″>
    <div class=“text“>
    <?php
    if($encoding==0) echo nl2br(imap_qprint(imap_fetchbody($imap,$id,1)));
    else echo nl2br(imap_fetchbody($imap,$id,1));
    ?>
    </div>
  </td></tr>
  </table>
  <?php
  imap_close($imap);
}

Táto funkcia zobrazuje prijatú správu. Identifikuje ju na základe premennej $id, prijatej cez URL. Nájdeme tu IMAP funkcie:

  • array imap_headers(int spojenie); – vracia hlavičky všetkých správ v e-mailovej schránke
  • object imap_header(int spojenie, int číslo_správy, int dĺžka_from, int dĺžka_subject, string defaultná_doména); – prečíta hlavičku správy
  • array imap_mime_header_decode(string text); – dekóduje prvky MIME hlavičky
  • string imap_fetchheader(int spojenie, int číslo_správy, int možnosti); – prečíta celú hlavičku správy a vracia v neupravenej podobe
  • object imap_fetchstructure(int spojenie, int číslo_správy, int možnosti); – zistí štruktúru správy
  • string imap_qprint(string text); – dekóduje text zakódovaný metódou quoted-printable
  • string imap_fetchbody(int spojenie, int číslo_správy, string časť, int možnosti); – prečítanie jednej časti tela správy
  • int sizeof(mixed premenná); – táto funkcia slúži na zistenie počtu prvkov v premennej (netýka sa priamo IMAP funkcií, ale v škripte je použitá)

V škripte je spomenutá aj zatiaľ vám neznáma funkcia get_info(), ktorá podáva informácie o jednotlivých častiach správy. Vyzerá nasledovne:

function get_info($part)
{
  $name = „[unknown]“;
  // popis časti
  if($part->ifdescription == true) $description = $part->description;
  // meno
  for($i=0;$i<count($part->parameters);$i++)
  {
    $parameter = $part->parameters[$i];
    if((($parameter->attribute==“name“) || ($parameter->attribute==“NAME“)) && ($parameter->value!=““))
    {
      $name = $parameter->value;
      break;
    }
  }
  // typ
  if(isset($part->type)):
    switch($part->type)
    {
      case 0:
      $type = „text“;
      break;
      case 1:
      $type = „multipart“;
      break;
      case 2:
      $type = „message“;
      break;
      case 3:
      $type = „application“;
      break;
      case 4:
      $type = „audio“;
      break;
      case 5:
      $type = „image“;
      break;
      case 6:
      $type = „video“;
      break;
      case 7:
      $type = „other“;
        break;
      default:
      $type = „unknown“;
      break;
    }
  endif;
  // mime
  $mime = $type.“/“.$part->subtype;
  // kódovanie
  if(isset($part->encoding)):
    switch($part->encoding)
    {
      case 0:
      $encoding = „7BIT“;
      break;
      case 1:
      $encoding = „8BIT“;
      break;
      case 2:
      $encoding = „BINARY“;
      break;
      case 3:
      $encoding = „BASE64“;
      break;
      case 4:
      $encoding = „QUOTED-PRINTABLE“;
      break;
      case 5:
      $encoding = „OTHER“;
      break;
      default:
      $encoding = „none“;
      break;
    }
  else:
    $encoding = ‚7BIT‘;
  endif;
  // veľkosť
  $size = $part->bytes;
  if($size>1000) $size = ceil($size/1000);
  else $size = 1;
  // spolu
  $info = array
  (
  ‚name‘ => $name,
  ‚mime‘ => $mime,
  ‚transfer‘ =>$encoding,
  ‚size‘ =>$size,
  );
  return $info;
}

Tieto informácie sa použijú pri sťahovaní príloh v mailoch. Informácie ako meno, MIME, kódovanie alebo veľkosť vracia funkcia v poly $info. Funkcia read_message(); sa bude nachádzať v súbore read.php.

<?php
  session_start();
  require „./functions.php“;
  html_header();
  read_message($_GET[‚id‘]);
  html_footer();
?>

Odosielanie správ (send.php)

Ďalšia funkcia send(); nám poslúži na odosielanie e-mailov:

function send($form)
{
  global $userid;
  db_connect();
  // zistíme, či adresa nebola vyberaná z adresára
  if($form[‚to2‘]!=“false“) $form[‚to‘] = $form[‚to2‘];
  $name = name(); // vaše meno
  $address = address(); // vaša e-mailová adresa
  $to_name = $form[‚to‘]; // odosielateľove meno (alebo adresa)
  $text = strip_tags($form[‚message‘]); // text, odstránime html tagy
  $html = $form[‚message‘]; // html
  $outer_boundary = „—-=_“.md5(000).“_000″;
  $inner_boundary = „—-=_“.md5(001).“_001″;
  // hlavičky správys
  $headers = „MIME-Version: 1.0\r\n“;
  $headers .= „From: „.$name.“ <„.$address.“>\n“;
  $headers .= „To: „.$to_name.“ <„.$form[‚to‘].“>\n“;
  $headers .= „Reply-To: „.$name.“ <„.$address.“>\n“;
  $headers .= „X-Priority: 2\n“;
  $headers .= „X-MSMail-Priority: Normal\n“;
  $headers .= „X-Mailer: PHP/“.phpversion().“\n“;
  $headers .= „Content-Type: multipart/mixed;\n\tboundary=\““.$outer_boundary.“\“\n“;
  // obsah správy
  $message = „This is a multi-part message in MIME format.\n“;
  $message .= „\n–„.$outer_boundary.“\n“;
  $message .= „Content-Type: multipart/alternative;\n\tboundary=\““.$inner_boundary.“\“\n\n“;
  // text
  $message .= „\n–„.$inner_boundary.“\n“;
  $message .= „Content-Type: text/plain;\n\tcharset=\“iso-8859-1\“\n“;
  $message .= „Content-Transfer-Encoding: quoted-printable\n\n“;
  $message .= $text.“\n\n“;
  // html
  $message .= „\n–„.$inner_boundary.“\n“;
  $message .= „Content-Type: text/html;\n\tcharset=\“iso-8859-1\“\n“;
  $message .= „Content-Transfer-Encoding: base64\n\n“;
  $message .= chunk_split(base64_encode($html)).“\n\n“;
  $message .= „\n–„.$inner_boundary.“–\n“;
  // príloha číslo 1
  if(!empty($_FILES[‚priloha1‘][‚name‘]))
  {
    $file = $_FILES[‚priloha1‘][‚name‘];
    $message .= „\n–„.$outer_boundary.“\n“;
    $message .= „Content-Type: „.$_FILES[‚priloha1‘][‚type‘].“;\n\tname=\““.$file.“\“\n“;
    $message .= „Content-Transfer-Encoding: base64\n“;
    $message .= „Content-Disposition: attachment;\n\tfilename=\““.$file.“\“\n\n“;
    $file1 = $_FILES[‚priloha1‘][‚tmp_name‘];
    $fp = fopen($file1,“r“);
    $content = fread($fp,filesize($file1));
    fclose($fp);
    $content = chunk_split(base64_encode($content));
    $message .= $content;
    $message .= „\n\n“;
  }
  // príloha číslo 2
  if(!empty($_FILES[‚priloha2‘][‚name‘]))
  {
    $file = $_FILES[‚priloha2‘][‚name‘];
    $message .= „\n–„.$outer_boundary.“\n“;
    $message .= „Content-Type: „.$_FILES[‚priloha2‘][‚type‘].“;\n\tname=\““.$file.“\“\n“;
    $message .= „Content-Transfer-Encoding: base64\n“;
    $message .= „Content-Disposition: attachment;\n\tfilename=\““.$file.“\“\n\n“;
    $file1 = $_FILES[‚priloha2‘][‚tmp_name‘];
    $fp = fopen($file1,“r“);
    $content = fread($fp,filesize($file1));
    fclose($fp);
    $content = chunk_split(base64_encode($content));
    $message .= $content;
    $message .= „\n\n“;
  }
  // príloha číslo 3
  if(!empty($_FILES[‚priloha3‘][‚name‘]))
  {
    $file = $_FILES[‚priloha3‘][‚name‘];
    $message .= „\n–„.$outer_boundary.“\n“;
    $message .= „Content-Type: „.$_FILES[‚priloha3‘][‚type‘].“;\n\tname=\““.$file.“\“\n“;
    $message .= „Content-Transfer-Encoding: base64\n“;
    $message .= „Content-Disposition: attachment;\n\tfilename=\““.$file.“\“\n\n“;
    $file1 = $_FILES[‚priloha3‘][‚tmp_name‘];
    $fp = fopen($file1,“r“);
    $content = fread($fp,filesize($file1));
    fclose($fp);
    $content = chunk_split(base64_encode($content));
    $message .= $content;
    $message .= „\n\n“;
  }
  $message .= „\n–„.$outer_boundary.“–\n“;
  // e-mail odošleme
  if(mail($form[‚to‘],$form[‚subject‘],$message,$headers)) echo „<div class=’middle‘ align=’center‘>Správa bola úspešne odoslaná.</div>“;
  else echo „<div class=’warning‘ align=’center‘>Správu sa neporadilo odoslať.</div>“;
  // odoslanú správu uložíme do databázi
  $time = time();
  $from = address();
  $query = „insert into sent values(“,’$userid‘,’$form[to]‘,’$form[subject]‘,’$form[message]‘,’$time‘)“;
  $result = mysql_query($query);
  if(!$result) echo „<div class=’warning‘ align=’center‘>Správu sa neporadilo uložiť do odoslanej pošty.</div>“;
}

Táto funkcia nám slúži na odosielanie mailov. Dáta preberá z predchádzajúceho súboru (new.php) – adresu prijímateľa (prijímateľov), predmet, prílohy a samozrejme samotný text. Tieto premenné sú posielané metódou POST a preberané funkciou send(). Táto funkcia neobsahuje žiadne IMAP premenné. Funkcie name() a address() si ukážeme až v budúcom článku. Sú krátke a vracajú vaše meno a vašu e-mailovú adresu z databáze. V premennej $header zhromažďujeme hlavičky správy. V premennej $message zasa samotnú správu. Tieto premenné potom predávame funkcií mail() ktorá e-mail odosiela.

Funkcia send(); sa nachádza v súbore send.php.

<?php
  session_start();
  require „./functions.php“;
  html_header();
  send($_POST);
  html_footer();
?>

Sťahovanie príloh (download.php)

Posledný súbor, ktorý si v tomto článku ukážeme, umožňuje sťahovanie príloh:

<?php
  session_start();
  require „./functions.php“;
  header(‚Content-Type: application/x-unknown-‚.$mime);
  if (eregi(‚MSIE‘, $HTTP_USER_AGENT) && eregi(‚5.5‘, $HTTP_USER_AGENT)) header(‚Content-Disposition: filename=‘ . urldecode($filename));
  else header(‚Content-Disposition: attachment; filename=‘ . urldecode($filename));
  $imap = open();
  $file = imap_fetchbody($imap, $id, $part);
  imap_close($imap);
  if ($transfer == ‚BASE64‘) $file = imap_base64($file);
  elseif($transfer == ‚QUOTED-PRINTABLE‘) $file = imap_qprint($file);
  header(‚Content-Length:‘.strlen($file));
  echo $file;
?>

Súbory prijaté v mailoch stiahneme pomocou tohto kódu uloženom v download.php. Ten príjme premenné metódou GET a zobrazí alebo ponúkne na stiahnutie výsledný súbor vďaka funkcii header().

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

2 komentářů

  1. Snacker

    Čvc 4, 2009 v 20:41

    Zdravim,
    RObil som podla vas mailoveho klienta, nomam problem ak do prilohy vkladam typ suboru word(2007) alebo powerpoint(2007).Ukaze sa mi chyba: Fatal error: Cannot use object of type stdClass as array in

    Ak by ste mi vedeli poradit budem vdacny.

    Dakujem

    Odpovědět
  2. Honza

    Led 18, 2011 v 8:40

    Ahoj. tvůj webmail se mi velice líbí a už v něm vychytávám nějaké drobnosti, ale mám jeden zásadní problém. Nemaže mi to žádné zprávy, i když je označím, tak mi to napíše, že nebyli vybrané žádné zprávy pro vymazání. A pokud chci zobrazit odeslané zprávy, tak mi to napíše, že žádné zprávy nebyli nalezené. pomůže mi někdo prosím???

    Odpovědět

Napsat komentář: Snacker Zrušit odpověď na komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *