# Enviar e-mail no Laravel

> Enviar e-mail pelo Couryo no Laravel com Mail::to()->send(), pelo transporte couryo do SDK PHP ou por SMTP, com tags, filas e webhook assinado.

Fonte: https://couryo.com/docs/laravel

Duas formas, as duas com `Mail::to()->send()` e os seus Mailables de sempre:

- **Transporte `couryo` do [SDK PHP](https://couryo.com/docs/sdks.md)** (recomendado): fala com a API, devolve o ID da mensagem e leva as tags e os metadados do Mailable.
- **SMTP**: nenhuma dependência nova, só o `.env`.

## Opção 1: transporte do SDK

```bash title="Terminal"
composer require couryo/couryo-php
```

O service provider é registrado sozinho (auto-discovery). Configure o `.env`:

```ini title=".env"
MAIL_MAILER=couryo
COURYO_API_KEY=ck_test_...
COURYO_WEBHOOK_SECRET=whsec_...
MAIL_FROM_ADDRESS=oi@exemplo.com.br
MAIL_FROM_NAME="Exemplo"
```

E acrescente o mailer em `config/mail.php`:

```php title="config/mail.php"
'mailers' => [
    // ...
    'couryo' => [
        'transport' => 'couryo',
    ],
],
```

Pronto. O código que já existe continua igual:

```php title="app/Http/Controllers/PedidoController.php"
use App\Mail\PedidoEnviado;
use Illuminate\Support\Facades\Mail;

Mail::to($pedido->cliente->email)->send(new PedidoEnviado($pedido));

// Em fila (recomendado para não segurar a requisição):
Mail::to($pedido->cliente->email)->queue(new PedidoEnviado($pedido));
```

Tags e metadados do Mailable viram `tags` e `metadata` no Couryo, para filtrar no painel e nos webhooks:

```php title="app/Mail/PedidoEnviado.php"
use Illuminate\Mail\Mailables\Envelope;

public function envelope(): Envelope
{
    return new Envelope(
        subject: "Seu pedido {$this->pedido->numero} saiu para entrega",
        tags: ['pedido'],
        metadata: ['pedido_id' => (string) $this->pedido->id],
    );
}
```

Para mandar no fluxo de marketing (com descadastro em um clique), acrescente o cabeçalho `X-Couryo-Stream: marketing` no método `headers()` do Mailable. Sem ele, o e-mail é transacional.

### Chamar a API direto

Para o que o `Mail` não cobre (lote, templates salvos, domínios, contatos, eventos e campanhas), injete o cliente:

```php title="app/Http/Controllers/CadastroController.php"
use Couryo\Couryo;

public function store(Request $request, Couryo $couryo)
{
    $usuario = User::create($request->validated());

    $couryo->events->track([
        'contact' => ['email' => $usuario->email, 'attributes' => ['nome' => $usuario->name]],
        'name' => 'user.signed_up',
    ], ['idempotency_key' => "signup-{$usuario->id}"]);

    return redirect('/painel');
}
```

## Opção 2: SMTP

Sem pacote nenhum. No Laravel 11 ou mais novo:

```ini title=".env"
MAIL_MAILER=smtp
MAIL_SCHEME=smtp
MAIL_HOST=smtp.couryo.com
MAIL_PORT=587
MAIL_USERNAME=couryo
MAIL_PASSWORD=ck_live_...
MAIL_FROM_ADDRESS=oi@exemplo.com.br
MAIL_FROM_NAME="Exemplo"
```

Na porta 587 a conexão sobe para TLS (STARTTLS) sozinha. Para a 465, use `MAIL_SCHEME=smtps`. No Laravel 10 ou anterior, troque `MAIL_SCHEME` por `MAIL_ENCRYPTION=tls`.

Por SMTP, `X-Couryo-Tags: tipo=pedido` e `X-Couryo-Stream: marketing` nos cabeçalhos do Mailable fazem o mesmo papel das tags e do fluxo. Veja [SMTP](https://couryo.com/docs/smtp.md).

## Receber webhooks

```php title="routes/web.php"
use Couryo\Exception\WebhookVerificationError;
use Couryo\Webhook;
use Illuminate\Http\Request;

Route::post('/webhooks/couryo', function (Request $request) {
    try {
        $evento = Webhook::verify(config('couryo.webhook_secret'), $request->headers->all(), $request->getContent());
    } catch (WebhookVerificationError $e) {
        abort(400, 'assinatura inválida');
    }

    if ($evento['type'] === 'bounced') {
        // $evento['data']['recipient'], $evento['data']['explanation']
    }

    return response()->noContent();
});
```

Tire a rota da proteção CSRF (a assinatura já protege). No Laravel 11 ou mais novo:

```php title="bootstrap/app.php"
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: ['webhooks/couryo']);
})
```

## Testar sem enviar

Com uma chave `ck_test_`, os e-mails são capturados e aparecem no painel, sem chegar a ninguém ([modo de teste](https://couryo.com/docs/test-mode.md)). Nos testes automatizados, continue usando `Mail::fake()`.

## Problemas comuns

| Sintoma | O que fazer |
|---|---|
| `Unsupported mail transport [couryo]` | o pacote não foi carregado: rode `composer dump-autoload` e `php artisan config:clear` |
| `domain_not_verified` | o `MAIL_FROM_ADDRESS` precisa estar num [domínio verificado](https://couryo.com/docs/domains.md) |
| `535 5.7.8` no SMTP | usuário diferente de `couryo` ou chave inválida, revogada ou sem escopo `send` |
| Webhook com `419` | a rota ainda está na proteção CSRF |
