michangarrito/docs/02-integraciones/INT-010-email-providers.md
rckrdmrd 2c916e75e5 [SIMCO-V4] feat: Agregar documentación SaaS, ADRs e integraciones
Nuevas Épicas (MCH-029 a MCH-033):
- Infraestructura SaaS multi-tenant
- Auth Social (OAuth2)
- Auditoría Empresarial
- Feature Flags
- Onboarding Wizard

Nuevas Integraciones (INT-010 a INT-014):
- Email Providers (SendGrid, Mailgun, SES)
- Storage Cloud (S3, GCS, Azure)
- OAuth Social
- Redis Cache
- Webhooks Outbound

Nuevos ADRs (0004 a 0011):
- Notifications Realtime
- Feature Flags Strategy
- Storage Abstraction
- Webhook Retry Strategy
- Audit Log Retention
- Rate Limiting
- OAuth Social Implementation
- Email Multi-provider

Actualizados:
- MASTER_INVENTORY.yml
- CONTEXT-MAP.yml
- HERENCIA-SIMCO.md
- Mapas de documentación

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:43:15 -06:00

7.8 KiB

id type title provider status integration_type created_at updated_at simco_version tags
INT-010 Integration Email Multi-Provider SendGrid/SES/SMTP Planificado notifications 2026-01-10 2026-01-10 4.0.1
email
notifications
transactional
multi-provider

INT-010: Email Multi-Provider

Metadata

Campo Valor
Codigo INT-010
Proveedor SendGrid, AWS SES, SMTP
Tipo Notificaciones
Estado Planificado
Multi-tenant Si
Epic Relacionada MCH-029
Owner Backend Team

1. Descripcion

Sistema de envio de emails transaccionales con soporte para multiples proveedores y fallback automatico. Incluye templates reutilizables, tracking de entrega y rate limiting por tenant.

Casos de uso principales:

  • Emails de bienvenida y verificacion
  • Notificaciones de pedidos
  • Recordatorios de pago
  • Alertas de inventario bajo
  • Reportes programados

2. Credenciales Requeridas

Variables de Entorno

Variable Descripcion Tipo Obligatorio
EMAIL_PROVIDER Proveedor principal (sendgrid/ses/smtp) string SI
SENDGRID_API_KEY API Key de SendGrid string SI (si usa SendGrid)
AWS_SES_REGION Region de AWS SES string SI (si usa SES)
AWS_SES_ACCESS_KEY Access Key para SES string SI (si usa SES)
AWS_SES_SECRET_KEY Secret Key para SES string SI (si usa SES)
SMTP_HOST Host del servidor SMTP string SI (si usa SMTP)
SMTP_PORT Puerto SMTP number SI (si usa SMTP)
SMTP_USER Usuario SMTP string SI (si usa SMTP)
SMTP_PASS Password SMTP string SI (si usa SMTP)
EMAIL_FROM_ADDRESS Email de remitente string SI
EMAIL_FROM_NAME Nombre de remitente string SI

Ejemplo de .env

# Email Configuration
EMAIL_PROVIDER=sendgrid
EMAIL_FROM_ADDRESS=noreply@michangarrito.com
EMAIL_FROM_NAME=MiChangarrito

# SendGrid
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxx

# AWS SES (fallback)
AWS_SES_REGION=us-east-1
AWS_SES_ACCESS_KEY=AKIAXXXXXXXXXXXXXXXX
AWS_SES_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# SMTP (ultimo recurso)
SMTP_HOST=smtp.mailtrap.io
SMTP_PORT=587
SMTP_USER=xxxxxxxx
SMTP_PASS=xxxxxxxx

3. Endpoints/SDK Utilizados

SendGrid

Operacion Metodo Endpoint Descripcion
Enviar email POST /v3/mail/send Envio simple o con template
Templates GET /v3/templates Listar templates

AWS SES

Operacion SDK Method Descripcion
Enviar email sendEmail() Via AWS SDK v3
Enviar raw sendRawEmail() Con attachments

SMTP

import * as nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  port: parseInt(process.env.SMTP_PORT),
  auth: {
    user: process.env.SMTP_USER,
    pass: process.env.SMTP_PASS,
  },
});

