Email s diakritikou a přílohou v PHP - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



PHP

Email s diakritikou a přílohou v PHP

php

6. ledna 2003, 00.00 | Funkce API mail() je velmi užitečná. Autoři ji ale nevybavili některými potřebnými vlastnostmi, jako např. možností zasílat přílohy. V tomto článku si ukážeme jak na to. Součástí je samozřejmě i funkční skript.

Funkce API mail() je velmi užitečná. Autoři ji ale nevybavili některými potřebnými vlastnostmi, jako např. možností zasílat přílohy. Zde je návod jak na to.
Nejprve si musíme o emailu něco málo říct. Email se skládá z hlaviček a vlastního těla emailu. Hlavičky jsou normou RFC definované informace, ktaré určují jak email vlastně vypadá, jak je kódován a další užitečné informace. Informace v hlavičce mají formát:

Nazev hlavicky: hodnota

Na každém řádku je vždy jedna hlavička. Po hlavičkách následuje jeden prázdný řádek a pak vlastní tělo emailu. O tom se toho už tolik říct nedá, protože většinu obstarávají právě hlavičky.


Hlavičky, které budeme používat

From: - odesílatel. Jako odesílatele můžete někdy narazit i na tohle: "Petr Macek" <> Pro uživatele je vhodnější, když vidí jméno člověka, emailový klient používá to co je uvedeno v ostrých závorkách, zbytek ignoruje

MIME-version: 1.0 - určuje, jakou verzi mime mail používá. Zatím existuje jen tato. Mime nám říká typ souboru (např: jpg => image/jpeg, txt => text/plain), podle něj potom emailový program s přílohou pracuje.

X-Mailer: PHP - hlavičky začínající x nejsou pro funkci důležité. Většinou nesou informace o použitém mailovacím programu a další. Nejsou nutné

Subject: text - subject, nadpis zprávy

Return-Path: <> - kvůvi chybám

Reply-To: - z této hlavičky se bere, na kterou adresu se odpoví (většinou se rovná hlavičce from)

Content-Type: multipart/mixed; boundary="$boundary"
Content-Type: text/plain; charset="windows-1250"
- určuje mime typ zprávy, přílohy a další informace (znaková sada, boundary)

Content-Transfer-Encoding: quoted-printable - nese informaci o kódování (base64 nebo quoted-printable)

Content-Disposition: attachment; filename="neco.txt" - nese informace o příloze


Znakové sady
V tomto příkladu jsem použil windows 1250. Ti, kdo pracují na linuxu budou patrně používat latin2. V tom případě si nastavte správně hlavičku Content-Type (Content-Type: text/plain; charset="iso-8859-2").


Kódování emailů
V PHP máme dva způsoby kódování:
Base64 - kóduje trojici bajtů do čtyřbajtového kódu. Výsledek je pro člověka naprosto nečitelný. Tímto kódováním budeme kódovat přílohy (je to výhodnější, ale je možné s ním kódovat i běžný text)
Quoted-printable - znaky, které v ascii leží výš než 127 nahradí kombinací =xx, kde xx je hexa hodnota daného znaku. Většina textu je i po zakódování čitelná. Na kódování příloh nepoužívat. Asi by to nedopadlo dobře :-)

Zde se můžete podívat, jak takový zakódovaný text vypadá:
<?
$text = "Smál se, až se za břicho popadal.";
echo "8bit: " . imap_8bit($text);            // zobrazí Sm=E1l se, a=9E se za b=F8icho popadal.
echo "base64: " . base64_encode ($text);     // zobrazí U23hbCBzZSwgYZ4gc2UgemEgYvhpY2hvIHBvcGFkYWwu
?>



Struktura mailu s přílohou
UVOD
tady je informace, že se jedná o mail s více částmi a je zde definována boundary (hranice, která se používá k oddělení jednotlivých částí emailu)
--BOUNDARY
první část emailu, nejprve jsou samozřejmě hlavičky určující, jak je část emailu kódovaná, jakou používá znakovou sadu a další. Pak následuje prázný řádek a po něm obsah této části
--BOUNDARY
další část emailu, je tvořena stejně jako předchozí. Částí může být více. Vždy jsou oddělené pomocí boundary . . .
--BOUDARY--


PHP

