# Enviar emails con Nuxt

> Envía emails desde una ruta de API de servidor de Nuxt con el SDK de Node.js de Emailit, guarda la clave en el runtimeConfig privado y verifica los webhooks con h3.

En esta guía se explica cómo enviar emails desde una aplicación Nuxt 3. Llamas a Emailit desde una ruta de API de servidor, guardas la clave de API en el `runtimeConfig` privado y verificas los webhooks con las funciones auxiliares de h3.

## Requisitos previos

- Nuxt 3 con un preset de servidor de Node.js 18 o posterior.
- Un [dominio de envío verificado](/es/docs/domains/add-a-domain/), por ejemplo `acme.com`.
- Una [clave de API](/es/docs/developers/api-keys/). Basta con una clave Sending Only limitada a tu dominio.
- Hasta que tu espacio de trabajo tenga [acceso de producción](/es/docs/workspaces/production-access/), solo puedes enviar a las direcciones de email de las cuentas de los miembros del espacio de trabajo.

## Instalar el SDK

```bash
npm install @emailit/node
```

## Configurar la clave de API

Declara claves privadas en el runtime config. Las claves que están fuera de `public` solo están disponibles en el servidor:

```typescript title="nuxt.config.ts"
  runtimeConfig: {
    emailitApiKey: '',
    emailitWebhookSecret: '',
  },
});
```

Nuxt las rellena a partir de las variables de entorno con el prefijo `NUXT_`:

```bash title=".env"
NUXT_EMAILIT_API_KEY=secret_••••••••••••••••••••••••••••••••
NUXT_EMAILIT_WEBHOOK_SECRET=whsec_••••••••
```

> **No pongas la clave en runtimeConfig.public:** Los valores de `runtimeConfig.public` se envían al navegador. No pongas nunca ahí la clave de API y no llames nunca a Emailit desde un componente o una página.

Añade una pequeña función auxiliar. Los archivos de `server/utils` se importan automáticamente en las rutas de servidor:

```typescript title="server/utils/emailit.ts"

  return new Emailit(useRuntimeConfig(event).emailitApiKey);
}
```

Si TypeScript indica que falta una declaración para `@emailit/node`, añade `declare module '@emailit/node';` a un archivo `.d.ts` de tu proyecto.

## Enviar un email

Crea una ruta de API de servidor. Esta ruta de un formulario de contacto envía a una dirección interna fija, así que los visitantes no pueden usarla para enviar emails a cualquiera:

```typescript title="server/api/contact.post.ts"
  const { email, message } = await readBody(event);

  if (typeof email !== 'string' || typeof message !== 'string' || !email.includes('@')) {
    throw createError({ statusCode: 400, statusMessage: 'Invalid input' });
  }

  const sent = await emailitClient(event).emails.send({
    from: 'Acme website <website@acme.com>',
    to: 'support@acme.com',
    reply_to: email,
    subject: 'New contact form message',
    text: message,
  });

  return { id: sent.id };
});
```

Llámala desde una página o un componente con `$fetch`:

```vue title="pages/contact.vue"
<script setup lang="ts">
const email = ref('');
const message = ref('');
const sent = ref(false);

async function submit() {
  await $fetch('/api/contact', {
    method: 'POST',
    body: { email: email.value, message: message.value },
  });
  sent.value = true;
}
</script>

<template>
  <form @submit.prevent="submit">
    <input v-model="email" type="email" required />
    <textarea v-model="message" required />
    <button type="submit">Send</button>
    <p v-if="sent">Thanks, we'll be in touch.</p>
  </form>
</template>
```

Para enviar una plantilla guardada en lugar de contenido en línea, pasa `template` (un alias o un ID `tem_`) y `variables`. Consulta [Plantillas](/es/docs/templates/) y [Enviar un email](/es/docs/api-reference/emails/send/).

## Enviar por SMTP

Si prefieres SMTP, usa Nodemailer en una ruta de servidor. SMTP necesita un preset de servidor de Node.js; los presets edge y de workers no pueden abrir conexiones SMTP, así que en ellos usa la API.

```typescript title="server/utils/mailer.ts"

  return nodemailer.createTransport({
    host: 'smtp.emailit.com',
    port: 587,
    secure: false,
    requireTLS: true,
    auth: { user: 'emailit', pass: useRuntimeConfig().emailitApiKey },
  });
}
```

Después, llama a `await mailer().sendMail({ from, to, subject, html })` desde una ruta. Para otros puertos, consulta [Configuración SMTP](/es/docs/smtp/settings/).

## Recibir webhooks

[Crea un webhook](/es/docs/webhooks/set-up/) que apunte a `https://your-app.com/api/webhooks/emailit`. Verifica la firma con el cuerpo en bruto y después analiza el array de eventos:

```typescript title="server/api/webhooks/emailit.post.ts"

  const rawBody = (await readRawBody(event)) ?? '';
  const signature = getHeader(event, 'x-emailit-signature') ?? '';
  const timestamp = getHeader(event, 'x-emailit-timestamp') ?? '';
  const secret = useRuntimeConfig(event).emailitWebhookSecret;

  const age = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp));
  const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
  const valid =
    Number.isFinite(age) &&
    age <= 300 &&
    expected.length === signature.length &&
    timingSafeEqual(Buffer.from(expected), Buffer.from(signature));

  if (!valid) {
    throw createError({ statusCode: 401, statusMessage: 'Invalid signature' });
  }

  const events = JSON.parse(rawBody) as Array<{ event_id: string; type: string; data: { object: any } }>;
  for (const item of events) {
    if (item.type === 'email.complained') {
      // Stop emailing item.data.object.to
    }
  }

  return { received: events.length };
});
```

Devuelve un `2xx` en menos de 30 segundos; las demás respuestas se reintentan. Consulta [Firma de las peticiones](/es/docs/webhooks/request-signature/).

## Consejos para producción

- **Define los secretos en tu hosting.** Configura `NUXT_EMAILIT_API_KEY` en la configuración de entorno de tu proveedor de hosting en lugar de desplegar un archivo `.env`.
- **Valida antes de enviar.** Acepta un destinatario desde el navegador solo cuando sea la dirección del propio usuario que ha iniciado sesión, y limita la frecuencia de las rutas públicas. Cada email cuesta créditos y cuenta para tus [límites de envío](/es/docs/limits/).
- **Usa claves distintas para cada entorno** para poder revocar una clave de vista previa sin tocar la de producción.

## Próximos pasos

  - [Guía de Node.js](/es/docs/frameworks/nodejs/): Detalles sobre la gestión de errores y Nodemailer.
  - [Enviar emails con la API](/es/docs/email-api/send-email/): Adjuntos, programación y seguimiento.
  - [Tipos de eventos de webhook](/es/docs/webhooks/event-types/): Todos los eventos y su payload.
  - [Claves de API](/es/docs/developers/api-keys/): Permisos, limitación por dominio y rotación.

---
Fuente: https://emailit.com/es/docs/frameworks/nuxt/
