Tutorial
E-Mails mit Laravel senden
Senden Sie Laravel-E-Mails über Emailit mit dem Mail-Transport und der Facade von emailit/emailit-laravel oder per SMTP und verifizieren Sie Emailit-Webhooks.
Diese Anleitung zeigt zwei Wege, Laravel-E-Mails über Emailit zu senden: das Paket emailit/emailit-laravel, das einen Mail-Transport emailit und eine Facade Emailit hinzufügt, und einfaches SMTP mit dem integrierten Mailer von Laravel. Zum Schluss folgt eine Webhook-Route, die Signaturen verifiziert.
Voraussetzungen
- PHP 8.1 oder neuer und Laravel 10, 11 oder 12.
- Eine verifizierte Versanddomain, zum Beispiel
acme.com. - Ein API-Schlüssel. Ein reiner Sende-Schlüssel, der auf Ihre Domain beschränkt ist, genügt.
- Solange Ihr Workspace keinen Produktionszugang hat, können Sie nur an die Konto-E-Mail-Adressen von Workspace-Mitgliedern senden.
Option 1: das Laravel-Paket von Emailit
Das Paket sendet Ihre vorhandenen Mailables, Markdown-Mailables, Benachrichtigungen und E-Mails aus der Warteschlange über die Emailit-API, ohne Änderungen an Ihrem Mail-Code.
Paket installieren
composer require emailit/emailit-laravelDer Service Provider wird automatisch erkannt.
Transport konfigurieren
Fügen Sie in .env Ihren Schlüssel hinzu und machen Sie Emailit zum Standard-Mailer:
EMAILIT_API_KEY=secret_••••••••••••••••••••••••••••••••
MAIL_MAILER=emailit
MAIL_FROM_ADDRESS=hello@acme.com
MAIL_FROM_NAME="Acme"Registrieren Sie den Mailer in config/mail.php:
'mailers' => [
// ...
'emailit' => [
'transport' => 'emailit',
],
],MAIL_FROM_ADDRESS muss zu einer verifizierten Versanddomain gehören. Um die Basis-URL der API zu ändern, veröffentlichen Sie die Konfigurationsdatei mit php artisan vendor:publish --tag=emailit-config; für die normale Nutzung ist das nicht nötig.
Mailable senden
Erstellen Sie wie gewohnt ein Mailable:
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');
}
}Senden Sie es oder stellen Sie es in die Warteschlange, damit die Anfrage nicht auf die API wartet:
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
Mail::to($user)->send(new WelcomeEmail($user));
Mail::to($user)->queue(new WelcomeEmail($user));Facade für API-Funktionen verwenden
Die Facade Emailit stellt das vollständige PHP-SDK bereit, für Funktionen, die der Mailer von Laravel nicht abbildet, etwa gespeicherte Vorlagen und geplante Versände:
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_…Die Facade deckt außerdem Domains, Kontakte, Kontaktlisten, Sperrungen, Webhooks und die übrigen Ressourcen ab. Wenn Sie Dependency Injection bevorzugen, geben Sie Emailit\EmailitClient als Typ in einem Controller oder Job an, und Laravel löst den Client mit Ihrem konfigurierten Schlüssel auf.
Fangen Sie typisierte Exceptions ab, um Fehler zu behandeln:
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
}Option 2: einfaches SMTP
Wenn Sie lieber kein Paket hinzufügen möchten, richten Sie den SMTP-Mailer von Laravel auf das Emailit-Relay aus:
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"Auf Port 587 stuft der Mailer von Laravel die Verbindung per STARTTLS hoch. Ältere config/mail.php-Dateien lesen MAIL_ENCRYPTION, neuere ignorieren es; Sie können die Variable also gefahrlos behalten. Für implizites TLS verwenden Sie Port 465; wenn Ihr Hoster 587 blockiert, verwenden Sie 2525 oder 2587. Mailables, Benachrichtigungen und Warteschlangen funktionieren genauso wie mit dem Paket. Siehe SMTP-Einstellungen.
Per SMTP können Sie keine gespeicherten Vorlagen und kein scheduled_at verwenden; nutzen Sie dafür die Facade oder die API.
Webhooks empfangen
Erstellen Sie einen Webhook, der auf https://your-app.com/webhooks/emailit zeigt, und speichern Sie dann sein Signatur-Secret:
EMAILIT_WEBHOOK_SECRET=whsec_••••••••'emailit' => [
'webhook_secret' => env('EMAILIT_WEBHOOK_SECRET'),
],Fügen Sie einen Controller hinzu, der die Signatur anhand des unveränderten Bodys prüft:
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.
}
}Registrieren Sie die Route und nehmen Sie sie vom CSRF-Schutz aus, da Emailit kein CSRF-Token senden kann:
use App\Http\Controllers\EmailitWebhookController;
Route::post('/webhooks/emailit', EmailitWebhookController::class);->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: ['webhooks/emailit']);
})Unter Laravel 10 fügen Sie 'webhooks/emailit' stattdessen dem Array $except in app/Http/Middleware/VerifyCsrfToken.php hinzu. Geben Sie innerhalb von 30 Sekunden einen 2xx-Status zurück und verlagern Sie langsame Arbeit in eine Warteschlange. Siehe Anfragesignatur.
Tipps für den Produktivbetrieb
- E-Mails in die Warteschlange stellen. Verwenden Sie
queue()oderShouldQueue, damit Webanfragen nicht auf E-Mails warten, und drosseln Sie Massen-Jobs (zum Beispiel mitRedis::throttle), um unter Ihren Versandlimits zu bleiben. Neue Workspaces können standardmäßig 2 E-Mails pro Sekunde senden. - Konfiguration sicher cachen. Nach
php artisan config:cachefunktioniertenv()nur noch in Konfigurationsdateien. Lesen Sie den Schlüssel über die Konfiguration, so wie es das Paket tut. - Eigenen Schlüssel verwenden. Geben Sie jeder App und Umgebung einen eigenen reinen Sende-Schlüssel, damit Sie einen rotieren können, ohne die anderen anzutasten. Siehe API-Schlüssel.
- Webhooks deduplizieren. Speichern Sie jede verarbeitete
event_idund überspringen Sie Wiederholungen, da fehlgeschlagene Zustellungen erneut versucht werden.