<?
function extra_mail ($to,$from,$subj,$body,$attach = "",$real_name = "") {

// možná vám není jasný zápis v hlavičce funkce $real_name = ""
// dělá následující: pokud parametr real_name nezadáme, doplní
// to co je za rovnítkem. Vyhneme se tak problému se zadáváním nesprávného
// počtu parametrů

$header = "From: $from\n";
$header .= "MIME-version: 1.0\n";
$header .= "X-Mailer: PHP\n";
$header .= "Return-Path: <$from>\n";
$header .= "Reply-To: $from\n";

if ( !empty($attach) ) { // když máme nějakou přílohu

// mime.php obsahuje funkci na zjištění MIME podle přípony souboru
// include "mime.php";

// když nezadáme $real_name, bude se příloha jmenovat stejně jako je
// název, který vchází do funkce. To nemusí být vhodné například,
// pokud fci voláme přímo po uploadu souboru (php uploadovaný soubor
// ukládá do definovaného adresáře pod nahodně generovaným názvem
// nebo v případě, že v proměnné $attach je jméno souboru i s cestou

if ( empty($real_name) ) {
$real_name = $attach;
}

// zjištění mime typu vznikající přílohy
$type = dej_mime ($real_name);

// načteme přílohu
$f = fopen ($attach,"r");
if (!$f) {
exit ("Nelze otevrit prilohu - koncime");
}

$attach_obsah = fread ($f,filesize ($attach));

// překódujeme obsah přílohy do base64, je vhodné použít i fci chunk
$attach_obsah = chunk_split (base64_encode ($attach_obsah));

fclose ($f);

// připravíme hlavičky (příloha bude přímo v nich)!!!

// vygenerování boundary (hranice), musí to být řetězec, který se nebude
// vyskytovat nikde v textu. Dále vytvoříme úvod mailu, v kterém
// určujeme, že mail má více částí vzájemně oddělených pomocí boundary

$boundary = strtoupper(md5(uniqid("bound_")));
$header .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n\n";
$header .= "This is a multi-part message in MIME format.\n\n";

// hranicí oddělíme úvod
$header .= "--" . $boundary . "\n";

// první část mailu obsahuje běžné tělo mailu, zakódované
$header .= "Content-Type: text/plain; charset=\"windows-1250\"\n";
$header .= "Content-Transfer-Encoding: quoted-printable\n\n";
$header .= imap_8bit($body) . "\n\n";

// hranicí určíme, že následuje další část emailu
$header .= "--" . $boundary . "\n";

// dalsi cast mailu - přidáme hlavičky na kódování, mime a přílohu
$header .= "Content-Type: " . $type . "\n";
$header .= "Content-Transfer-Encoding: base64\n";
$header .= "Content-Disposition: attachment; filename=\"$real_name\"\n\n";
$header .= $attach_obsah . "\n\n";

// hranicí ukončíme mail (na konci ještě musí být --)
$header .= "--" . $boundary . "--";
}
else { // email bez přílohy. Pouze zakódujeme a přidáme příslušnou hlavičku
$header .= "Content-Type: text/plain; charset=\"windows-1250\"\n";
$header .= "Content-Transfer-Encoding: quoted-printable\n\n";
$header .= imap_8bit($body) . "\n\n";
}

// a vygenerované pošleme
return (mail ($to,$subj,"",$header));

}

?>


K tomuto kódu ještě patří soubor mime.php (podle přípony souboru vrátí MIME typ. U uploadovaných souborů ji může vracet přímo php). Mírně jsem ho osekal, ale měl by postačit pro běžné přílohy:
<?

function dej_mime ($jmeno_souboru) {

$pozice = strrpos($jmeno_souboru,'.');
$typ = substr( $jmeno_souboru, $pozice + 1 , strlen($jmeno_souboru) - $pozice);

$mimetypes = array(
'doc' => 'application/msword',
'bin' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'pdf' => 'application/pdf',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'swf' => 'application/x-shockwave-flash',
'tar' => 'application/x-tar',
'zip' => 'application/zip',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'm3u' => 'audio/x-mpegurl',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'ief' => 'image/ief',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'png' => 'image/png',
'tiff' => 'image/tiff',
'tif' => 'image/tiff',
'xbm' => 'image/x-xbitmap',
'wrl' => 'model/vrml',
'vrml' => 'model/vrml',
'css' => 'text/css',
'html' => 'text/html',
'htm' => 'text/html',
'asc' => 'text/plain',
'txt' => 'text/plain',
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'sgml' => 'text/sgml',
'sgm' => 'text/sgml',
'xml' => 'text/xml',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
'avi' => 'video/x-msvideo',
'rar' => 'application/rar',
);

return ( $mimetypes[$typ]);
}
?>


Způsoby volání funkce extra_mail
Funkci je možné volat když máte přílohu uloženou na disku nebo i v případě, že byla právě nauploadována z formuláře.

Pokud skript voláte hned po upoladu doporučuji použít i $new_name, jinak se v mailu bude příloha v emailu bude jmenovat např. c:\winnt\tmp\aoi332kl.
extra_mail ($to,$from,$subj,$body,$attach,$new_name);

Pokud máte přílohu ve stejném adresáři, voláme:
extra_mail ($to,$from,$subj,$body,"soubor.txt",null);
nebo
extra_mail ($to,$from,$subj,$body,"soubor.txt","novysoubor.txt");
(v prvním případě se bude příloha v mailu jmenovat jako soubor na disku.)

Když máte přílohu v jiném adresáři, volejte takhle:
extra_mail ($to,$from,$subj,$body,"../data/soubor.txt","novysoubor.txt");
(platí to samé jako u uploadu, zadejte i nové jméno, jinak se příloha bude jmenovat ../data/soubor.txt.)

Důležitá poznámka
Testoval jsem skript na 7 strojích. Bohužel na 3 PC s os Win 2000, Win NT (každý měl jiný SMTP server) se mi nedařilo odmailovat přílohu větší než 2KB. Chyba je někde v komunikaci se SMTP serverem. Na ostatních strojích (linux) je situace o dost lepší, během chvilky odmailujete cokoli.

Tématické zařazení:

 » Rubriky  » PHP  

 » Rubriky  » Web  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: