Aller au contenu
Docs

Tutoriel

Envoyez des e-mails depuis une route d’API serveur Nuxt avec le SDK Node.js d’Emailit, gardez la clé dans le runtimeConfig privé et vérifiez les webhooks avec h3.

Mis à jour le 1 oct. 2026

Ce guide montre comment envoyer des e-mails depuis une application Nuxt 3. Vous appelez Emailit depuis une route d’API serveur, gardez la clé API dans le runtimeConfig privé et vérifiez les webhooks avec les fonctions utilitaires de h3.

Prérequis

  • Nuxt 3 avec un preset serveur Node.js 18 ou version ultérieure.
  • Un domaine d’envoi vérifié, par exemple acme.com.
  • Une clé API. Une clé Sending Only limitée à votre domaine suffit.
  • Tant que votre espace de travail n’a pas l’accès production, vous ne pouvez envoyer qu’aux adresses e-mail des comptes des membres de l’espace de travail.

Installer le SDK

Terminal
npm install @emailit/node

Configurer votre clé API

Déclarez des clés de configuration d’exécution privées. Les clés situées hors de public ne sont disponibles que sur le serveur :

nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    emailitApiKey: '',
    emailitWebhookSecret: '',
  },
});

Nuxt les renseigne à partir des variables d’environnement préfixées par NUXT_ :

.env
NUXT_EMAILIT_API_KEY=secret_••••••••••••••••••••••••••••••••
NUXT_EMAILIT_WEBHOOK_SECRET=whsec_••••••••

Ajoutez une petite fonction utilitaire. Les fichiers de server/utils sont importés automatiquement dans les routes serveur :

server/utils/emailit.ts
import type { H3Event } from 'h3';
import { Emailit } from '@emailit/node';

export function emailitClient(event: H3Event) {
  return new Emailit(useRuntimeConfig(event).emailitApiKey);
}

Si TypeScript signale une déclaration manquante pour @emailit/node, ajoutez declare module '@emailit/node'; à un fichier .d.ts de votre projet.

Envoyer un e-mail

Créez une route d’API serveur. Cette route de formulaire de contact envoie à une adresse interne fixe : les visiteurs ne peuvent donc pas l’utiliser pour envoyer des e-mails à n’importe qui :

server/api/contact.post.ts
export default defineEventHandler(async (event) => {
  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 };
});

Appelez-la depuis une page ou un composant avec $fetch :

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>

Pour envoyer un modèle enregistré plutôt qu’un contenu en ligne, transmettez template (un alias ou un ID tem_) et variables. Consultez Modèles et Envoyer un e-mail.

Envoyer plutôt via SMTP

Si vous préférez le SMTP, utilisez Nodemailer dans une route serveur. Le SMTP nécessite un preset serveur Node.js ; les presets edge et worker ne peuvent pas ouvrir de connexions SMTP : utilisez l’API dans ce cas.

server/utils/mailer.ts
import nodemailer from 'nodemailer';

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

Appelez ensuite await mailer().sendMail({ from, to, subject, html }) depuis une route. Pour les autres ports, consultez Paramètres SMTP.

Recevoir des webhooks

Créez un webhook qui pointe vers https://your-app.com/api/webhooks/emailit. Vérifiez la signature à partir du corps brut, puis analysez le tableau d’événements :

server/api/webhooks/emailit.post.ts
import { createHmac, timingSafeEqual } from 'node:crypto';

export default defineEventHandler(async (event) => {
  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 };
});

Renvoyez un 2xx dans les 30 secondes ; pour toute autre réponse, Emailit réessaie. Consultez Signature des requêtes.

Conseils pour la production

  • Définissez les secrets chez votre hébergeur. Configurez NUXT_EMAILIT_API_KEY dans les paramètres d’environnement de votre hébergeur plutôt que de livrer un fichier .env.
  • Validez avant d’envoyer. N’acceptez un destinataire depuis le navigateur que s’il s’agit de l’adresse de l’utilisateur connecté, et limitez le débit des routes publiques. Chaque e-mail coûte des crédits et compte dans vos limites d’envoi.
  • Utilisez des clés distinctes par environnement pour pouvoir révoquer une clé de prévisualisation sans toucher à la production.

Étapes suivantes

Gestion des erreurs et détails sur Nodemailer.
Pièces jointes, programmation et suivi.
Tous les événements et leur payload.
Portées, limitation à un domaine et rotation.

Cette page vous a-t-elle été utile ?

Merci pour votre retour.

Merci, nous lisons chaque message.