Přejít k navigační liště

Zdroják » PHP » Testujeme posílání mailů z aplikace v PHP

Testujeme posílání mailů z aplikace v PHP

Články PHP, Různé

Při testování aplikace na lokálním stroji často potřebujeme ověřit, jestli aplikace odeslala správný e-mail na správnou adresu. Možností, jak to ověřit, je víc, nemusíte vždy zadávat svůj mail a kontrolovat, jestli zpráva přišla. Jak na to v PHP (převážně pod Windows) si ukážeme v článku.

Pravděpodobně jste už někdy ve své PHP aplikaci potřebovali naprogramovat odesílání mailů a jistě se shodneme, že zkoušet, zda funguje správně, není na vývojovém PC úplně pohodlné. Někteří to řeší tak, že to odzkouší až na testovacím serveru, jiní doufají, že se to tak nějak správně odesílá. Správným fungování máme na mysli to, že se do e-mailu generuje to, co se tam generovat má.

Možnost 1 – použití živého SMTP serveru

Pro použití SMTP serveru není potřeba žádného složitého nastavování. Stačí v  php.ini nastavit adresu SMTP serveru (třeba od vašeho providera), a je to.

SMTP = smtp.t-email.cz
smtp_port = 25
sendmail_from = martin.hujer@example.com

Hodnotu sendmail_from nastavte na nějaký reálný e-mail, protože jinak může SMTP bránit odeslání nebo budou maily na straně příjemce padat do SPAMu. Toto, na první pohled jednoduché, řešení má velkou nevýhodu – může se snadno stát, že z aplikace omylem odešlete testovací e-maily přímo zákazníkům (vzpomeňme na známou testovací SMS serveru iHNed). Ale na druhou stranu se může hodit, když potřebujete otestovat zobrazení HTML e-mailů v různých webmailech. Jinak je většinou vhodnější použít nějaké jiné řešení, třeba dummy SMTP server.

Poznámka: Pokud vyvíjíte na Windows, můžete zkusit alternativu k sendmailu – fake sendmail.

Možnost 2 – použití dummy SMTP serveru

Tzv. dummy (neboli fiktivní) SMTP server je aplikace, která se z pohledu PHP chová jako běžný SMTP server, ale e-maily si nechává v sobě a nikam je neodesílá. Nemůže se vám tedy stát, že odešlete něco, co jste nechtěli. Jako příklad použijeme smtp4dev (spoustu dalších si můžete najít vyhledáním dummy smtp server). Program se po spuštění tváří jako lokální SMTP server, takže stačí v  php.ini změnit SMTP:

SMTP = localhost

Po odeslání testovacího mailu vyskočí bublina

a e-mail si můžeme prohlédnout v hlavním okně

Po poklikání se e-mail otevře jako náhled ve výchozím programu (může to být například Outlook nebo Thunderbird). Případně je možné si zobrazit detaily zprávy včetně hlaviček v interním prohlížeči aplikace.

Možnost 3 – ukládání e-mailů do souborů

Pokud si nechcete instalovat další program, můžete použít řešení, které jsme dali dohromady s Tomášem Fejfarem. V  php.ini máme volbu sendmail_path, která je v distribučním balíčku zakomentovaná a je u ní komentář „For Unix only“. Ale toho se nebudeme bát, odkomentujeme jej, a protože volba může obsahovat jakýkoliv příkaz, vložíme tam toto:

sendmail_path = "more | i:\xampplite\sendmail\savemail.bat"

Vše, co by se předávalo sendmailu, předáme skriptu příkazové řádky, který vypadá takto:

savemail.bat

::kam budeme ukládat e-maily?
SET mailpath=I:\xampplite\sendmail\mails

if not exist %mailpath% mkdir %mailpath%

::pokud je ráno mezi 0-9h, tak musíme hodiny získat jiným způsobem - " 0" jinak dělá neplechu v názvu souboru
IF %time:~0,2% EQU  0 (
    SET hours=0%time:~1,1%
) ELSE (
    SET hours=%time:~0,2%
)
::sestavíme název souboru
SET filename=20%date:~11,4%-%date:~6,2%-%date:~3,2%_%hours%-%time:~3,2%-%time:~6,2%_%time:~9,2%

::zajistíme unikátnost souboru
:random
SET file=%mailpath%\%filename%%RANDOM%.eml
IF EXIST %file% goto :random

