nSMTPMailer
Tato knihovna slouží pro odesílání emailů přes (i zabezpečené) SMTP servery. Jedním z hlavních cílů je i její použitelnost bez Nette, ovšem s Nette je její použití samozřejmě mnohem pohodlnější (hlavně díky Nette\Mail). Dalším cílem je co nejvěrnější implementace příslušných RFC.
Vrták už podobnou knihovnu napsal dřív (SmtpSendmailMailer), a i ta jeho ve většině běžných případů funguje. Nicméně vypadá, že je daleko víc zadrátovaná do Nette, navíc je licencovaná pod LGPL.
| Verze | 1.0 |
|---|---|
| Download | http://github.com/…TPMailer.zip |
| Demo | pouze ke stažení, jinak bych také použitý server mohl dostat na SMTP blacklisty; ukázka použití bez Nette: http://github.com/…/example.php ; ukázka použití s Nette: http://github.com/…_example.zip |
| Forum thread | http://forum.nette.org/…tp-mailovani |
| Autor | Martin Pecka (peci1 uzenáč seznam) |
| Licence | New BSD |
| Homepage | http://addons.nette.org/cs/nsmtpmailer |
| Git web | http://github.com/…/nSMTPMailer |
| Git | git://github.com/peci1/nSMTPMailer.git |
Adresářová struktura
- nSMTPMailer
- Commands
- Implementace SMTP příkazů
- SmtpClient.php
- exceptions.php
- Communicator.php
- Response.php
- license.txt
- netterobots.txt
- Commands
- SmtpMailer.php
Použití v Nette
Instalace
Stáhněte a archiv rozbalte do LIBS_DIR (v defaultní Nette struktuře je to /libs; je to ta složka, kde máte i složku Nette). Tím je instalace hotova (pokud tedy používáte RobotLoader, jinak musíte includnout SmtpMailer.php).
Můžete smazat soubory exceptions.php a netterobots.txt, ale buďto pouze oba najednou a nebo je oba nechte být!
Příklad použití
SendModel.php – nějaký model, který obstarává odesílání emailů
<?php
class SendModel
{
private $result = '';
/**
* Pošle email
* @param array of string $recipients Příjemci emailu
* @param string $body Tělo emailu
*/
public function send(array $recipients, $body) {
//povolíme nastavování přes config.ini
$conf = Environment::getConfig('mail');
//email sestavíme pomocí Nette\Mail
$mail = new Mail();
//nastavení nSMTPMaileru (z config.ini)
$mailer = new SmtpMailer($conf['host'], $conf['port'],
$conf['transport'], $conf['username'], $conf['password'],
$conf['authId'], $conf['mechanism'], $conf['tryUnauthenticated']);
$mail->setMailer($mailer); //důležité!!!
$mail->setFrom($conf['from']);
$undelivered = array();
foreach ($recipients as $email) {
try {
//tady můžeme prohnat zadané adresy nějakým úžasným regexem
if (!preg_match('/^\s*$/', $email)) {
//můžeme použít i addCC a addBcc
$mail->addTo($email);
} else {
$undelivered[] = $email;
}
} catch (InvalidArgumentException $e) {
$undelivered[] = $email;
}
}
$mail->setSubject('Great mail');
$mail->setBody($body);
try {
$mail->send();
$undelivered = array_merge(
$undelivered,
$mailer->getUndeliveredRecipients());
if (count($undelivered) > 0)
$this->result = $undelivered;
else
$this->result = TRUE;
} catch (InvalidStateException $e) {
$this->result = FALSE;
}
}
public function getResult()
{
return $this->result;
}
}
?>
A ukázkový config.ini
[common]
mail.from = "username@gmail.com"
mail.username = "username"
mail.password = "password"
mail.host = "smtp.gmail.com"
mail.port = "587"
mail.transport = "tcp"
Parametry konstruktoru SmtpMailer
| Parametr | Význam | Defaultní hodnota |
|---|---|---|
| $server | URL adresa SMTP serveru (bez schématu (http://)) (viz Příklady konfigurace) | povinný |
| $port | Port, na který se připojit (viz Příklady konfigurace) | 25 |
| $transport | Transportní vrstva (viz Příklady konfigurace) | ‚tcp‘ |
| $username | Uživatelské jméno (viz Implementované autentizační mechanismy) | NULL |
| $password | Heslo (viz Implementované autentizační mechanismy) | NULL |
| $authId | Role pro PLAIN autentizaci (viz Implementované autentizační mechanismy) | NULL |
| $mechanism | Preferovaný autentizační mechanismus (viz Příklady konfigurace) | LOGIN |
| $tryUnauthenticated | Zkusit odeslat email i přes nepovedenou autentizaci? | TRUE |
Použití bez Nette
Instalace
Pokud nechcete tuto knihovnu používat v Nette, ale v nějaké jiné aplikaci, rozbalte archiv a někam do své aplikace překopírujte podsložku nSMTPMailer (tj. nekopírujte SmtpMailer.php !). Pak includněte SmtpClient.php.
Můžete smazat netterobots.txt
Pokud používáte nějakou formu autoloadingu, je třeba ho ve složce nSMTPMailer zakázat a includovat pouze SmtpClient.php!
Knihovna si definuje výjimky InvalidStateException a IOException. Pokud je vaše aplikace také definuje, musíte zajistit jejich kompatibilitu s výjimkami v exceptions.php!
Příklad použití
send.php
<?php
header('Content-Type: text/html; charset=utf-8');
require_once('nSMTPMailer/SMTPClient.php');
$client = new SMTPClient();
$client->setConnectionInfo('smtp.gmail.com', 587, 'tcp', 300);
$client->setLoginInfo('username', 'password');
$client->setFrom('username@gmail.com');
$recipients = array('user1@seznam.cz', 'user2@seznam.cz');
$client->setRecipients($recipients);
$client->setBody('Very dirty message without headers in it!');
try {
$client->send();
$undelivered = $client->getUndeliveredRecipients();
if (empty($undelivered))
echo 'Email byl úspěšně odeslán';
else
echo 'Email se neodeslal na tyto adresy: ' . implode (',', $undelivered);
} catch (InvalidStateException $e) {
echo 'Email se vůbec nepovedlo odeslat';
}
/* ?> omitted intentionally */
Parametry pro setConnectionInfo a setLoginInfo odpovídají parametrům konstruktoru SmtpMailer (viz Parametry konstruktoru SmtpMailer)
Jako argument pro setBody je nutné předat už hotový email včetně hlaviček a všeho ostatního! Právě tuhle práci pro Nettisty udělá Nette\Mail (a možná si ji i neNettisté mohou vyextrahovat a pak používat SmtpMailer).
Poznámky k implementaci
Návratová hodnota SmtpClient::send()
Metoda send() nemá žádnou návratovou hodnotu. Pokud vyhodí výjimku InvalidStateException, pak se nepovedlo připojení k serveru, selhala autentizace nebo nebyli specifikováni žádní (validní) příjemci. Pokud výjimku nevyhodí, pak byl email na alespoň jednu adresu odeslán. Pokud se ho na nějakou adresu nepovedlo odeslat, pak se tato adresa ocitne v poli SmtpClient::getUndeliveredRecipients() (a to ať už z důvodu špatné adresy nebo z důvodu, že tuto adresu odmítl server). Takže byste vždy po odeslání měli obsah tohoto pole kontrolovat.
Implementované autentizační mechanismy
Zde je popis implementovaných autentizačních mechanismů a význam proměnných předávaných do SmtpClient::setLoginInfo.
| Mechanismus | Popis | Význam $username | Význam $password | Význam $authId |
|---|---|---|---|---|
| LOGIN | Nejpoužívanější mechanismus (Google, Seznam). Bez SSL nebezpečný. | Uživatelské jméno | Heslo | – |
| PLAIN | Nezabezpečený mechanismus, snad už se veřejně nepoužívá | Uživatelské jméno | Heslo | Jméno role pro přihlášení |
| CRAM-MD5 | Autentizační mechanismus bezpečný i bez SSL, ale málo používaný | Uživatelské jméno | Heslo | – |
Příklady konfigurace
Konfigurace několika nejznámějších free SMTP serverů
| Server | Port | Transportní vrstva | Aut. mechanismus |
|---|---|---|---|
| smtp.gmail.com | 587 | tcp | LOGIN |
| smtp.gmail.com | 465 | ssl | LOGIN |
| smtp.gmail.com | 25 | tcp | LOGIN |
| smtp.seznam.cz | 25 | tcp | LOGIN |
Ukázky použití
Odkazy jsou uvedeny výše. Po rozbalení příkladu pro Nette je třeba ještě vytvořit složku /libs a nahrát do ní Nette i nSMTPMailer
Debugging
Můžete nastavit statickou proměnnou SmtpClient::$debugMode na TRUE. Pak bude klient vypisovat komunikaci se serverem a výjimky, které nastaly uvnitř klienta. Pokud tento obsah nechcete vypsat, musíte použít output buffering (ob_start)
Poznámky k implementovaným RFC
Čísla implementovaných RFC už si nepamatuju :) Ovšem hlavní SMTP RFC vyžaduje, aby klient opakovaně zkoušel odeslat email, který se mu odeslat nepovedlo. To na běžně nastaveném PHP serveru není možné. Také doporučené timeouty nebylo možné dodržet vzhledem k omezení doby běhu skriptu.
Poznámky k licenci
Pokud New BSD licenci neznáte, tak v krátkosti – s knihovnou smíte dělat vše, co vás napadne, pokud zachováte copyrightové a právní doložky na začátku skriptů. Mimo jiné smíte knihovnu používat pro komerční účely, integrovat do non-open-source aplikací a tyto aplikace pak prodávat. Licence je plně kompatibilní s GPL (a snad i LGPL).
Komentáře 
Matúš Matula | 26. 4. 2010, 1:40 | comment
v php 5.3 je eregi deprecated, pouzi namiesto toho preg_match s identifikatorom ‚i‘ . viac napr. tu http://takien.com/…hp-5-3-0.php
2bfree | 18. 1. 2011, 15:56 | comment
Aby si i jiní ušetřili čas implementování něčeho, co už je pasé, tak jsem vložím toliko důležitý odkaz http://forum.nette.org/…rimo-v-nette

oaki | 23. 4. 2010, 15:11 | bug
Ahoj, toto mi vyhadzuje pri odosielani. PHP Deprecated: Function eregi() is deprecated in /Nette-extras/nSMTPMailer/nSMTPMailer/Commands/BaseCommand.php on line 180