Postmark es una plataforma de envío de emails transaccionales que cuenta con una API muy fácil de implementar, especialmente si trabajas con Laravel. En este post veremos cómo implementar este servicio a nuestras aplicaciones de Laravel utiilzando Mailbles y aplicando Test Driven Development.

Importante antes de continuar: para poder usar Postmark es requerido poseer una dirección de email bajo un dominio privado [email protected], cuentas de correo de gmail, hotmail, etc. no son permitidas con postmark.

Registro en Postmark

Lo primero que tienes que hacer es crear tu cuenta de usuario en https://postmarkapp.com. Una vez que hayas creado y confirmado tu cuenta podrás configurar un nuevo «servidor» de emails para tu aplicación.

Aquí vas a usar el dominio de tu aplicación, si estas usando, recuerda que siempre es recomendable crear un hostname para tus proyectos locales. Para este proyecto estoy usando «laravel-project.dev».

Luego de hacer click en el botón «Create Server» puedes ver el API KEY que se ha generado, más adelante usaremos este dato para configurar Postmark en Laravel.

Antes de continuar, hay un último paso que debes realizar y se trata de configurar tus «Sender Signatures», de esta manera Postmark verifica que la cuenta de correo que intenta enviar un email utilizando el API KEY especificado, tenga los permisos necesarios para hacerlo.

Para crear una nueva firma puedes hacer click en el botón «Add Sender Signature» y completar los campos requeridos

Si todo va bien hasta ahora, debes haber recibido un correo electrónico similar a este

Envio de Emails en Laravel

Lo primero que debemos hacer es agregar el token generado por Postmark para el servidor que creamos (laravel-project.dev en mi caso) en el archivo .env del proyecto de la siguiente manera:

MAIL_HOST=smtp.postmarkapp.com
MAIL_USERNAME=postmark_token_value
MAIL_PASSWORD=postmark_token_value

Debes cambiar también el MAIL_HOST usando el valor descrito anteriormente.

De igual forma, puedes especificar la cuenta de correo y el nombre que verán los usuarios que reciban los emails enviados por la aplicación

[email protected]
MAIL_FROM_NAME="your name"

Usando TDD

Ya tenemos toda la configuración necesaria para comenzar con el desarrollo. Podemos iniciar creando una nueva clase de prueba para verificar el envío de correos.

<?php

namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Mail;

use App\Mail\UserCreated;

class EmailTest extends TestCase
{

    use DatabaseMigrations;
    use DatabaseTransactions;

    /** @test */
    public function send_email_after_registration()
    {
        $this->withoutMiddleware();

        $user = factory(\App\User::class)->create([
            'email' => '[email protected]',
            'name'  => 'jeff'
        ]);

        Mail::to($user)->send(new UserCreated($user));

    }
}

Cambia la dirección de correo de la prueba ([email protected]) por un email real para que verifiques que todo funciona al 100%.

Si ejecutas las pruebas desde la consola, por supuesto van  a fallar debido a que no hemos creado el Mailable «UserCreated«. Para generar un nuevo Mailable ejecutamos desde la consola

Creando un nuevo Mailable

En Laravel 5.3 fueron presentados los Mailables como una forma mucho más clara de manejar el envío de emails en el framework.

$ php artisan make:mail UserCreated

Para más información visita este post sobre Enviar emails con Mailables en Laravel 5.3.

Podemos editar el Mailable UserCreated de la siguiente manera:

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;

class UserCreated extends Mailable
{
    use Queueable, SerializesModels;

    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function build()
    {
        return $this->markdown('emails.welcome')
            ->with(['name' => $this->user->email]);
    }
}

En Laravel 5.4 existe soporte para emails con markdown, para más información visita este post sobre  Uso de Markdown en los Mailables en Laravel 5.4.

Ahora escribimos la vista welcome.blade.php dentro de resources/views/emails:

@component('mail::message')
# Welcome {{ $name }}

This is a welcome email!

Thanks,<br>
{{ config('app.name') }}
@endcomponent

Probando el envío de emails con Postmark

Nuevamente ejecutamos las pruebas desde la consola:

$ vendor/bin/phpunit --filter=EmailTest

En este punto, el resultado debería ser algo similar a esto:

PHPUnit 5.7.8 by Sebastian Bergmann and contributors.

.                                        1 / 1 (100%)

Time: 3.34 seconds, Memory: 16.00MB

OK (1 test, 0 assertions)

Y si revisas tu bandeja de entrada en tu cuenta de email podrás ver algo similar a esto:

Refactorizando los Tests

En primer lugar, las pruebas están siendo ejecutadas correctamente, pero no tenemos ningún método de aserción que nos permita saber si el email se está enviando, por ahora solo estamos ejecutando el código necesario para enviar el email y por otro lado, no es muy conveniente realizar envío de correos durante las prueba, veamos cómo podemos «simular» esto:

Editamos el archivo EmailTest de la siguiente manera

public function send_email_after_registration()
    {
        $this->withoutMiddleware();
        Mail::fake();

        $user = factory(\App\User::class)->create([
            'email' => '[email protected]',
            'name'  => 'jeff'
        ]);

        Mail::to($user)->send(new UserCreated($user));

        Mail::assertSent(UserCreated::class, function ($mail) use ($user) {
            return $mail->user->email === $user['email'];
        });
    }

El método Mail::fake() simula el comportamiento real de «Mail» pero sin ejecutar concretamente el envío.

Ejecutando nuevamente las pruebas:

$ vendor/bin/phpunit --filter=EmailTest

PHPUnit 5.7.8 by Sebastian Bergmann and contributors.

...                                      3 / 3 (100%)

Time: 1.08 seconds, Memory: 14.00MB

OK (3 tests, 3 assertions)

Aprende más sobre desarrollo orientado a pruebas en nuestro curso Crea una aplicación con Laravel.

Envío de emails

Finalmente podemos usar el siguiente código donde sea requerido el envío de este email a través del mailable UserCreated enviando una instancia de App\User.php como parámetro:

Mail::to($user)->send(new UserCreated($user));

Material relacionado

Únete a nuestra comunidad en Discord y comparte con los usuarios y autores de Styde, 100% gratis.

Únete hoy

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.