Tutorial
Enviar e-mails com Laravel
Envie os e-mails do Laravel pelo Emailit com o transporte de e-mail e a facade do emailit/emailit-laravel, ou com SMTP simples, e verifique os webhooks do Emailit.
Este guia mostra duas formas de enviar os e-mails do Laravel pelo Emailit: o pacote emailit/emailit-laravel, que adiciona um transporte de e-mail emailit e uma facade Emailit, e o SMTP simples com o mailer nativo do Laravel. Ele termina com uma rota de webhook que verifica as assinaturas.
Pré-requisitos
- PHP 8.1 ou mais recente e Laravel 10, 11 ou 12.
- Um domínio de envio verificado, por exemplo,
acme.com. - Uma chave de API. Uma chave Sending Only restrita ao seu domínio é suficiente.
- Até o seu workspace ter acesso de produção, você só pode enviar para os e-mails das contas dos membros do workspace.
Opção 1: o pacote Laravel do Emailit
O pacote envia as suas Mailables, Markdown mailables, notificações e e-mails em fila existentes pela API do Emailit, sem alterações no seu código de e-mail.
Instalar o pacote
composer require emailit/emailit-laravelO service provider é descoberto automaticamente.
Configurar o transporte
Adicione a sua chave e defina o Emailit como mailer padrão no .env:
EMAILIT_API_KEY=secret_••••••••••••••••••••••••••••••••
MAIL_MAILER=emailit
MAIL_FROM_ADDRESS=hello@acme.com
MAIL_FROM_NAME="Acme"Registre o mailer em config/mail.php:
'mailers' => [
// ...
'emailit' => [
'transport' => 'emailit',
],
],MAIL_FROM_ADDRESS deve estar em um domínio de envio verificado. Para alterar a URL base da API, publique o arquivo de configuração com php artisan vendor:publish --tag=emailit-config; isso não é necessário no uso normal.
Enviar uma Mailable
Crie uma Mailable como de costume:
php artisan make:mail WelcomeEmailnamespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class WelcomeEmail extends Mailable
{
use Queueable, SerializesModels;
public function __construct(public User $user) {}
public function envelope(): Envelope
{
return new Envelope(subject: 'Welcome to Acme');
}
public function content(): Content
{
return new Content(view: 'emails.welcome');
}
}Envie-a ou coloque-a na fila para que a requisição não espere pela API:
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
Mail::to($user)->send(new WelcomeEmail($user));
Mail::to($user)->queue(new WelcomeEmail($user));Usar a facade para recursos da API
A facade Emailit expõe o SDK de PHP completo, para recursos que o mailer do Laravel não modela, como templates salvos e envios agendados:
use Emailit\Laravel\Facades\Emailit;
$email = Emailit::emails()->send([
'from' => 'Acme <hello@acme.com>',
'to' => $user->email,
'template' => 'welcome',
'variables' => ['first_name' => $user->first_name],
'scheduled_at' => 'tomorrow at 9am',
]);
$email->id; // em_…A facade também cobre domínios, contatos, listas de contatos, supressões, webhooks e os outros recursos. Se você preferir injeção de dependência, declare o tipo Emailit\EmailitClient em um controller ou job, e o Laravel o resolve com a chave configurada.
Capture as exceções tipadas para tratar as falhas:
use Emailit\Exceptions\ApiErrorException;
use Emailit\Exceptions\RateLimitException;
try {
Emailit::emails()->send($payload);
} catch (RateLimitException $e) {
// 429: release the job back to the queue and try again later
} catch (ApiErrorException $e) {
report($e); // $e->getHttpStatus() has the status code
}Opção 2: SMTP simples
Se você preferir não adicionar um pacote, aponte o mailer SMTP do Laravel para o relay do Emailit:
MAIL_MAILER=smtp
MAIL_HOST=smtp.emailit.com
MAIL_PORT=587
MAIL_USERNAME=emailit
MAIL_PASSWORD=secret_••••••••••••••••••••••••••••••••
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=hello@acme.com
MAIL_FROM_NAME="Acme"Na porta 587, o mailer do Laravel ativa o STARTTLS na conexão. Os arquivos config/mail.php mais antigos leem MAIL_ENCRYPTION, e os mais novos o ignoram, então é seguro mantê-lo. Para TLS implícito, use a porta 465; se o seu host bloquear a 587, use 2525 ou 2587. Mailables, notificações e filas funcionam exatamente como com o pacote. Consulte Configurações de SMTP.
Pelo SMTP, não é possível usar templates salvos nem scheduled_at; use a facade ou a API para isso.
Receber webhooks
Crie um webhook que aponte para https://your-app.com/webhooks/emailit e depois guarde o segredo de assinatura dele:
EMAILIT_WEBHOOK_SECRET=whsec_••••••••'emailit' => [
'webhook_secret' => env('EMAILIT_WEBHOOK_SECRET'),
],Adicione um controller que confira a assinatura com base no corpo bruto:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class EmailitWebhookController extends Controller
{
public function __invoke(Request $request)
{
$payload = $request->getContent();
$signature = (string) $request->header('X-Emailit-Signature');
$timestamp = (string) $request->header('X-Emailit-Timestamp');
$expected = hash_hmac('sha256', $timestamp.'.'.$payload, config('services.emailit.webhook_secret'));
if (abs(time() - (int) $timestamp) > 300 || ! hash_equals($expected, $signature)) {
abort(401, 'Invalid signature');
}
// The body is a JSON array of up to 100 events.
foreach (json_decode($payload, true) as $event) {
match ($event['type']) {
'email.bounced', 'email.complained' => $this->stopEmailing($event['data']['object']['to']),
default => null,
};
}
return response()->noContent();
}
private function stopEmailing(string $address): void
{
// Mark the address as undeliverable in your database.
}
}Registre a rota e exclua-a da proteção contra CSRF, porque o Emailit não consegue enviar um token CSRF:
use App\Http\Controllers\EmailitWebhookController;
Route::post('/webhooks/emailit', EmailitWebhookController::class);->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: ['webhooks/emailit']);
})No Laravel 10, adicione 'webhooks/emailit' ao array $except em app/Http/Middleware/VerifyCsrfToken.php. Retorne um 2xx em até 30 segundos e envie o trabalho demorado para uma fila. Consulte Assinatura das requisições.
Dicas para produção
- Coloque os e-mails na fila. Use
queue()ouShouldQueuepara que as requisições web não esperem pelo e-mail e limite o ritmo dos jobs em massa (por exemplo, comRedis::throttle) para ficar dentro dos seus limites de envio. Por padrão, os workspaces novos podem enviar 2 e-mails por segundo. - Use o cache de configuração com segurança. Depois de
php artisan config:cache,env()só funciona dentro dos arquivos de configuração. Leia a chave pela configuração, como o pacote faz. - Use uma chave dedicada. Dê a cada aplicação e ambiente a sua própria chave Sending Only para poder fazer a rotação de uma sem mexer nas outras. Consulte Chaves de API.
- Elimine webhooks duplicados. Guarde cada
event_idque você processa e ignore as repetições, porque as entregas com falha recebem novas tentativas.