4. Rate Limits

Proveedor Limite Periodo Plan SendGrid
SendGrid 100 por segundo Pro
SendGrid 40,000 por mes Free
AWS SES 14 por segundo Default
AWS SES 50,000 por dia Verified

Rate Limiting por Tenant

Plan MCH Emails/hora Emails/dia
Basic 100 500
Pro 1,000 10,000
Enterprise Ilimitado Ilimitado

5. Manejo de Errores

Codigo Descripcion Accion Retry
400 Email invalido Validar formato NO
401 API Key invalida Verificar credencial NO
429 Rate limit Esperar + retry SI
500 Error proveedor Fallback a siguiente SI
503 Servicio no disponible Fallback SI

Estrategia de Fallback

const providers = ['sendgrid', 'ses', 'smtp'];

async function sendWithFallback(email: EmailDto) {
  for (const provider of providers) {
    try {
      return await this.send(provider, email);
    } catch (error) {
      this.logger.warn(`Provider ${provider} failed, trying next`);
      continue;
    }
  }
  throw new Error('All email providers failed');
}

6. Templates

Templates Disponibles

Template Descripcion Variables
welcome Bienvenida {name}
verify_email Verificacion {name}, {link}
order_confirmation Pedido confirmado {order_id}, {items}
payment_reminder Recordatorio pago {amount}, {due_date}
low_inventory Alerta inventario {product}, {quantity}

Formato de Template (Handlebars)

<h1>Hola {{name}}</h1>
<p>Tu pedido #{{order_id}} ha sido confirmado.</p>
{{#each items}}
  <li>{{this.name}} x {{this.quantity}}</li>
{{/each}}

7. Multi-tenant

Modelo de Credenciales

  • Global: Credenciales compartidas por defecto
  • Por Tenant: Tenant puede configurar sus propias credenciales
  • Branding: From address personalizable por tenant (Enterprise)

Almacenamiento

CREATE TABLE messaging.tenant_email_config (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID REFERENCES auth.tenants(id) NOT NULL,
    provider VARCHAR(20) NOT NULL, -- sendgrid, ses, smtp
    from_address VARCHAR(255) NOT NULL,
    from_name VARCHAR(100),
    credentials JSONB NOT NULL, -- Encriptado
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(tenant_id)
);

8. Tablas de BD

email_templates

CREATE TABLE messaging.email_templates (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID REFERENCES auth.tenants(id),
    key VARCHAR(100) NOT NULL,
    name VARCHAR(255) NOT NULL,
    subject VARCHAR(255) NOT NULL,
    html_content TEXT NOT NULL,
    text_content TEXT,
    variables JSONB,
    is_active BOOLEAN DEFAULT true,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    UNIQUE(tenant_id, key)
);

email_logs

CREATE TABLE messaging.email_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    template_id UUID REFERENCES messaging.email_templates(id),
    to_address VARCHAR(255) NOT NULL,
    subject VARCHAR(255) NOT NULL,
    provider VARCHAR(20) NOT NULL,
    provider_message_id VARCHAR(255),
    status VARCHAR(20) NOT NULL, -- sent, delivered, opened, clicked, bounced, failed
    error_message TEXT,
    sent_at TIMESTAMP WITH TIME ZONE,
    delivered_at TIMESTAMP WITH TIME ZONE,
    opened_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

9. Testing

Modo Sandbox

Ambiente Proveedor Comportamiento
Development Mailtrap Emails atrapados, no enviados
Staging SendGrid Sandbox Emails simulados
Production SendGrid/SES Envio real

Test de Conexion

# Test SendGrid
curl -X POST "https://api.sendgrid.com/v3/mail/send" \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"personalizations":[{"to":[{"email":"test@example.com"}]}],"from":{"email":"noreply@michangarrito.com"},"subject":"Test","content":[{"type":"text/plain","value":"Test email"}]}'

10. Monitoreo

Metricas

Metrica Descripcion Alerta
email_sent_total Emails enviados -
email_failed_total Emails fallidos > 5%
email_delivery_rate Tasa de entrega < 95%
email_bounce_rate Tasa de rebote > 5%

11. Referencias


Ultima actualizacion: 2026-01-10 Autor: Backend Team