Talán sokaknak okozott már gondod a PHP kicsit fapados, viszont ennél fogva nagyon jól testre szabható mail() függvénye. Senki se szereti az ide vonatkozó RFC-ket túrni azért, hogy tudjon küldeni egy HTML levelet, vagy hogy egy képet tudjon csatolni a kiküldött levélhez.
A továbbiakban megnézzük, hogyan tudunk felépíteni egy HTML levelet, amihez egy képet csatoltunk hozzá. A dolog ott bonyolódik meg, hogy úgy szeretnénk azt a HTML levelet kiküldeni, hogy akinek az e-mail olvasója nem támogatja az ilyen leveleket az is el tudja majd olvasni. Azaz alternatívaként a levélben meg kell adnunk a sima szöveg változatot is.

--boundary_mixed ide jön majd a levél szövege --boundary_mixed ide jön majd a kép --boundary_mixed--
A "boundary_mixed" az egyedi azonosító, amivel daraboljuk a levelet. Új blokk kezdésénél két kötőjelet írunk az elválasztó elé, ha pedig le akarjuk zárni az utolsó blokkot, akkor az elválasztó elé és mögé is írunk két kötőjelet. A dolog ott bonyolódik csak meg egy picit, hogy a levél szövegét is több részre kell bontani majd, tehát egy lépéssel később a levél tartalma már így fog kinézni:
--boundary_mixed Content-Type: multipart/alternative; boundary=boundary_alt --boundary_alt a levél sima szövege --boundary_alt a levél html szövege --boundary_alt-- --boundary_mixed ide jön majd a kép --boundary_mixed--
Mint látszik, az első blokk elején megadtuk a blokk tartalmának a típusát (ezt majd a többi blokk kezdetnél is meg kell majd adnunk), amiben definiáltunk egy új elválasztó elemet. A multipart/alternative típus tulajdonsága, hogy a benne felsorolt blokkokból azt jeleníti meg, amelyiket a felhasználó e-mail olvasója támogat. Épp ezt akartuk elérni, hogy ha a kliens nem támogatja a HTML alapú leveleket, akkor a sima szöveget kapja meg. A levél tartalma így fog kinézni, miután mindenhol megadtuk a megfelelő fejléc elemeket:
--boundary_mixed Content-Type: multipart/alternative; boundary=boundary_alt --boundary_alt Content-Type: text/plain; charset=iso-8859-2 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline a levél sima szövege --boundary_alt Content-Type: text/html; charset=iso-8859-2 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline a levél html szövege --boundary_alt-- --boundary_mixed Content-Type: image/gif; name=image.gif Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=image.gif a kép base64-el elkódolva --boundary_mixed--
A multipart résztől eltekintve a Content-Type fejléc teljesen hasonlóan viselkedik, mint a HTML-es fejlécek. A Content-Transfer-Encoding határozza meg, hogy milyen formátumban van az adott szöveg abban a blokkban. Kép esetén ez egy base64-es elkódolást jelent, szöveg esetén a quoted-printable értéket használjuk, aminek az esetén a blokk az ASCII karakterkészlet nyomtatható karaktereiből álló karakterláncot fog tartalmazni. A Content-Disposition azt adja meg, hogy a blokk a levél megjelenítésekor hogyan legyen kezelve (csatolt állományként (attachment), vagy jelenjen meg az e-mailben (inline)). A levél tartalma már megvan, most már csak a levél fejlécét kell megadnunk, ami annyiban módosul, hogy ott kell definiálnunk az első elválasztó elemünket (boundary_mixed) és meg kell adnunk a MIME verzióját:
From: a levél feladója MIME-Version: 1.0 Content-type: multipart/mixed; boundary=boundary_mixed
Nincs más hátra, mint hogy ezt az egészet PHP-ben is megvalósítsuk, ami innentől már nem lesz egy bonyolult dolog:
$files = array('image/gif' => 'image.gif'); $from = 'a levél feladója'; $to = 'a levél címzettje'; $subject = 'a levél témája'; $content = 'a levél tartalma, ami HTML-t is tartalmazhat'; $bd_mixed = md5(uniqid(rand(), true)); $bd_alt = md5(uniqid(rand(), true)); $header = 'From: '.$from.' MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="'.$bd_mixed. '" '; $text = '--'.$bd_mixed. ' Content-Type: multipart/alternative; boundary="'.$bd_alt.'" --'.$bd_alt.' Content-Type: text/plain; charset=iso-8859-2 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline '.trim(strip_tags($content)).' --'.$bd_alt.' Content-Type: text/html; charset=iso-8859-2 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline '.$content.' --'.$bd_alt.'-- '; foreach ($files as $mime => $name) { $text .= '--'.$bd_mixed.' Content-Type: '.$mime.'; name="'.$name.'" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="'.$name.'" '.chunk_split(base64_encode(file_get_contents($name))).' '; } $text .= '--'.$bd_mixed.'--'; mail($to, $subject, $text, $header);
Ennyi lenne a kód, mint említettem, nem egy bonyolult dolog, a fentebb írt mail-darabolási ismeret birtokában. Talán csak a chunk_split függvény szorul némi magyarázatra: ha a szövegen kívül nem adunk meg neki más paramétert, akkor a 2045-ös RFC-nek megfelelő szemantika alapján 76 karakterenként tesz egy "\r\n"-t a szövegbe.
Erről ennyit, kellemes csatolt fájlokkal tűzdelt e-mail küldözgetést mindenkinek. :)


