Configuración SMTP por empresa
Sección titulada «Configuración SMTP por empresa»Cada empresa (tenant) define su propio servidor SMTP para enviar emails desde Keirost. Esto permite usar el dominio de la empresa como remitente.
Configurar SMTP
Sección titulada «Configurar SMTP»GET /api/email/configPATCH /api/email/config{ "enabled": true, "host": "smtp.gmail.com", "port": 587, "secure": false, "user": "noreply@tudominio.com", "password": "app_password_aqui", "from_name": "Keirost - Tu Empresa", "from_email": "noreply@tudominio.com", "reply_to": "soporte@tudominio.com", "tls": "starttls"}| Campo | Descripción |
|---|---|
host |
Servidor SMTP (smtp.gmail.com, smtp.office365.com, smtp.tudominio.com) |
port |
Puerto: 587 (STARTTLS), 465 (SMTPS), 25 (sin cifrar) |
secure |
true = usa SSL/TLS directamente (puerto 465) |
user |
Usuario o dirección de email remitente |
password |
Password o app password (recomendado: app password, no password real) |
from_name |
Nombre que aparece como remitente |
from_email |
Email que aparece como remitente |
reply_to |
Email de respuesta (si diferente del remitente) |
tls |
starttls (recomendado), tls (SSL), none |
Probar conexion
Sección titulada «Probar conexion»POST /api/email/config/testContent-Type: application/json
{ "to": "test@tudominio.com"}Envia un email de prueba a la dirección indicada. Devuelve success o el error de conexion.
Cola de envío de emails
Sección titulada «Cola de envío de emails»Los emails no se envian de forma sincrona. Se encolan en segundo plano para no bloquear la interfaz y poder reintentarlos en caso de fallo.
Modelo de cola
Sección titulada «Modelo de cola»interface EmailQueueItem { id: string; to: string[]; cc?: string[]; bcc?: string[]; subject: string; body_html: string; body_text?: string; attachments?: { filename: string; path: string; size: number }[]; status: 'queued' | 'sending' | 'sent' | 'failed' | 'retrying'; attempts: number; max_attempts: number; last_error?: string; sent_at?: string; created_at: string; created_by: string;}Estados de la cola
Sección titulada «Estados de la cola»| Estado | Descripción |
|---|---|
queued |
En espera. El siguiente proceso de cola lo recogerá. |
sending |
Enviando actualmente. |
sent |
Enviado correctamente. |
failed |
Fallo tras agotar todos los reintentos. |
retrying |
Reintentando tras un fallo temporal. |
Reintentos automáticos
Sección titulada «Reintentos automáticos»- Máximo de intentos: 5
- Intervalo de reintento: exponencial (1min, 5min, 15min, 1h, 4h)
- Solo se reintenta en fallos temporales (timeout, conexion rechazada, servidor ocupado)
- Fallos definitivos (autenticación incorrecta, email invalido) no se reintentan
Envío de documentos por email
Sección titulada «Envío de documentos por email»Enviar un documento
Sección titulada «Enviar un documento»POST /api/email/sendAuthorization: Bearer <token>Content-Type: application/json
{ "document_type": "sales_invoice", "document_id": "inv_2026_0012", "to": ["cliente@acme.com"], "cc": ["contabilidad@acme.com"], "subject": "Factura F-2026-0012", "body_html": "<p>Estimado cliente, adjuntamos la factura {{document_number}}.</p>", "attach_pdf": true}Respuesta inmediata (el email se encola):
{ "queue_id": "eq_001", "status": "queued", "message": "Email encolado. Recibirás una notificacion cuando se complete."}Preview del email
Sección titulada «Preview del email»Antes de enviar, puedes ver exactamente como quedará:
POST /api/email/previewAuthorization: Bearer <token>Content-Type: application/json
{ "document_type": "sales_invoice", "document_id": "inv_2026_0012", "to": ["cliente@acme.com"], "subject": "Factura F-2026-0012", "body_html": "<p>Estimado cliente, adjuntamos la factura {{document_number}}.</p>"}Devuelve:
{ "subject": "Factura F-2026-0012", "from": "noreply@tudominio.com", "to": ["cliente@acme.com"], "body_html_rendered": "<p>Estimado cliente, adjuntamos la factura F-2026-0012.</p>", "attachments": [ { "filename": "F-2026-0012.pdf", "size": 45678 } ], "preview_url": "/api/email/preview/:queue_id"}Adjuntos automáticos
Sección titulada «Adjuntos automáticos»Por defecto, cuando attach_pdf: true:
- Se genera el PDF del documento con la plantilla activa
- Se adjunta con el nombre
{{series}}-{{number}}.pdf
También puedes adjuntar archivos adicionales (contratos, presupuestos, etc.):
{ "attachments": [ { "path": "/storage/contracts/CTR-2026-001.pdf" }, { "path": "/storage/presupuestos/PRE-2026-001.pdf" } ]}Envío masivo
Sección titulada «Envío masivo»Seleccionar múltiples documentos
Sección titulada «Seleccionar múltiples documentos»POST /api/email/send-bulkAuthorization: Bearer <token>Content-Type: application/json
{ "document_type": "sales_invoice", "document_ids": ["inv_2026_001", "inv_2026_002", "inv_2026_003"], "to_field": "partner.email", "subject": "Factura {{series}}-{{number}}", "body_html": "<p>Estimado {{partner_name}}, adjuntamos su factura {{document_number}} del {{document_date}}.</p>", "attach_pdf": true}| Campo | Descripción |
|---|---|
document_ids |
Lista de IDs de documentos a enviar |
to_field |
Campo del documento/partner usado como destinatario |
subject |
Asunto con variables ({{series}}, {{number}}, {{partner_name}}) |
body_html |
Cuerpo HTML con variables |
Respuesta:
{ "queued": 3, "failed": 0, "queue_ids": ["eq_001", "eq_002", "eq_003"], "message": "3 emails encolados para envio"}Historial de emails enviados
Sección titulada «Historial de emails enviados»Listar historial
Sección titulada «Listar historial»GET /api/email/history?from=2026-01-01&to=2026-05-08&status=sent{ "data": [ { "id": "eq_001", "to": ["cliente@acme.com"], "subject": "Factura F-2026-0012", "document_type": "sales_invoice", "document_id": "inv_2026_0012", "status": "sent", "attempts": 1, "sent_at": "2026-05-08T10:05:00Z", "created_by": "admin" } ], "pagination": { "total": 156, "page": 1, "per_page": 20 }}Ver detalle de un email
Sección titulada «Ver detalle de un email»GET /api/email/history/:idIncluye el contenido HTML completo, adjuntos y eventos de reintento.
Notificaciones in-app de email
Sección titulada «Notificaciones in-app de email»Cuando un email termina de enviarse (o falla después de todos los reintentos), se genera una notificación in-app dirigida al usuario que lo envió.
GET /api/notifications?type=email_status{ "data": [ { "id": "notif_001", "type": "email_status", "title": "Email enviado", "body": "Factura F-2026-0012 enviada a cliente@acme.com", "read": false, "created_at": "2026-05-08T10:05:00Z" } ]}El icono de campana en la interfaz muestra un indicador pulsante cuando hay nuevas notificaciones de email.
Plantillas de email
Sección titulada «Plantillas de email»Keirost permite crear plantillas de email reutilizables por tipo de documento.
Endpoints
Sección titulada «Endpoints»GET /api/email/templatesPOST /api/email/templatesPATCH /api/email/templates/:idDELETE /api/email/templates/:id{ "id": "et_factura_cliente", "name": "Factura a cliente", "document_type": "sales_invoice", "subject": "Factura {{series}}-{{number}}", "body_html": "<h2>Estimado {{partner_name}},</h2><p>Adjuntamos su factura <strong>{{document_number}}</strong> por importe de <strong>{{total}} EUR</strong>.</p>", "attach_pdf": true, "active": true}Variables disponibles
Sección titulada «Variables disponibles»| Variable | Descripción |
|---|---|
{{document_number}} |
Número completo del documento |
{{document_date}} |
Fecha en formato legible |
{{partner_name}} |
Nombre del cliente/proveedor |
{{partner_vat}} |
CIF/NIF del partner |
{{subtotal}} |
Importe sin impuestos |
{{tax_amount}} |
Importe de impuestos |
{{total}} |
Total con impuestos |
{{due_date}} |
Fecha de vencimiento |
{{company_name}} |
Nombre de la empresa |
{{company_address}} |
Dirección de la empresa |
Resumen de endpoints
Sección titulada «Resumen de endpoints»| Método | Ruta | Descripción |
|---|---|---|
| GET | /api/email/config |
Obtener config SMTP |
| PATCH | /api/email/config |
Guardar config SMTP |
| POST | /api/email/config/test |
Enviar email de prueba |
| POST | /api/email/send |
Enviar un documento por email |
| POST | /api/email/preview |
Preview antes de enviar |
| POST | /api/email/send-bulk |
Envío masivo |
| GET | /api/email/history |
Historial de emails enviados |
| GET | /api/email/history/:id |
Detalle de un email |
| GET | /api/email/templates |
Listar plantillas |
| POST | /api/email/templates |
Crear plantilla |
| PATCH | /api/email/templates/:id |
Actualizar plantilla |
| DELETE | /api/email/templates/:id |
Eliminar plantilla |