::e-mail uložíme do souboru
more %1 > %file%

::otevřeme adresář s e-maily Průzkumníkem
:: start %mailpath%

::a nebo přímo otevřeme e-mail
start %file%

Tento dávkový soubor vytvoří jméno souboru podle aktuálního data a času, uloží do něj obsah e-mailu a složku s e-maily otevře v Průzkumníku (nebo otevře přímo e-mail).

Řešení pro Linux

Na Linuxu je možné nastavit sendmail_path takto:

sendmail_path = "/home/martinhujer/mail/send.sh"

A použít skript:

send.sh

#!/bin/sh

#kam budeme ukládat e-maily?
mailpath=/tmp

#název souboru
file=$(date +"%Y-%m-%d")\_$(date +"%H-%M-%S_%N")".eml"

echo $mailpath/$file

#mail ze /dev/stdin uložíme do souboru
while read x ; do echo $x >> $mailpath/$file ; done

Ten uloží e-mail do souboru do adresáře /tmp. (Otevření souboru jsem zde neřešil – pozn.aut.)

Možnost 4 – ukládání e-mailů do souborů přímo v aplikaci

Pokud PHP framework podporuje odesílání e-mailů, tak většinou umožňuje použití různých adaptérů (transportů) pro odesílání e-mailů (pomocí funkce mail(), přes SMTP,…). Není tedy problém si vytvořit svoji implementaci transportu, která bude e-maily ukládat do souboru. Například Zend Framework takový adaptér obsahuje již v základu, použití může vypadat takto:

<?php
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);

Zend_Mail::setDefaultTransport(
    new Zend_Mail_Transport_File(
        array(
            'path' => __DIR__,
            'callback' => function() {
                do {
                    $file = 'email-' . date('Y-m-d_H-i-s') . '_' . mt_rand() . '.eml';
                } while (file_exists($file));
                return $file;
            },
        )
    )
);

$mail = new Zend_Mail('utf-8');
$mail->addTo('mhujer@gmail.com');
$mail->setSubject('Test subj');
$mail->setBodyText('test text');
$mail->send();

Tuto možnost je vhodné kombinovat s ukládáním mailů odeslaných přímo přes mail()  – může se stát, že v kódu někde je zapomenuté přímé volání této funkce, tak aby vám nějaký odesílaný e-mail neušel.

Závěr

V článku jsme si ukázali, jak lze testovat odesílání e-mailů z PHP třeba i o něco elegantněji, než prostým posláním a následnou kontrolou e-mailové schránky. Pokud používáte ještě nějaké jiné (a třeba lepší) řešení, podělte se o něj v diskusi.

Komentáře

Subscribe
Upozornit na
guest
28 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Dalibor Šimáček

Používám Papercut, podle všeho je podobný zmiňovanému smtp4dev. Umí rychle přepínat mezi Raw View (s hlavičkami), Body View (plain text obsahu) a HTML View (i se styly). Je jednoduchý a funguje zatím spolehlivě.

Miloslav Hůla

Díky za tip na Papercut. smtp4dev-2.0 na WinXP SP3 padá neustále, škoda že se nevygeneruje alespoň nějaký bug report.

Neznáte nějaký dummy SMTP server, který by uměl také pracovat s přílohami?

dasim

Papercut mi nepadá, alespoň ne pod Win 7. To je asi jediné co můžu dodat, přílohy jsem zatím testovat nepotřeboval. Každopádně stabilní Papercut je.

Jan Pobořil

V produkčním prostředí bych rád ukládal všechny maily odeslané z PHP na IMAP server do odeslaných, konkrétně do Gmail schránky, aby bylo možné při komunikaci s klienty jednoduše vidět co jim přišlo z systému. Napadá Vás nějaké řešení?

František Kučera

Odesílat to i sám sobe ve skryté kopii a na serveru si udělat filtr, který tyto zprávy přesune do složky Odeslaná pošta.

Ondřej Mirtes

Odesílat přes SMTP Googlu?

Radim Daniel Pánek

Jak to myslíš? Dyť přes IMAP se dá přesunout zpráva do jiné složky, tedy i do odeslané.

Některé SMTP servery ukládají poštu, která přes ně projde, zároveň do příslušné složky do schránky odesílatele – takže není potřeba zprávu odesílat po síti dvakrát (jednou přes SMTP a podruhé přes IMAP pro uložení do schránky).

