ugrás a tartalomhoz

Levélküldés PHP-ben

Bártházi András · 2004. Május. 14. (P), 21.00
Levélküldés PHP-ben
Sokszor felmerül a PHP levelezőlistán, hogy valaki szeretne PHP segítségével HTML levelet, csatolmányokat, HTML levélben képeket küldeni. Cikkemben először a mail() függvény alapjait veszem sorra. Kiderül, hogy néhány fontos paraméter beállítására is lehetőségünk van segítségével, ráadásul akár HTML levelet is igen egyszerűen küldhetünk a segítségével - ha nem gondolunk a szöveges alternatívát igénylő olvasókra. Persze ha többet szeretnénk, akkor jobban tesszük, ha nem találjuk fel a kereket, és a rengeteg lehetőség közül egy olyan kész megoldást választunk, mellyel még több is könnyedén megoldható.

Amit a PHP mail() tud

A PHP beépített mail() függvénye segítségével, ha nem szeretnénk sokat bűvészkedni, akkor egy egyszerű szöveges, vagy pedig egy egyszerű HTML levelet tudunk küldeni. Lehetőségünk van UNIX/Linux környezetben a helyi sendmail paranccsal, Windows alatt pedig SMTP szerver segítségével elküldenünk a levelet.

A parancs formátuma a következő:

<?
mail("címzett##kukac##domain.hu",
     "a levél tárgya",
     "magának a levélnek\naz egyes sorai.");
?>
A parancs ezen kívül lehetőséget nyújt a levelek fejlécének a manipulálására is, ezt a következő formában tudjuk elérni:

<?
mail("címzett##kukac##domain.hu",
     "a levél tárgya",
     "magának a levélnek\naz egyes sorai.",
     "From: feladó##kukac##domain.hu\r\n".
     "Reply-to: válaszoló##kukac##domain.hu");
?>
Fontos, hogy a fejléchez hozzávenni kívánt sorokat "\r\n" sortörésekkel válasszuk el a szabvány szerint!

Nézzünk egy példát HTML levél küldésére is:

