Enviar Email a Contactos Específicos
POST /api/messages/email/contacts
Sección titulada « /api/messages/email/contacts»Envía mensajes de correo electrónico a una lista específica de direcciones de email. La operación es asíncrona: la API registra cada mensaje en la persistencia, programa la entrega en BullMQ y retorna un resumen del encolado.
Autenticación
Sección titulada «Autenticación»- Incluye el token bearer en
Authorization: Bearer <token>. - Solo los miembros que han aceptado los términos actuales pueden activar acciones de mensajería; de lo contrario, el servicio retorna
403 Forbidden.
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»interface EmailContactsMessagePayload extends EmailMessageBasePayload { contacts: string[]; // Lista explícita de direcciones de email}
interface EmailMessageBasePayload { subject: string; message: string; // HTML o texto plano soportado por el proveedor}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
subject | string | Sí | Asunto del email |
message | string | Sí | Contenido del email (HTML o texto plano) |
contacts | string[] | Sí | Lista de direcciones de email |
Ejemplo del cuerpo
Sección titulada «Ejemplo del cuerpo»{ "subject": "Bienvenido a SendMe - Confirmación de registro", "message": "<h1>¡Bienvenido!</h1><p>Tu cuenta ha sido creada exitosamente. Gracias por unirte a SendMe.</p>",}Respuesta
Sección titulada «Respuesta»La API responde con el contrato compartido MessageEnqueueResultDto:
interface MessageEnqueueResultDto { queueId: string; // Identificador del job de BullMQ, vacío cuando no se encoló nada channel: 'email'; messages: Array<{ id: string; // UUID del mensaje persistido recipient: string; // Dirección de email normalizada por el backend }>;}Respuesta exitosa (201 Created)
Sección titulada «Respuesta exitosa (201 Created)»{ "queueId": "email-queue-12345", "channel": "email", "messages": [ { "id": "msg-uuid-1", }, { "id": "msg-uuid-2", } ]}Sin destinatarios válidos (200 OK)
Sección titulada «Sin destinatarios válidos (200 OK)»Cuando la petición no resuelve direcciones de email válidas, el servicio responde con 200 OK, un queueId vacío y un array de messages vacío.
{ "queueId": "", "channel": "email", "messages": []}Ejemplos de uso
Sección titulada «Ejemplos de uso»async function sendEmailToContacts(token: string, payload: EmailContactsMessagePayload) { const response = await fetch('/api/messages/email/contacts', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify(payload), });
if (!response.ok) { throw new Error(`Email enqueue failed: ${response.status}`); }
const data: MessageEnqueueResultDto = await response.json(); return data;}
// Uso con HTMLconst result = await sendEmailToContacts('your-token', { subject: 'Factura de tu pedido #12345', message: ` <div style="font-family: Arial, sans-serif;"> <h2>Gracias por tu compra</h2> <p>Adjunto encontrarás la factura de tu pedido.</p> <a href="#" style="background: #007cba; color: white; padding: 10px 20px; text-decoration: none;"> Ver Pedido </a> </div> `,});
console.log(`Emails encolados: ${result.messages.length}`);import axios from 'axios';
async function sendEmailToContacts(token: string, payload: EmailContactsMessagePayload) { const { data } = await axios.post<MessageEnqueueResultDto>( '/api/messages/email/contacts', payload, { headers: { Authorization: `Bearer ${token}`, }, }, );
return data;}
// Uso con texto planoconst result = await sendEmailToContacts('your-token', { subject: 'Recuperación de contraseña', message: 'Hemos recibido una solicitud para restablecer tu contraseña. Si no fuiste tú, ignora este email.',});curl -X POST "/api/messages/email/contacts" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "subject": "Newsletter SendMe - Novedades del mes", "message": "<h1>Novedades</h1><p>Descubre las nuevas funciones que hemos añadido este mes.</p>", "contacts": ["[email protected]", "[email protected]"] }'Tipos de contenido soportados
Sección titulada «Tipos de contenido soportados»Email HTML
Sección titulada «Email HTML»const htmlPayload = { subject: "Promoción especial", message: ` <html> <body> <div style="max-width: 600px; margin: 0 auto;"> <h1 style="color: #333;">¡Oferta especial!</h1> <p>No te pierdas nuestra promoción de fin de temporada.</p> <img src="https://ejemplo.com/promocion.jpg" alt="Promoción" style="max-width: 100%;"> <a href="https://tienda.ejemplo.com" style="background: #ff6b6b; color: white; padding: 15px 25px; text-decoration: none; border-radius: 5px;"> Comprar ahora </a> </div> </body> </html> `,};Email de texto plano
Sección titulada «Email de texto plano»const textPayload = { subject: "Confirmación de cita", message: ` Estimado cliente,
Su cita ha sido confirmada para: Fecha: 15 de Abril, 2024 Hora: 10:00 AM Lugar: Oficina principal
Si necesita reprogramar, responda a este email.
Saludos, Equipo SendMe `,};Notas operacionales
Sección titulada «Notas operacionales»- El backend elimina destinatarios duplicados por lote y omite silenciosamente destinos inválidos.
- La validación del saldo se ejecuta antes del encolado; créditos insuficientes retornan una respuesta de error sin encolar mensajes.
- Usa el
queueIdretornado para correlacionar el estado de entrega dentro de la UI de administración o vía endpoints de estado dedicados. - Cada mensaje persiste metadatos del proveedor y puede ser auditado a través de los filtros del módulo de mensajería.
- El contenido HTML debe ser válido y compatible con los principales clientes de email.