Üdvözletem.
Követtem az utasitásokat de nem jártam sikerrel.
Megérkezik a levél de sajnos a levélben nem jelenik meg a kép csak a körvonala, és a csatolásban sem látható.
Hírlevélhez szeretnék egy bannert küldeni, nem csatolni hanem csak megjeleniteni a képet.
Tudnának segíteni?
Ha a csatolt képet meg szeretnéd jeleníteni a HTML levélben, akkor szükség van még egy extra header-re, a Content-ID nevezetűre (a fenti kódban a foreach-en belül lévő header-ek közé kell tenni), ami valahogy így néz ki:
Content-ID: <valami@valami>Aztán a levélben pedig ahova be akarod szúrni a képet:
<img src="cid:valami@valami"/>Persze lehetőség van valamilyen tárhelyre feltöltenia képet és
<img src="http://valami/valami.gif"/>kódot használni, csak a külső hivatkozásokat az e-mail kliensek nem mindig jelenítik meg.Köszönöm a leírást.
Nekem a levél megérkezik de sajnos a csatolt állomány nem.
Ha nem adunk meg a csatolt állománynak elérési utvonalat akkor hol kell lennie
Köszönettel
Zseni Ferenc
Minden elérési út nélkül a php fájllal egy könyvtárban.
Üdvözöllek!
Had kezdjem hízelgéssel, igazán kíváló összeszedett a fenti anyag.
Tudtam is csatolt file-okat küldeni, és már nagyon elégedett kezdtem lenni, amikor is szerettem volna a html oldalban a linkelt képet megjeleníteni. Nem sikerült.
Kérdésem a kódban a / tévedés vagy szükséges.
Továbbá ha a
a csatolt file neve image.gif, és
Content-Transfer-Encoding: base64
sor után beteszem, hogy mondjuk:
Content-ID: -et
és a html-be pedig a
-t
akkor miért nem jelenik meg a kép.
Szóval már majdnem mindent értek, csak azt nem, hogy a html.ben levő kép nevének mivel kell megegyeznie, a csatolt file nevével, vagy a Cintent-ID-ben levővel, vagy ...
Valamint: a valami@valami példából az (is) kiolvasható hogy abban a @ karakternek szerepelniekell, vagy csak én bonyolítom?
És végül: az
sem működik, pedig a file ott van.
(Microsoft outlook-ot használok, és kapok olyan leveleket, amelyek html-ek és meg is jelennek a képek)
Várom szíves segítségeteket.
Tisztelettel: Nagy Miklós
A fenti hozzászólásomból eltüntek elküldés után a kódok. Hogy tudok úgy írni, hogy azt lásd amit írok?
Vagy ha kitennél néhány sort ami egy adott levélhez csatol egy képet, és azt automatikusan meg is jeleníti + a fentiismertetőddel már boldogulnék.
Előre is köszönöm.
A kód végi foreach-be kell (például) a Content-Disposition: sor alá valami olyasmi sor, hogy
Content-ID: <'.$name.'@valami>A fenti példa esetében ugye a $name az image.gif, tehát a HTML-be ezt kell írni, hogy megjelenjen a kép:
<img src="cid:image.gif@valami"/>A @ utáni rész elméletileg a küldő domainje (Mozilla Thunderbird azt írja oda, és az RFC 21111 példáiból is ez jön le: http://www.faqs.org/rfcs/rfc2111.html), tehát ha a feladó valaki@tesztemailcim.hu akkor tesztemailcim.hu.
Ha a megjelenítendő kódokban < és > helyett < és > -t írsz, akkor megjelennek rendesen. Különben a WordPress valószínűleg nem engedélyezett HTML kódnak nézi, és megeszi.
Aki szépen akarja megoldani a feladatot: PHPMailer.