<?
mail("címzett##kukac##domain.hu",
     "a levél tárgya",
     "<html><head><title>Cím</title></head><body>A levél
      tartalma</body></html>",
     "MIME-Version: 1.0\r\n"."Content-type: text/html; 
      charset=iso-8859-2\r\n");
?>
Mint látható, egy olyan levélfejlécet adtunk meg, ami azt mondja meg, hogy a levél tartalma HTML formátumú (és mellesleg iso-8859-2-es, azaz közép-európai kódolású).

A mail() függvény tud még pár apróságot, sőt, ha kedvünk van, használhatjuk komplexebb levelek küldésére is, mi azonban egy olyan osztályt fogunk most bemutatni, mely segít nekünk ebben, sokkal egyszerűbbé téve a dolgunkat. Hozzá kell tenni, hogy a bemutatott osztály is magát a mail() függvényt használja levélküldésre...

A mail() függvényről további információkat, továbbá az SMTP levélküldési lehetőségekről és azok beállításáról a PHP dokumentációban (a mail() függvénynél) olvashatunk részletesebben. Windows felhasználóknak röviden: a php.ini-ben az SMTP paraméterrel vagy programunkban az ini_set() paranccsal lehet beállítani az SMTP szerver címét, ha nem sendmail-lel szeretnénk a levelet küldeni (chroot környezetben tevékenykedő Linuxos, vagy más rokon Un*xos felhasználóknál ez a módszer nem működik, a legegyszerűbb egy az alábbiakban bemutatandó osztályt használni erre a célra, vagy pedig egy megfelelő célprogramot telepíteni a chroot környezetbe). A cím, amit megadunk lehet a localhost, ha a PHP-t futtató gépen van levelező szerver, vagy lehet az internet szolgáltatónk SMTP szerverének címe (amit a levelezőprogramunkban is megadunk a levélküldéshez), ha otthon futtatjuk a programot. A php.ini beállítás:

SMTP = azen.ispmcime.hu
Programból kiadva:

<?
ini_set('SMTP', 'azen.ispmcime.hu');
?>
Ha mégis érdeklődünk az iránt, hogy a szabvány szerint hogyan kell felépülnie egy levélnek, hogy hogyan tudnánk ezt mi is megtenni, akkor két utat tudok javasolni. Egyrészt a PHP dokumentációban is megemlített leírások is segítséget nyújthatnak: RFC 1896, RFC 2045, RFC 2046, RFC 2047, RFC 2048 és RFC 2049, másrészt pedig foghatunk egy a következőkben bemutatott osztályhoz hasonló kódot és megnézhetjük, hogy hogyan végzi a dolgát.

Hogyan lehet egyszerűbben?

Az előző HTML-es példában láthattuk, hogy már ott is egy kicsit bonyolultabb kódot kellett írnunk, ha HTML levelet akartunk küldeni. Persze egy ilyet nem nehéz leírni, főleg másolgatni az egyes programjaink között, de azért vannak relatíve szebb megoldások is különböző osztályok személyében. Mi most a Sourceforge-on is elérhető egyik ilyen osztály mutatjuk be, hangsúlyozva, hogy számos más megoldás is létezik. Ez az osztály a PHP Mailer.

Röviden felsorolva lássuk, mit tud: több címzettet (valódi címzett, másolatot és titkos másolatot kapó címzettek), több válaszcímet, több redundáns SMTP szervert adhatunk meg, küldhetünk "multipart/alternative" levelet (HTML-t és sima szöveget is elküldjük, a címzett levelezőprogramja azt jeleníti meg, amelyikre fel van készítve), támogat számos (8 bit, base64, bináris, "quoted-printable") kódolási lehetőséget, tördelni képes a sorokat, stb.

A cikkben nem fogjuk bemutatni a teljes eszköztárát, csak egy ízelítőt szeretnénk nyújtani abból, hogy milyen egyszerűen és széleskörűen használható osztályról van szó. Részletes referenciáért keressük fel a dokumentációját.

Alapok

Egy egyszerű példán keresztül nézzük meg, hogyan tudunk levelet küldeni ezzel az osztállyal:

<?
require("class.phpmailer.php");

$mail=new PHPMailer();
$mail->From="feladó##kukac##domain.hu";
$mail->AddAddress("címzett##kukac##domain.hu");
$mail->Subject="a levél tárgya";
$mail->Body="magának a levélnek\naz egyes sorai.";

if (!$mail->Send()) {
  echo "Az üzenet nem került elküldésre";
  echo "A felmerült hiba: " . $mail->ErrorInfo;
  exit;
}

echo "A levelet sikeresen kiküldtük";
A legelsőnek bemutatott példához képest ez "kicsit" bonyolultabb, viszont talán egy "kicsit" áttekinthetőbb, hiszen önleíró abból a szempontból, hogy beszélő elnevezéseket használ. Persze általában nem egy ilyen egyszerű levél elkészítésére használjuk, az elkövetkezőkben be is mutatunk egy jóval bonyolultabb esetet is. De elsőnek nézzük meg, hogy melyik sor mire való.

Az első sor az osztály betöltésére való. Ezután egy egyedet készítünk a PHPMailer() osztályból.

A következő sorokban beállítjuk a paramétereit a levélnek. A From a levél címzettjét határozza meg, a Subject a levél tárgyát, míg a Body a levél tartalmát. Az AddAddress-t kihagytam, mivel egy kicsit más - itt egy eljáráson keresztül a címzett(ek)et állítjuk be.

Végül elküldjük a levelet a Send eljárás meghívásával. Ha ennek a visszatérési értéke hamis, akkor hiba történt az elküldés folyamán, a hiba okát az ErrorInfo tartalmának kiíratásával jelenítjük meg.

Fokozzuk az élvezeteket

Lássunk egy bonyolult példát mely szinte bemutatja az összes lehetőségét az osztálynak. A példát - nem titkoltan - az osztályt bemutató oldalról másoltuk:

<?
require("class.phpmailer.php");

$mail = new PHPMailer();

$mail->IsSMTP();                                   // SMTP-n keresztüli küldés
$mail->Host     = "smtp1.site.com;smtp2.site.com"; // SMTP szerverek
$mail->SMTPAuth = true;                            // SMTP autentikáció bekapcs
$mail->Username = "jswan";                         // SMTP felhasználó
$mail->Password = "secret";                        // SMTP jelszó

$mail->From     = "from##kukac##email.com";                // Feladó e-mail címe
$mail->FromName = "Mailer";                        // Feladó neve
$mail->AddAddress("josh##kukac##site.com","Josh Adams");   // Címzett és neve
$mail->AddAddress("ellen##kukac##site.com");               // Még egy címzett
$mail->AddReplyTo("info##kukac##site.com","Information");  // Válaszlevél ide

$mail->WordWrap = 50;                              // Sortörés állítása
$mail->AddAttachment("/var/tmp/file.tar.gz");      // Csatolás
$mail->AddAttachment("/tmp/image.jpg", "new.jpg"); // Csatolás más néven
$mail->IsHTML(true);                               // Küldés HTML-ként

$mail->Subject = "Here is the subject";            // A levél tárgya
$mail->Body    = "This is the <b>HTML body</b>";   // A levél tartalma
$mail->AltBody = "This is the text-only body";     // A levél szöveges tartalma

if (!$mail->Send()) {
  echo "A levél nem került elküldésre";
  echo "A felmerült hiba: " . $mail->ErrorInfo;
  exit;
}

echo "A levelet sikeresen kiküldtük";
?>
Ebben a példában egy SMTP szerveren keresztüli küldést viszünk véghez. Mint látható, több szervert is beállíthatunk - ha az első nem elérhető, akkor a másodikkal próbálkozik a program. A példában olyan szervereket állítottunk be, ahol autentikáció szükséges, így a felhasználónevet és a jelszót is meg kellett adnunk.

A feladó és nevének beállítása után két címzettet is beállítunk, illetve egy olyan címet is, ahova a válaszlevelek visszaérkezhetnek. Megadjuk, hogy tördelje a sorokat minden 50. karakternél, két állományt csatolunk a levélhez, a második esetben nem az eredeti nevén, továbbá jelezzük, hogy HTML levelet fogunk küldeni.

A küldés előtt még be kell állítani a levél tárgyát és tartalmát, illetve esetünkben egy alternatív tartalom is meg lett adva, ami akkor fog megjelenni a címzett levelezőprogramjában, ha az nem tud HTML levelet megjeleníteni.

Összefoglalás

A program honlapján egy szép lista van a referenciákról, komoly projektek döntöttek ennek az osztálynak az alkalmazása mellett. A csatolmányok és egyéb feladatok küldését egyszerűbbé teszi ez az osztály, tehát akinek nincs hajlama arra, hogy megismerkedjen mélyebben a MIME levelek felépítésével, vagy csak nincs ideje rá, annak mindenképpen a figyelmébe ajánlanám ezt az osztályt.

Mint korábban is említettem, ez csak egy alternatíva, tehát lehet, hogy egy számunkra szimpatikusabb, vagy az adott helyzethez jobban illő osztályt találunk - keresgéljünk nyugodtan. Az általános igényeket ez az osztály is ki tudja elégíteni, kiindulási alapnak tökéletes.

Pár link, melyeken el lehet indulni, ha további lehetőségeket keresünk:
 
Bártházi András arcképe
Bártházi András
Az Emarsys-nál dolgozik vezető fejlesztőként, és az API-ért, integrációkért felelős termékmenedzserként. Szeret profi csapatban profit alkotni.
1

PEAR Mail_Mime

Mocsnik Norbert · 2004. Okt. 27. (Sze), 21.43
PEAR Mail_Mime

<?php
include('Mail.php');
include('Mail/mime.php');

$text = 'Text version of email';
$html = '<html><body>HTML version of email</body></html>';
$file = '/home/richard/example.php';
$crlf = "\n";
$hdrs = array(
              'From'    => 'you##kukac##yourdomain.com',
              'Subject' => 'Test mime message'
              );

$mime = new Mail_mime($crlf);

$mime->setTXTBody($text);
$mime->setHTMLBody($html);
$mime->addAttachment($file, 'text/plain');

$body = $mime->get();
$hdrs = $mime->headers($hdrs);

$mail =& Mail::factory('mail');
$mail->send('postmaster@localhost', $hdrs, $body);
?>


Beágyazott képek küldése: addHTMLImage()
2

Port

Anonymous · 2005. Júl. 21. (Cs), 16.40
Az SMTP szervert ugyan meg lehet adni, de a portot hogy állapíthatjuk meg?
4

Port

tiny · 2007. Júl. 15. (V), 10.21
Alapból a 25-ös portot használja, de előfordulhat, hogy a szerver más portot kér. Ebben az esetben a $Port változó értékét kell átállítani.
[off]tudom, hogy régi a kérdés, de hátha valaki belebotlik :) [/off]
3

