Odesílání emailů na localhostu i na produkci

Odesílání emailů bývá často nezbytnou součástí webové aplikace. V tomto tutoriálu si ukážeme, jak si vytvořit jednoduchou emailovou šablonu a poté email odeslat, ať už na localhostu pomocí Mailtrapu nebo i na produkci na Gmail nebo Seznam.

Vytvoření emailové šablony

Jako příklad si dáme odeslání emailu po dokončení registrace. Začneme vytvořením nového projektu:

laravel new mail-demo

Laravel nabízí jednoduché API knihovny SwiftMailer, která umožňuje využívat SMTP, Mailgun, SparkPost či Amazon SES a snadno odesílat emaily z localhostu nebo pomocí cloudu. Každý typ emailu odeslán v Laravel aplikaci je reprezentován jako "mailable" třída. Tyto třídy pak najdeme v adresáři app/Mail, který defaultně není vytvořený a musíme ho ručně vytvořit nebo se nám automaticky vytvoří společně s naší novou třídou, kterou si vygenerujeme pomocí příkazu:

php artisan make:mail RegistrationComplete

Tím se nám vytvořila nová třída app/Mail/RegistrationComplete.php, kterou si upravíme následně:

<?php

namespace App\Mail;

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

class RegistrationComplete extends Mailable
{
    use Queueable, SerializesModels;
    
    /**
     * @var User
     */
    protected $user;

