Jak v PHP poslat e-mail s přílohou pomocí MIME třídy

2. listopadu 2002

Na Intervalu již vyšel článek „Jak v PHP poslat e-mail s přílohou“, při posílání přílohy se však vloží příloha s příponou .dat, což je způsobeno špatným MIME typem. Budeme zde tedy řešit posílání přílohy e-mailem jiným způsobem a to pomocí MIME třídy.

jak jsem již naznačil, budu vycházet z článku Jak v PHP poslat e-mail s přílohou. Pro pořádek jen upozornění, že veškeré zabezpečení kontroly posílaných údajů si musí udělat už každý uživatel sám.

K řešení problému budeme využívat třídy. Třída je šablonou objektu zahrnující vlastnosti a metody, které popisují objekt a pracují s ním. Následující třída mime_mail poskytuje jednoduché rozhraní k MIME.

Třída mime_mail

Třídu si uložíme jako mime_mail.inc Nalezl jsem ji už jako hotovou na internetu (nakladatelství Wrox Press).

<?
// uložit jako „mime_mail.inc“
class mime_mail
{
   var $parts;
   var $to;
   var $from;
   var $headers;
   var $subject;
   var $body;
   /*
   * void mime_mail()
   * konstruktor třídy
   */
    function mime_mail() {
      $this->parts = array();
      $this->to = „“;
      $this->from = „“;
      $this->subject = „“;
      $this->body = „“;
      $this->headers = „“;
   }
   /*
   * void add_attachment(string message, [string name], [string ctype])
   * vloží přílohu do objektu zprávy
   */

   function add_attachment($message, $name = „“, $ctype = „application/octet-stream“) {
      $this->parts[] = array (
         „ctype“ => $ctype,
         „message“ => $message,
         „encode“ => $encode,
         „name“ => $name
         );
   }
   /*
   * void build_message(array part=
   * vytvoření části vícedílné zprávy
   */

   function build_message($part) {
      $message = $part[ „message“];
      $message = chunk_split(base64_encode($message));
      $encoding = „base64“;
      return „Content-Type: „.$part[ „ctype“].
      ($part[ „name“]? „; name = \““.$part[ „name“].
      „\““ : „“).
      „\nContent-Transfer-Encoding: $encoding\n\n$message\n“;
   }
   /*
   * void build_multipart()
   * vytváří vícedílnou zprávu
   */

   function build_multipart() {
      $boundary = „b“.md5(uniqid(time()));
      $multipart =
      „Content-Type: multipart/mixed; boundary = $boundary\n\nThis is a MIME encoded message.\n\n–$boundary“;
      for($i = sizeof($this->parts)-1; $i >= 0; $i–)
      {
      $multipart .= „\n“.$this->build_message($this->parts[$i]).
      „–$boundary“;
    }
   return $multipart.= „–\n“;
   }
   /*
   * string get_mail()
   * vrací vytvořenou zprávu
   */

   function get_mail($complete = true) {
      $mime = „“;
      if (!empty($this->from))
      $mime .= „From: „.$this->from. „\n“;
      if (!empty($this->headers))
      $mime .= $this->headers. „\n“;
      if ($complete) {
       if (!empty($this->to)) {
       $mime .= „To: $this->to\n“;
      }
      if (!empty($this->subject)) {
       $mime .= „Subject: $this->subject\n“;
      }
   }
      if (!empty($this->body))
       $this->add_attachment($this->body, „“, „text/plain“);
      $mime .= „MIME-Version: 1.0\n“.$this->build_multipart();
      return $mime;
   }
   /*
   * void send()
   * odesílá zprávu(poslední funkce třídy, kterou je potřeba zavolat)
   */

   function send() {
      $mime = $this->get_mail(false);
      mail($this->to, $this->subject, „“, $mime);
   }
}; // konec třídy
?>

Formulář

Následující formulář slouží k zadání e-mailové adresy odesílatele, e-mailové adresy příjemce, ke vložení souboru jako přílohy a případně k napsání stručného textu k e-mailu. Soubor si pojmenujeme send.php:

<? if(empty($_POST[‚akce‘])):?>
<form action=“send.php“ method=“post“ enctype=“multipart/form-data“>
Odesílatel: <input type=“text“ name=“odesilatel“ value=““ size=“50″ maxlenght=“50″ />
Příjemce: <input type=“text“ name=“prijemce“ value=““ size=“50″ maxlenght=“50″ />
Předmět: <input type=“text“ name=“predmet“ value=““ size=“50″ maxlenght=“50″ />
Text: <textarea name=“dopis“ cols=“50″ rows=“10″></textarea>
Soubor: <input type=“file“ name=“soubor“ />
<input type=“submit“ name=“akce“ value=“Odeslat“ />
</form>
<? endif;

