Laravel Cafè #3 – Creazione ed Invio di Mail

0
924


Benvenuto al Laravel Cafè! Ogni settimana proporremo un nuovo argomento sul mondo Laravel, quindi trova un posto libero, prendi un caffè e condividi le tue opinioni con la comunità! L’idea è di creare un punto di discussione. Se hai qualche perplessità sull’argomento trattato, leggi fino alla fine e fai una domanda usando il forum! Cercheremo di risponderci a vicenda e di aiutarci, ed il confronto ci farà crescere tutti un po’ di più.

Di mercoledì in mercoledì parleremo di qualcosa di diverso, quindi tornaci a trovare! Potresti dare una mano a qualcuno in difficoltà, o ricevere tu un aiuto in caso di problemi! Dai, siediti, il primo caffè lo offriamo noi.

L’Argomento

Nel mondo del web 2.0 l’invio di mail automatizzate è parte integrante della maggioranza delle applicazioni. L’esempio più semplice è la mail di conferma che ci arriva dopo aver effettuato la registrazione ad un portale web, un forum, o a un social network, che viene inviata automaticamente dall’applicativo. Oggi, per la nostra abituale pausa caffè del mercoledì, vediamo come implementare questo servizio su Laravel 5.3.

N.B.: Laravel 5.3 ha diverse novità rispetto ai suoi predecessori e alcune di queste riguardano proprio le API per le mail, ma il codice che vi propongo è tranquillamente adattabile alle versioni antecedenti con un controller apposito.

Il Codice

Tralascerò la parte di configurazione del servizio (e vi rimando direttamente alla documentazione ufficiale) dato che può variare a seconda delle necessità del developer. Come di consueto vi propongo prima di tutto la struttura del filesystem:

app/
|-- Http/Controllers
|-- MailController.php     <-- Controller per l'invio delle mail
 |-- Mail/                      <-- Cartella base dei modelli "mailable" https://laravel.com/docs/5.3/mail#generating-mailables
     |-- Contact.php            <-- Classe che si occupa del build della mail di richiesta informazioni
resources/views/                <-- Cartella viste
     |-- emails                 <-- Cartella omissibile
         |-- contact.blade.php  <-- View che fa da template per mail richiesta informazioni

Utilizzando il comando php artisan make:mail Contact Laravel ci aiuta ad automatizzare la creazione della classe che rappresenta in modo astratto quanto l’utente fanale riceverà nella propria casella di posta. A mio avviso se automatizzasse anche la creazione della vista base non sarebbe male, ma potrebbe essere uno spunto per qualche plugin o una futura feature di Laravel.

Dopo aver lanciato il comando precedentemente descritto, il risultato sarà la creazione di un’estensione della classe IlluminateMailMailable e contenente il metodo build() che ci permette di impostare sia tutte le informazioni riguardanti mittenti e destinatari, la vista da utilizzare come template ed eventualmente implementare anche code di invio.

Contact.php

namespace AppMail;

use IlluminateBusQueueable;
use IlluminateMailMailable;
use IlluminateQueueSerializesModels;
use IlluminateContractsQueueShouldQueue;

class Contact extends Mailable
{

    use Queueable,
        SerializesModels;

    /**
     * Array with sender informations.
     * [ 'name' => 'John', 'mail' => 'john@doe.com' ]
*
* @var array
*/
private $sender;

/**
* Collection with recipients informations.
* Collection: [
*      [ 'name' => 'stewie', 'mail' => 'stewie@griffin.com' ]
*      [ 'name' => 'Peter', 'mail' => 'peter@griffin.com' ]
*      [ 'name' => 'Lois', 'mail' => 'lois@griffin.com' ]
*      [ 'name' => 'Chris', 'mail' => 'chris@griffin.com' ]
*      [ 'name' => 'Brian', 'mail' => 'brian@griffin.com' ]
*    // No one care about Meg
* ]
* @var Collection
*/
private $recipients;

/**
* Mail view template.
*
* @var String
*/
private $template;

/**
* Collection with other attributes for the view.
*
* @var mixex
*/
public $attributes;

/**
* Create a new message instance.
*
* @return void
*/
public function __construct($sender, $recipients, $template, $attributes)
{
$this->sender = $sender;
$this->email = $recipients;
$this->template = $template;
$this->attributes = $attributes;
}

/**
* Build the message.
*
* @return $this
*/
public function build()
{
// Senders addresses
$this->from($this->sender['name'], $this->sender['mail']);

// Recipients addresses
foreach($recipients as $recipient) {
$this->to($recipient['name'], $recipient['mail']);
}

// Subject
$this->subject("Richiesta informazioni");

// Return view
return $this->view($this->template);
}

}

Come potete vedere la classe contiene tre variabili private ($sender, $recipients, $template) e una variabile pubblica $attributes. Le classi Mailable hanno questa caratteristica (vedi la documentazione.

any public property defined on your mailable class will automatically be made available to the view.

Tradotto:

qualsiasi proprietà pubblica definita nella tua classe verrà resa automaticamente disponibile alla view.

Quindi, nella view descritta di seguito, avrò a disposizione un array $attributes che conterrà tutte le variabili dinamiche da passare ad un determinato template, a differenza delle variabili $sender, $recipients, $template, utilizzate solo per impostare la testata della mail. Ovviamente dato che de gustibus non est disputandum, se avete suggerimenti o volete aggiungere la vostra implementazione della classe, vi invito a continuare la discussione!

contact.blade.php




<meta charset=""UTF-8""> <h4>Nuova richiesta informazioni da parte di {{ $attributes['name'] }}</h4> {{ $attributes['name'] }} ti ha invito il seguente messaggio: {{ {{ $attributes['message'] }} }} <h4>Ulteriori informazioni:</h4> <ul> @foreach($attributes['infos'] as $key => $info) <li><strong>{{ $key }}:</strong> {{ $info }}</li> @endforeach</ul>

Il Test

La pausa caffè sta per terminare, quindi verifichiamo che tutto funzioni creando un piccolo controller, richiamato, ad esempio, da un form di richiesta informazioni.

namespace AppHttpControllers;

use IlluminateHttpRequest;
use AppHttpRequests;
use Mail;
use Collection;
use AppMailContact;

class MailController extends Controller
{

public function contact(Request $request)
{
// validation and other stuff...
[...]

// sender
$sender = [ 'name' => $request->name, 'mail' => $request->mail ];

// recipients
$recipients = new Collection;
$recipients->push(['name' => 'Laravel Italia', 'mail' => 'info@laravel-italia.it']);

// attributes
$attributes = [
'name' => $request->name,
'message' => $request->message,
'infos' => [
'telefono' => $request->phone,
'indirizzo' => $request->address,
// [...]
]
];

Mail::send(new Contact($sender, $recipients, 'mail.contact', $attributes));

// return result
[...]
}

}

Questo controller si occuperà di inviare la mail, richiamando il metodo build() della classe Contact, il risultato? Beh guardate la casella di posta per scoprirlo!

… ed ora?

Cosa ne pensate di queste feature? Implementate anche voi le classi Mailable o lavorate in maniera differente?

In questo articolo ho tralasciato la parte di configurazione dei vari driver mail, l’aggiunta di allegati e l’invio tramite una coda. Se volete avere maggiori informazioni riguardo questi argomenti, vi invito a continuare la discussione in tutti i canali di Laravel Italia così da riuscire rendere più completo l’esempio proposto!

Fateci sapere cosa ne pensate, e non dimenticate che c’è sempre il nostro bellissimo Slack, pieno di gente che discute del framework più bello del mondo!