    /**
     * Create a new message instance.
     *
     * @param User $user
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->from('nas@email.cz')
            ->view('emails.registration-complete')
            ->with(['user' => $this->user]);
    }
}

Samotný kód by měl být "self-explaining", nicméně ho trochu popíšu. Nejdůležitější z celé třídy je to, že dědí ze třídy Illuminate\Mail\Mailable, která obsahuje celou logiku pro odesílání emailu a nabízí nám mnoho metod, které můžeme využít. Protože budeme odesílat email po dokončení registrace, tak si přes konstruktor předáme našeho nového uživatele, protože budeme potřebovat jak jeho email kam to poslat, tak také využijeme jeho data v emailové šabloně. Další důležitou částí je metoda build(), která se automaticky zavolá při odeslání emailu. V této metodě si nastavíme jaký bude odchozí email, jaká šablona se má vygenerovat a jako data ji předáme našeho nového uživatele.

Dalším krokem bude vytvoření emailové šablony. Ve třídě RegistrationComplete jsme volali metodu view('emails.registration-complete'), takže je potřeba vytvořit nový blade resources/views/emails/registration-complete.blade.php. Šablona se chová jako klasický blade pohled, takže je možné si ji upravit podle potřeb včetně CSS, nicméně je stále potřeba myslet na to, že se jedná o emailovou šablonu a tudíž ho musí poštovní klienti podporovat. V našem případě budeme minimalisti a obsah bude velmi stručný:

Děkujeme, registrace uživatele {{ $user->name }} byla úspěšně dokončena.

Routa a controller

Mailable třídu a šablonu máme připravenou. Dalším postupem bude vytvořit si routu, která po zavolání odešle email. Jedná se o zjednodušení příkladu, v reálu samozřejmě žádná routa není potřeba, ale email by se měl odeslat hned po dokončení procesu s registrací (nejlépe pak ho přiřadit do jobu, aby uživatel nemusel čekat, až se email skutečně odešle). Upravíme si tedy soubor routes/web.php aby se nám hned při načtení úvodní stránky odeslal email:

<?php

use App\Http\Controllers\RegistrationController;
use Illuminate\Routing\Router;

/** @var Router $router */
$router->get('/', [RegistrationController::class, 'sendEmail']);

Společně s tímto si hned vytvoříme nový controller:

php artisan make:controller RegistrationController

který si upravíme takto:

<?php

namespace App\Http\Controllers;

use App\Mail\RegistrationComplete;
use App\User;
use Illuminate\Support\Facades\Mail;

class RegistrationController extends Controller
{
    public function sendEmail(): void 
    {
    	$user = new User(['name' => 'John Doe', 'email' => 'john@doe.com']);
    	
    	Mail::to($user->email)->send(new RegistrationComplete($user));
    }
}

Přes routu si tedy zavoláme metodu sendEmail() ve třídě RegistrationController, kde si vytvoříme nového uživatele. Dále si přes fasádu zavoláme metodu to(), kde si vložíme adresu, na kterou chceme poslat email a pomocí metody send() si odešleme samotný email, kdy jako první parametr využijeme novou instanci naší mailable třídy společně s novým uživatelem. Jak už jsem psal dříve, v mailable třídě se pak automaticky zavolá metoda build().

Testovací email z localhostu

Když vyvíjíme aplikaci, často potřebujeme i testovací smtp server pro vyzkoušení jak funkcionality, tak třeba i vzhledu emailu, který zákazník obdrží. Existuje řada služeb, která toto poskytují, nicméně v tomto článku se zaměříme na službu Mailtrap, která nabízí velmi jednoduchou implementaci. Mailtrap nabízí zdarma plán, který zahrnuje 500 emailů za měsíc a jednu schránku o velikosti 5 MB. Není to moc, ale pro testovací účely to často vystačí. Aby jste službu mohli používat, tak se musíte na jejich stránkách registrovat. Poté se vám vytvoří demo schránka, kterou můžete využívat: Mailtrap

Jakmile se dostanete do schránky, tak jako první se vám nabízí SMTP údaje, které pro implementaci potřebujete. Protože se Mailtrap často používá s Laravelem, tak služba již nabízí vygenerované hodnoty pro .env. Stačí tedy pod sekcí Integrations vybrat Laravel a vygenerové hodnoty zkopírovat do souboru .env, například:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=2e6bee500atd11
MAIL_PASSWORD=n8u6tb02f93409
MAIL_FROM_ADDRESS=from@example.com
MAIL_FROM_NAME=Example

A tím máme prakticky vše připraveno. Protože jsme upravili konfigurační soubor, tak si jen ještě pro jistotu pročistíme cache:

php artisan cache:clear

Nyní můžeme znovu provolat naši routu a v Mailtrapu by se nám měl náš email zobrazit. Přijatý email v Mailtrapu

Odesílání z Gmailu

Odesílání pomocí Gmailu je poměrně jednoduché. V souboru .env si upravíme SMTP údaje:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.googlemail.com
MAIL_PORT=465
MAIL_USERNAME=VASE_GMAIL_ADRESA
MAIL_PASSWORD=VAS_GMAIL_HESLO
MAIL_ENCRYPTION=ssl

Dále je potřeba si správně nastavit Google účet. Přihlašte se do Gmailu, v pravo nahoře klikněte na svůj účet a dejte Manage your Google Account (Spravovat účet Google): Správa Google účtu

V Google účtu vyberte Zabezpečení a zapněte přístup pro méně zabezpečené aplikace: Google účet

Poté je konfigurace kompletní a můžete využívat odesílání emailu z Gmailu.

Odesílání ze Seznamu

Odesílání z účtu na Seznamu je velmi jednoduché, stačí SMTP údaje v .env upravit takto:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.seznam.cz
MAIL_PORT=465
MAIL_USERNAME=VAS_SEZNAM_EMAIL
MAIL_PASSWORD=VASE_SEZNAM_HESLO
MAIL_ENCRYPTION=ssl

Žádné další nastavení není potřeba nastavovat.

Dokumentace

Laravel nabízí více než jen jednoduché odesílání emailu. Je možné využít další emailové poskytovatele jako jsou Mailgun, Postmark nebo Amazon SES. Je možné přikládat přílohy, využít markdownu, posílat emaily do jobu či si nastavit lokalizaci jazyka. To vše najdete v oficiální dokumentaci Laravelu.