Kedy

Jako „dummy SMTP server“ používám doposud „Test Mail Server Tool“, ten ukládá eml soubory na disk.

Chtěl jsem zkusit smtp4dev ale ten když mu přijde e-mail tak spadne. Mám WINXP SP2, netušíte někdo kde je problém ?

radas

Na Windows 7 taky padá.

nAS

Starší verze mi funguje, ale má problém s diakritikou.

radas

Tak dokonce na Windows 7 funguje i 2.0 beta.

jos

na otázku sis odpověděl ještě před jejím položením ;)

Martin

Mne zas chvíľu fungoval Test Mail Server Tool, potom prestal, neprišiel som na príčinu ale odvtedy používam smtp4dev a funguje dobre, na win7. Takže to mám opačne ako ty :)

error414-

existuje neco takoveho i pro osx? nic sem zatim nenasel.

Tomáš Fejfar

Můžeš využít popsaný skript pro Linux, ne?

Radim Daniel Pánek

Přesně, taky bycch šáhnul po skriptu pro Linux. Jenže error414 pořídil 8GB ram, tak na všechno chce aplikačky :-D :-D :-D

abtris
Radim Daniel Pánek

Placený cca 500kč

Pilgrim

Jedna věc je zajistit odesílání, ale to zvládne každý. Větší efektivitu vidím v tom, ohlídat si zda email do schránky dorazil a zda si ho vůbec adresát přečetl. Toto má částečně hezky vyřešený SugarCRM, který do každého emailu dává 1px obrázek s adresou skriptu, který po zavolání (načtení obrázku) zapíše informaci, že si email adresát přečetl. Nevýhoda je v tom, že některý klienti nestahují obrázky ve zprávě automaticky, ale až na vyžádání.

František Kučera

„Nevýhoda“ :-)

Spíš výhoda. To jsou legitimní bezpečnostní důvody, že se tyhle obrázky nenačítají ;-) Ne každý chce být sledován (zvlášť když ten e-mail může být odeslaný spamerem nebo jiným záškodníkem). Serióznější je použít klasické doručenky – ty jsou jednak standardní a jednak respektují přání uživatele (někdo je odesílá vždy, někdo jen po ručním potvrzení, někdy nikdy…). Ty skryté 1px obrázky jsou zákeřnější a neslušné.

Pilgrim

V tomto případě je to nevýhoda, jinak co se týče bezpečnosti emailů, tak je to samozřejmě výhoda. Ale pro potřeby programování je daleko jednodušší hodit do mailu 1px obrázek a na zavolané url si to zpracovat, než dělat skript, který by vyčítal doručenky a ještě to někam podle nich zapisoval. Však doručenku i obrázky stejně někdo musí odkliknout. :-)

Radim Daniel Pánek

Spíše se přikládním u kládání „příklad v linuxu“ do souboru z důvodu, že pokud provádím „integrační test“, tak samozřejmě chci zkontrolovat odeslání emailu z aplikace, nicméně bych chtěl otestovat i výsledný email – resp. jeho syntax.

Představuji si to jako testování externího zdroje a napadá mě, že ukládání do souboru je lepší řešení, než testování odeslaných emailů IMAPem.

1). Otestuji odeslání emailu
2). Uložím email do souboru do root_projektu/tes­ts/_files/
3). Otestuji existenci souboru
4). Otestuji, zda-li se v těle souboru nachází řetězec který mě zajímá

Tomáš Fejfar

V ukázkách kódu zmizela zpětná lomítka. Takže jsou trochu nepřehledné :) Můžeš to fixnout ty, @martinhujer nebo to musí udělat @hassmann ?

Martin Hassman

Pošli mi to do mailu a já to opravím.

Vendula

Nedaří se mi prosím zprovoznit upozornění o zachyceném odeslaném e-mailu.

Používám XAMPP a stahla jsem si smtp4dev, odkomentovala jsem v php.ini řádky pro port a localhost a smtp4dev spustila, ale po odeslání se mi nezobrazí nic.

Zkoušela jsem to i na jednoduchém scripnu pro odeslání zprávy a taky se nic nezobrazilo, tak netuším, kde je to třeba ještě povolit.

Firewall brána mi to taky neblokuje – je odblokováno.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.