Mail

Trimitere
E-mailuri

Trimiterea de e-mailuri

Sunteți pe cale să trimiteți e-mailuri, de exemplu, newslettere sau confirmări de comandă? Nette Framework oferă instrumentele necesare cu o API foarte prietenoasă. Vă vom arăta:

  • cum să creați un e-mail, inclusiv atașamente
  • cum să îl trimiteți
  • cum să combinați e-mailurile și șabloanele

Instalare

Descărcați și instalați biblioteca folosind Composer:

composer require nette/mail

Crearea unui e-mail

E-mailul este un obiect al clasei Nette\Mail\Message. Îl creăm, de exemplu, astfel:

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Confirmare comandă')
	->setBody("Bună ziua,\ncomanda dvs. a fost primită.");

Toți parametrii introduși trebuie să fie în UTF-8.

Pe lângă specificarea destinatarului cu metoda addTo(), puteți specifica și destinatarul copiei addCc(), sau destinatarul copiei ascunse addBcc(). În toate aceste metode, inclusiv setFrom(), putem scrie adresa în trei moduri:

$mail->setFrom('franta@example.com');
$mail->setFrom('franta@example.com', 'Franta');
$mail->setFrom('Franta <franta@example.com>');

Corpul e-mailului scris în HTML se transmite prin metoda setHtmlBody():

$mail->setHtmlBody('<p>Bună ziua,</p><p>comanda dvs. a fost primită.</p>');

Nu trebuie să creați alternativa text, Nette o va genera automat pentru dvs. Și dacă e-mailul nu are setat un subiect, va încerca să îl preia din elementul <title>.

De asemenea, puteți insera imagini în corpul HTML extrem de ușor. Este suficient să transmiteți calea unde se află fizic imaginile ca al doilea parametru, iar Nette le va include automat în e-mail:

// adaugă automat /path/to/images/background.gif în e-mail
$mail->setHtmlBody(
	'<b>Hello</b> <img src="background.gif">',
	'/path/to/images',
);

Algoritmul care inserează imagini caută aceste modele: <img src=...>, <body background=...>, url(...) în interiorul atributului HTML style și sintaxa specială [[...]].

Poate fi trimiterea de e-mailuri și mai simplă?

E-mailul este ca o carte poștală. Nu trimiteți niciodată parole sau alte date de acces prin e-mail.

Atașamente

Desigur, puteți atașa fișiere la e-mail. Metoda addAttachment(string $file, ?string $content = null, ?string $contentType = null) este folosită pentru aceasta.

// inserează fișierul /path/to/example.zip în e-mail sub numele example.zip
$mail->addAttachment('/path/to/example.zip');

// inserează fișierul /path/to/example.zip în e-mail numit info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// inserează fișierul example.txt în e-mail cu conținutul "Hello John!"
$mail->addAttachment('example.txt', 'Hello John!');

Șabloane

Dacă trimiteți e-mailuri HTML, este firesc să le scrieți în sistemul de șabloane Latte. Cum se face?

$latte = new Latte\Engine;
$params = [
	'orderId' => 123,
];

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->setHtmlBody(
		$latte->renderToString('/path/to/email.latte', $params),
		'/path/to/images',
	);

Fișierul email.latte:

<html>
<head>
	<meta charset="utf-8">
	<title>Confirmare comandă</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Bună ziua,</p>

	<p>Comanda dvs. numărul {$orderId} a fost primită.</p>
</body>
</html>

Nette inserează automat toate imaginile, setează subiectul conform elementului <title> și generează alternativa text la HTML.

Utilizare în Nette Application

Dacă utilizați e-mailurile împreună cu Nette Application, adică cu presenteri, este posibil să doriți să creați linkuri în șabloane folosind atributul n:href sau tag-ul {link}. Latte nu le cunoaște implicit, dar este foarte ușor să le adăugați. Crearea linkurilor este gestionată de obiectul Nette\Application\LinkGenerator, la care puteți ajunge solicitându-l prin injecția de dependențe:

use Nette;

class MailSender
{
	public function __construct(
		private Nette\Application\LinkGenerator $linkGenerator,
		private Nette\Bridges\ApplicationLatte\TemplateFactory $templateFactory,
	) {
	}

	private function createTemplate(): Nette\Application\UI\Template
	{
		$template = $this->templateFactory->createTemplate();
		$template->getLatte()->addProvider('uiControl', $this->linkGenerator);
		return $template;
	}

	public function createEmail(): Nette\Mail\Message
	{
		$template = $this->createTemplate();
		$html = $template->renderToString('/path/to/email.latte', $params);

		$mail = new Nette\Mail\Message;
		$mail->setHtmlBody($html);
		// ...
		return $mail;
	}
}

În șablon, creăm apoi linkurile așa cum suntem obișnuiți. Toate linkurile create prin LinkGenerator vor fi absolute.