Embedded image support

Anonymous · 2006. Aug. 12. (Szo), 05.42
Hi! Probált már valaki phpmailer segítségével beágyazott képet köldeni. A weboldalukon lévő minta nekem nem müködik.

http://phpmailer.sourceforge.net/tutorial.html#4

$mail->AddEmbeddedImage("rocks.png", "my-attach", "rocks.png"));
$mail->Body = 'Embedded Image: <img alt="PHPMailer" src="cid:my-attach"> Here is an image!';

Eleve a zárójel nem kell. De ha azt kiveszem akkor is a levélben csak a kép helye jelenik meg magat a képet nem küldi.
5

Nálam az volta gond, hogy

ED · 2010. Már. 23. (K), 16.00
Nálam az volta gond, hogy netről próbáltam berakni a képet...
Azaz így nem működik:
$mail->AddEmbeddedImage("http://valami.hu/valami.jpg", "valami", "valami.jpg");

Így viszont már igen:
$mail->AddEmbeddedImage($_SERVER["DOCUMENT_ROOT"].KEPEK_HELYE."valami.jpg", "valami", "valami.jpg");

Így ugyan rákényszerülök, hogy php-val először az adott serverre másolom a képet, majd onnan beszúrom a levélbe, végül törlöm a képet...
6

Lehetséges?

buzlee · 2012. Május. 4. (P), 13.43
Megoldható ay php segítségével hogy az email fiókomba beérkező bizonyos emailek továbbítva legyenek egy sql-es címlista alapján?