Mail

Envío de
Correos electrónicos

Envío de correos electrónicos

¿Va a enviar correos electrónicos, como boletines o confirmaciones de pedidos? Nette Framework proporciona las herramientas necesarias con una API muy agradable. Le mostraremos:

  • cómo crear un correo electrónico, incluidos los archivos adjuntos
  • cómo enviarlo
  • cómo combinar correos electrónicos y plantillas

Instalación

Descargue e instale la biblioteca usando Composer:

composer require nette/mail

Creación de un correo electrónico

El correo electrónico es un objeto de la clase Nette\Mail\Message. Lo creamos así:

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Confirmación de pedido')
	->setBody("Hola,\nsu pedido ha sido recibido.");

Todos los parámetros especificados deben estar en UTF-8.

Además de especificar el destinatario con el método addTo(), también puede especificar el destinatario de la copia addCc() o el destinatario de la copia oculta addBcc(). En todos estos métodos, incluido setFrom(), podemos escribir la dirección de tres maneras:

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

El cuerpo del correo electrónico escrito en HTML se pasa usando el método setHtmlBody():

$mail->setHtmlBody('<p>Hola,</p><p>su pedido ha sido recibido.</p>');

No necesita crear la alternativa de texto, Nette la generará automáticamente por usted. Y si el correo electrónico no tiene un asunto establecido, intentará tomarlo del elemento <title>.

También es extraordinariamente fácil insertar imágenes en el cuerpo HTML. Simplemente pase la ruta donde se encuentran físicamente las imágenes como segundo parámetro, y Nette las incluirá automáticamente en el correo electrónico:

// agrega automáticamente /path/to/images/background.gif al correo electrónico
$mail->setHtmlBody(
	'<b>Hola</b> <img src="background.gif">',
	'/path/to/images',
);

El algoritmo que inserta imágenes busca estos patrones: <img src=...>, <body background=...>, url(...) dentro del atributo HTML style y la sintaxis especial [[...]].

¿Puede ser aún más fácil enviar correos electrónicos?

Un correo electrónico es como una postal. Nunca envíe contraseñas u otras credenciales por correo electrónico.

Adjuntos

Por supuesto, se pueden adjuntar archivos al correo electrónico. El método addAttachment(string $file, ?string $content = null, ?string $contentType = null) se utiliza para esto.

// inserta el archivo /path/to/example.zip en el correo electrónico con el nombre example.zip
$mail->addAttachment('/path/to/example.zip');

// inserta el archivo /path/to/example.zip en el correo electrónico llamado info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// inserta el archivo example.txt en el correo electrónico con el contenido "Hola John!"
$mail->addAttachment('example.txt', 'Hola John!');

Plantillas

Si envía correos electrónicos HTML, es natural escribirlos en el sistema de plantillas Latte. ¿Cómo hacerlo?

$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',
	);

Archivo email.latte:

<html>
<head>
	<meta charset="utf-8">
	<title>Confirmación de pedido</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Hola,</p>

	<p>Su pedido número {$orderId} ha sido recibido.</p>
</body>
</html>

Nette inserta automáticamente todas las imágenes, establece el asunto según el elemento <title> y genera una alternativa de texto al HTML.

Uso en Nette Application

Si utiliza correos electrónicos junto con Nette Application, es decir, con presenters, es posible que desee crear enlaces en las plantillas utilizando el atributo n:href o la etiqueta {link}. Latte no los conoce de forma nativa, pero es muy fácil agregarlos. El objeto Nette\Application\LinkGenerator puede crear enlaces, y puede obtenerlo pidiéndolo mediante inyección de dependencias:

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;
	}
}

En la plantilla, creamos enlaces como estamos acostumbrados. Todos los enlaces creados a través de LinkGenerator serán absolutos.

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

Envío de un correo electrónico

Mailer es una clase que se encarga de enviar correos electrónicos. Implementa la interfaz Nette\Mail\Mailer y hay varios mailers predefinidos disponibles, que presentaremos.

El framework agrega automáticamente un servicio de tipo Nette\Mail\Mailer al contenedor DI basado en la configuración, al que puede acceder pidiéndolo mediante inyección de dependencias.

SendmailMailer

El mailer predeterminado es SendmailMailer, que utiliza la función PHP mail. Ejemplo de uso:

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

Si desea establecer returnPath y su servidor sigue sobrescribiéndolo, use $mailer->commandArgs = '-fMuj@email.cz'.

SmtpMailer

Para enviar correo a través de un servidor SMTP, se utiliza SmtpMailer.

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

Se pueden pasar los siguientes parámetros adicionales al constructor:

  • port – si no se establece, se utiliza el predeterminado 25 o 465 para ssl
  • timeout – tiempo de espera para la conexión SMTP
  • persistent – usar conexión persistente
  • clientHost – establecer la cabecera Host del cliente
  • streamOptions – permite establecer opciones de contexto SSL para la conexión

FallbackMailer

No envía correos electrónicos directamente, sino que media el envío a través de un conjunto de mailers. Si un mailer falla, repite el intento con el siguiente. Si el último también falla, comienza de nuevo desde el primero.

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

Como parámetros adicionales en el constructor, podemos especificar el número de reintentos y el tiempo de espera en milisegundos.

DKIM

DKIM (DomainKeys Identified Mail) es una tecnología para aumentar la confiabilidad de los correos electrónicos, que también ayuda a detectar mensajes falsificados. El mensaje enviado se firma con la clave privada del dominio del remitente y esta firma se almacena en la cabecera del correo electrónico. El servidor del destinatario compara esta firma con la clave pública almacenada en los registros DNS del dominio. Si la firma coincide, se demuestra que el correo electrónico realmente proviene del dominio del remitente y que no se modificó durante la transmisión del mensaje.

Puede configurar la firma de correos electrónicos para el mailer directamente en la configuración. Si no utiliza la inyección de dependencias, se utiliza de esta manera:

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

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

Configuración

Resumen de las opciones de configuración para Nette Mail. Si no utiliza todo el framework, sino solo esta biblioteca, lea cómo cargar la configuración.

Para enviar correos electrónicos, se utiliza de forma predeterminada el mailer Nette\Mail\SendmailMailer, que no se configura más. Sin embargo, podemos cambiarlo a Nette\Mail\SmtpMailer:

mail:
	# usa SmtpMailer
	smtp: true       # (bool) predeterminado es false

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

	# contexto para la conexión al servidor SMTP, predeterminado es stream_context_get_default()
	context:
		ssl:         # resumen de opciones en https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # resumen de opciones en https://www.php.net/manual/en/context.http.php
			header: ...
			...

Con la opción context › ssl › verify_peer: false, puede desactivar la verificación de certificados SSL. Desaconsejamos encarecidamente hacer esto, ya que la aplicación se volverá vulnerable. En su lugar, agregue los certificados al almacén.

Para aumentar la confiabilidad, podemos firmar los correos electrónicos utilizando la tecnología DKIM:

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

Servicios DI

Estos servicios se agregan al contenedor DI:

Nombre Tipo Descripción
mail.mailer Nette\Mail\Mailer clase que envía correos electrónicos
mail.signer Nette\Mail\Signer firma DKIM
versión: 4.0