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

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: 28

Přehled komentářů

Dalibor Šimáček Papercut
Miloslav Hůla Re: Papercut
dasim Re: Papercut
janpoboril Archivace na IMAP
František Kučera Re: Archivace na IMAP
Ondřej Mirtes Re: Archivace na IMAP
Radim Daniel Pánek Re: Archivace na IMAP
František Kučera Re: Archivace na IMAP
Kedy smtp4dev padá
radas Re: smtp4dev padá
nAS Re: smtp4dev padá
radas Re: smtp4dev padá
jos Re: smtp4dev padá
Martin Re: smtp4dev padá
error414- Re: Testujeme posílání mailů z aplikace v PHP
Tomáš Fejfar Re: Testujeme posílání mailů z aplikace v PHP
Radim Daniel Pánek Re: Testujeme posílání mailů z aplikace v PHP
Martin Hujer Re: Testujeme posílání mailů z aplikace v PHP
abtris Re: Testujeme posílání mailů z aplikace v PHP
Radim Daniel Pánek Re: Testujeme posílání mailů z aplikace v PHP
Pilgrim SugarCRM
František Kučera Doručenky v e-mailech
Pilgrim Re: Doručenky v e-mailech
Radim Daniel Pánek Testování obsahu odeslaného emailu
Tomáš Fejfar Neoescapovaná zpětná lomítka v kódu?
Martin Hassman Re: Neoescapovaná zpětná lomítka v kódu?
Martin Hujer Re: Neoescapovaná zpětná lomítka v kódu?
Vendula SMTP nic nezachytí
Zdroj: https://www.zdrojak.cz/?p=3512