Samotný skript který slouží k poslání e-mailu

Pokračujeme zápisem v souboru send.php:

if(!empty($_POST[‚akce‘])):
   include „mime_mail.inc“;
   // načtení třídy mime_mail

   $newFile=“upload/“.$_FILES[‚soubor‘][‚name‘];
   // cesta k souboru
   move_uploaded_fileCopy($_FILES[‚soubor‘][‚tmp_name‘], „$newFile“);
   // nahraný soubor zkopírujeme z dočasného adresáře
   if(File_Exists($newFile)):
   // kontrola, zda existuje soubor
      $fd=FOpen($newFile, „r“);
      // otevření souboru pro čtení
      $data=FRead($fd, FileSize($newFile));
      // binární čtení dat
      FClose($fd);
      // zavření souboru
      $mail=new mime_mail;
      // vytvoření instance objektu
      $mail->from = $_POST[‚odesilatel‘];
      // nastavení údajů
      $mail->to = $_POST[‚prijemce‘];
      $mail->subject = $_POST[‚predmet‘];
      $mail->body = $_POST[‚dopis‘];
      $mail->add_attachment($data, $_FILES[‚soubor‘][‚name‘], $_FILES[‚soubor‘][‚type‘]);
      
      $mail->send();
      // odeslání e-mailu
      echo „Odesláno“;
      // potvrzení o odeslání
   else:
      echo „Chyba“;
      // pokud soubor neexistuje
   endif;
   unlink($newFile);
   // smazani dočasného souboru
endif;
?>

Adresářová struktura

V našem projektu nakonec vytvoříme podadresář upload, do kterého budeme dočasně ukládat posílané soubory. Skript je tedy hotov a nezbývá nic jiného, než jej otestovat, případně přidat kontrolní mechanismy vkládaných dat.

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

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

Předchozí článek Reklama, webdesign a inspirace 5.
Další článek WML v malíčku - časovače
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

5 komentářů

  1. Aleš Novotný

    Říj 16, 2009 v 13:53

    Zdravím.
    Nevím jestli na příspěvky zde někdo reaguje, nicméně za pokus to stojí:
    Díky moc za článek i vzorový příklad – povedlo se mi to rozběhnout.
    Ale nefunguje čeština v těle mailu – jen š a ž se neposílá správně.
    Kde dělám chybu?
    Díky Aleš

    Odpovědět
  2. Freeze

    Říj 16, 2009 v 23:38

    @Aleš Novotný:
    Chyba bude zřejmě v kódování. Windows-1250 a latin2 se od sebe liší (z používaných znaků) právě v š, ž.
    Teoreticky by mělo stačit přidat korektní hlavičku charset. Ale některé e-mailové klienty neberou win1250 kódování, takže doporučím spíš latin2 nebo to rovnou přepsat do utf-8 ;)

    Jinak zřejmě na příspěvky ani nikdo nereaguje. Přecejenom se jedná o články již pár let staré. Já jsem narazil náhodou.

    Odpovědět
  3. Marek

    Úno 10, 2010 v 19:36

    Hlásilo mi chybu na riadku (volá nedefinovanú funkciu): move_uploaded_fileCopy ($_FILES[‚soubor‘][‚tmp_name‘], „$newFile“);

    vyriešil som ju tak ze som riadok zmenil na:
    move_uploaded_file ($_FILES[‚soubor‘][‚tmp_name‘], „$newFile“);

    tak to funguje :-)

    Odpovědět
  4. Honza M.

    Říj 2, 2011 v 11:33

    @Freeze:
    Také mi nastal problém s kodováním, většinu koduju v utf-8, tedy respektivě vše na stránkách, pokud používám klasický vlastní kod na odesílání mailu bez přílohy, tak je vše OK, tam mám dopsané správné kodování, případně předělání an něj, ale zde v tomto kodu i přes několikahodinové snažení se mi nepodařilo ho upravit tak, aby proměnnou dopis bral v pohodě, tedy aby ji vypsal v mailu správně s diakritikou – tedy ve správném kodování. neporadí mi někdo, co zde změnit? Buď se mi znaky vypisují pomocí symbolů nebo jsou projistotu rovnou vynechané.

    Odpovědět
  5. petr

    Pro 10, 2013 v 0:27

    Zdravím, mohl by mi někdo prosím poradit jak tento příklad předělat tak, aby odesílal více jak jednu přílohu? Předem děkuji.

    Odpovědět

Napsat komentář: Aleš Novotný Zrušit odpověď na komentář

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