<a n:href="Presenter:action">Link</a>

Trimiterea e-mailului

Mailer este clasa care asigură trimiterea e-mailurilor. Implementează interfața Nette\Mail\Mailer și sunt disponibili mai mulți maileri predefiniți, pe care îi vom prezenta.

Framework-ul adaugă automat în containerul DI un serviciu de tip Nette\Mail\Mailer construit pe baza configurării, la care puteți ajunge solicitându-l prin injecția de dependențe.

SendmailMailer

Mailerul implicit este SendmailMailer, care utilizează funcția PHP mail. Exemplu de utilizare:

$mailer = new Nette\Mail\SendmailMailer;
$mailer->send($mail);

Dacă doriți să setați returnPath și serverul îl suprascrie constant, utilizați $mailer->commandArgs = '-fMuj@email.cz'.

SmtpMailer

Pentru a trimite e-mailuri prin serverul SMTP, se utilizează SmtpMailer.

$mailer = new Nette\Mail\SmtpMailer(
	host: 'smtp.gmail.com',
	username: 'franta@gmail.com',
	password: '*****',
	encryption: 'ssl',
);
$mailer->send($mail);

Constructorului i se pot transmite acești parametri suplimentari:

  • port – dacă nu este setat, se utilizează implicit 25 sau 465 pentru ssl
  • timeout – timeout pentru conexiunea SMTP
  • persistent – utilizează conexiune persistentă
  • clientHost – setarea antetului Host al clientului
  • streamOptions – permite setarea SSL context options pentru conexiune

FallbackMailer

Nu trimite e-mailuri direct, ci mediază trimiterea printr-un set de maileri. În cazul în care un mailer eșuează, repetă încercarea cu următorul. Dacă și ultimul eșuează, începe din nou de la primul.

$mailer = new Nette\Mail\FallbackMailer([
	$smtpMailer,
	$backupSmtpMailer,
	$sendmailMailer,
]);
$mailer->send($mail);

Ca parametri suplimentari în constructor, putem specifica numărul de repetări și timpul de așteptare în milisecunde.

DKIM

DKIM (DomainKeys Identified Mail) este o tehnologie pentru creșterea credibilității e-mailurilor, care ajută și la detectarea mesajelor falsificate. Mesajul trimis este semnat cu cheia privată a domeniului expeditorului, iar această semnătură este stocată în antetul e-mailului. Serverul destinatarului compară această semnătură cu cheia publică stocată în înregistrările DNS ale domeniului. Faptul că semnătura corespunde demonstrează că e-mailul provine într-adevăr din domeniul expeditorului și că nu a fost modificat în timpul transmiterii mesajului.

Puteți seta semnarea e-mailurilor pentru mailer direct în configurație. Dacă nu utilizați injecția de dependențe, se utilizează în acest mod:

$signer = new Nette\Mail\DkimSigner(
	domain: 'nette.org',
	selector: 'dkim',
	privateKey: file_get_contents('../dkim/dkim.key'),
	passPhrase: '****',
);

$mailer = new Nette\Mail\SendmailMailer; // sau SmtpMailer
$mailer->setSigner($signer);
$mailer->send($mail);

Configurație

Prezentare generală a opțiunilor de configurare pentru Nette Mail. Dacă nu utilizați întregul framework, ci doar această bibliotecă, citiți cum să încărcați configurația.

Pentru trimiterea e-mailurilor se utilizează în mod standard mailerul Nette\Mail\SendmailMailer, care nu se configurează ulterior. Cu toate acestea, îl putem comuta la Nette\Mail\SmtpMailer:

mail:
	# utilizează SmtpMailer
	smtp: true       # (bool) implicit este false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) implicit este null (are alias 'secure')
	clientHost: ...  # (string) implicit este $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) implicit este false

	# context pentru conectarea la serverul SMTP, implicit este stream_context_get_default()
	context:
		ssl:         # prezentare generală a opțiunilor la https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # prezentare generală a opțiunilor la https://www.php.net/manual/en/context.http.php
			header: ...
			...

Folosind opțiunea context › ssl › verify_peer: false, puteți dezactiva verificarea certificatelor SSL. Nu recomandăm insistent să faceți acest lucru, deoarece aplicația va deveni vulnerabilă. În schimb, adăugați certificatele în depozit.

Pentru a crește credibilitatea, putem semna e-mailurile folosind tehnologia DKIM:

mail:
	dkim:
		domain: myweb.com
		selector: lovenette
		privateKey: %appDir%/cert/dkim.priv
		passPhrase: ...

Servicii DI

Aceste servicii sunt adăugate în containerul DI:

Nume Tip Descriere
mail.mailer Nette\Mail\Mailer clasa care trimite e-mailuri
mail.signer Nette\Mail\Signer semnătură DKIM
versiune: 4.0