@jamx-framework/mailer
v1.0.0
Published
JAMX Framework — Transactional email
Maintainers
Readme
@jamx-framework/mailer
Descripción
Módulo de envío de correos electrónicos para JAMX Framework. Proporciona una API type-safe para enviar emails con múltiples drivers (SMTP, consola, servicios en la nube), soporte para plantillas (Handlebars, MJML), adjuntos, y gestión de colas. Ideal para aplicaciones que necesitan enviar emails transaccionales, newsletters o notificaciones.
Cómo funciona
El módulo implementa un sistema de envío de emails con drivers intercambiables:
- Mailer: Clase principal que construye y envía emails
- Drivers: Implementaciones concretas (SmtpDriver, ConsoleDriver) para diferentes métodos de envío
- Templates: Motor de plantillas con soporte para Handlebars y MJML
- Queue: Integración opcional con colas para envío asíncrono
Componentes principales
- src/mailer.ts: Clase
Mailerque construye y envía emails - src/drivers/smtp.ts: Driver que envía via SMTP
- src/drivers/console.ts: Driver que imprime a consola (desarrollo/testing)
- src/drivers/types.ts: Tipos compartidos (
MailDriver,MailMessage, etc.) - src/templates/engine.ts: Motor de plantillas (Handlebars)
- src/templates/defaults.ts: Plantillas predefinidas (welcome, reset password, etc.)
- src/index.ts: Punto de exportación
Uso básico
import { Mailer, SmtpDriver } from '@jamx-framework/mailer';
// Configurar driver SMTP
const driver = new SmtpDriver({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: '[email protected]',
pass: 'tu-contraseña',
},
});
const mailer = new Mailer(driver);
// Enviar email simple
await mailer.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Bienvenido',
text: '¡Hola! Bienvenido a nuestra app.',
html: '<p>¡Hola! Bienvenido a nuestra app.</p>',
});Con plantillas
import { Mailer, SmtpDriver } from '@jamx-framework/mailer';
const mailer = new Mailer(new SmtpDriver(config));
// Renderizar plantilla con datos
const html = await mailer.render('welcome', {
userName: 'Juan',
activationLink: 'https://miapp.com/activate?token=abc123',
});
await mailer.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Bienvenido a MiApp',
html,
});Ejemplos
Email con adjuntos
await mailer.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Tu reporte',
text: 'Adjunto encontrarás tu reporte.',
attachments: [
{
filename: 'reporte.pdf',
content: Buffer.from('PDF content here'),
contentType: 'application/pdf',
},
{
filename: 'imagen.png',
path: '/ruta/a/imagen.png', // también se puede usar path
},
],
});Email con CC y BCC
await mailer.send({
from: '[email protected]',
to: '[email protected]',
cc: ['[email protected]', '[email protected]'],
bcc: ['[email protected]'],
subject: 'Notificación importante',
html: '<p>Este es un mensaje importante.</p>',
});Uso con plantillas Handlebars
// Registrar plantilla personalizada
mailer.registerTemplate('invoice', {
subject: 'Factura #{{invoiceNumber}}',
html: `
<h1>Factura {{invoiceNumber}}</h1>
<p>Hola {{customerName}},</p>
<p>El total a pagar es: ${{total}}</p>
`,
});
// Usar la plantilla
await mailer.send({
from: '[email protected]',
to: '[email protected]',
template: 'invoice',
data: {
invoiceNumber: 'INV-2024-001',
customerName: 'Juan Pérez',
total: '150.00',
},
});Driver de consola (desarrollo)
import { Mailer, ConsoleDriver } from '@jamx-framework/mailer';
// En desarrollo, usar ConsoleDriver para no enviar emails reales
const mailer = new Mailer(new ConsoleDriver());
await mailer.send({
from: 'test@localhost',
to: '[email protected]',
subject: 'Test',
html: '<p>Esto se imprime en consola</p>',
});
// Output: [Mailer] Sending email to [email protected] with subject "Test"Envío con cola (Queue integration)
import { Mailer, SmtpDriver } from '@jamx-framework/mailer';
import { Queue } from '@jamx-framework/queue';
const mailer = new Mailer(new SmtpDriver(config));
const queue = new Queue();
// Encolar email para envío asíncrono
await queue.add('send-email', {
message: {
from: '[email protected]',
to: '[email protected]',
subject: 'Notificación',
html: '<p>Contenido</p>',
},
});
// Worker que procesa la cola
queue.process('send-email', async (job) => {
await mailer.send(job.data.message);
});Inyección de dependencias
import { Container } from '@jamx-framework/core';
import { Mailer, SmtpDriver } from '@jamx-framework/mailer';
// Registrar en contenedor
Container.registerSingleton('mailer', () => {
const driver = new SmtpDriver({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
return new Mailer(driver);
});
// Usar en cualquier parte
const mailer = Container.resolve<Mailer>('mailer');
await mailer.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Hello',
text: 'Hello world',
});Flujo interno
- Configuración: Se crea un driver (SMTP, Console, etc.) y se pasa al
Mailer - Construcción:
mailer.send()construye unMailMessagecon from, to, subject, content, attachments - Validación: Se validan campos obligatorios (from, to, subject)
- Renderizado: Si se usa
template, se renderiza con los datos proporcionados - Envío: El driver recibe el mensaje y lo envía por el medio correspondiente
- Respuesta: El driver retorna un
SendResultcon status, messageId, etc. - Error handling: Los errores se capturan y se lanzan como
MailerError
API Reference (Resumen)
Mailer
constructor(driver: MailDriver)async send(message: MailMessage | Partial<MailMessage> & { template: string, data: any }): Promise<SendResult>async render(templateName: string, data: any): Promise<string>registerTemplate(name: string, template: MailTemplate): voidhasTemplate(name: string): boolean
MailMessage
from: string | { name: string, address: string }to: string | string[] | { name: string, address: string }[]cc?: string | string[]bcc?: string | string[]subject: stringtext?: stringhtml?: stringattachments?: Attachment[]headers?: Record<string, string>
Attachment
filename: stringcontent?: Buffer | stringpath?: stringcontentType?: string
MailDriver (interface)
async send(message: MailMessage): Promise<SendResult>async verifyConnection(): Promise<boolean>
SendResult
success: booleanmessageId?: stringerror?: stringaccepted?: numberrejected?: number
Performance Considerations
- Connection pooling: SMTP driver reutiliza conexiones cuando es posible
- Batch sending: Se pueden enviar múltiples emails concurrentemente
- Template caching: Las plantillas compiladas se cachean en memoria
- Lazy rendering: Las plantillas se renderizan solo cuando se usan
- Queue integration: Para alto volumen, usar colas para procesamiento asíncrono
Configuration Options
// SMTP Driver
const smtpDriver = new SmtpDriver({
host: 'smtp.gmail.com',
port: 587,
secure: false, // true para SSL/TLS
auth: {
user: '[email protected]',
pass: 'password',
},
pool: {
maxConnections: 5,
maxMessages: 100,
},
});
// Console Driver (desarrollo)
const consoleDriver = new ConsoleDriver({
verbose: true, // imprime detalles completos
format: 'json', // 'json' | 'text'
});Testing
Tests en packages/mailer/tests/unit/:
pnpm testCubre:
- Envío de emails básicos
- Adjuntos y CC/BCC
- Renderizado de plantillas
- Drivers múltiples (SMTP mock, console)
- Validación de mensajes
- Manejo de errores
Compatibility
- Compatible con Node.js 18+
- Funciona con cualquier servidor SMTP (Gmail, SendGrid, Mailgun, etc.)
- Soporta TLS/SSL
- No requiere dependencias nativas
CLI Integration
jamx mail:send: Envía un email desde CLIjamx mail:test: Prueba la configuración SMTPjamx mail:template:compile: Compila plantillas MJML a HTMLjamx mail:queue:process: Procesa cola de emails pendientes
Security Considerations
- Never hardcode credentials: Usar variables de entorno para SMTP credentials
- Validate inputs: Sanitizar datos de plantillas para evitar XSS
- Use TLS: Siempre usar secure: true en producción
- Rate limiting: Limitar envíos para evitar spam
- BCC for bulk: Usar BCC para emails masivos (no revelar direcciones)
Best Practices
- Usar templates: Mantener HTML en plantillas, no en código
- Separar drivers: Usar ConsoleDriver en dev, SmtpDriver en prod
- Manejar errores: Capturar
MailerErrory loguear - Queue for async: Para alto volumen, usar colas (RabbitMQ, Redis)
- Test emails: Enviar emails de prueba antes de campañas masivas
- Monitor delivery: Revisar bounce rates y spam complaints
- Use DKIM/SPF: Configurar autenticación de email en dominio
This mailer module provides a flexible, type-safe email sending solution for JAMX applications, enabling developers to send transactional and marketing emails with multiple drivers, template support, and queue integration.
