156 lines
6.5 KiB
Go
156 lines
6.5 KiB
Go
package email
|
||
|
||
import (
|
||
"bytes"
|
||
"fmt"
|
||
"github.com/tuusuario/go-sync-service/internal/domain/ports"
|
||
"html/template"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// TaskTplData contiene los datos que se inyectarán en la plantilla HTML de la notificación de tarea.
|
||
// Se usan como {{.Campo}} dentro del template.
|
||
type TaskTplData struct {
|
||
AppName string
|
||
Nombre string
|
||
TareaNombre string
|
||
Descripcion string
|
||
FechaVencimiento string
|
||
ErrorDescripcion string
|
||
FechaError string
|
||
LinkTarea string
|
||
LogoURL string
|
||
Direccion string
|
||
Telefono string
|
||
EmailContacto string
|
||
Year int
|
||
ColorHeaderBG string
|
||
ColorAccent string
|
||
ColorFooterText string
|
||
ColorFooterMuted string
|
||
ColorBodyBG string
|
||
}
|
||
|
||
type Branding struct {
|
||
AppName string
|
||
LogoURL string
|
||
ColorHeaderBG string
|
||
ColorAccent string
|
||
ColorFooterText string
|
||
ColorFooterMuted string
|
||
ColorBodyBG string
|
||
Direccion string
|
||
Telefono string
|
||
EmailContacto string
|
||
Year int
|
||
}
|
||
|
||
// Código del parámetro en tu tabla `parametros` que guarda la PLANTILLA HTML para la tarea.
|
||
// Ej: SELECT valor FROM parametros WHERE codigo = 'EMAIL_TEMPLATE_TASK';
|
||
const ParamEmailTaskTemplate = "EMAIL_TEMPLATE_TASK"
|
||
|
||
// BuildTaskSubject arma el asunto con el nombre de la app.
|
||
func BuildTaskSubject(appName string) string {
|
||
appName = strings.TrimSpace(appName)
|
||
if appName == "" {
|
||
return "Tarea asignada"
|
||
}
|
||
return fmt.Sprintf("[%s] Tarea asignada", appName)
|
||
}
|
||
|
||
// RenderTaskEmailHTML recibe la plantilla HTML (tplStr) y los datos (data) para la notificación de tarea.
|
||
// Si tplStr viene vacío, usa DefaultTaskTemplate como fallback.
|
||
func RenderTaskEmailHTML(tplStr string, data TaskTplData) (string, error) {
|
||
if strings.TrimSpace(tplStr) == "" {
|
||
tplStr = DefaultErrorSyncTemplate
|
||
}
|
||
tpl, err := template.New("email_task").Parse(tplStr)
|
||
if err != nil {
|
||
return "", fmt.Errorf("parse template: %w", err)
|
||
}
|
||
var buf bytes.Buffer
|
||
if err := tpl.Execute(&buf, data); err != nil {
|
||
return "", fmt.Errorf("execute template: %w", err)
|
||
}
|
||
return buf.String(), nil
|
||
}
|
||
|
||
func LoadBrandingAsignation(cfg ports.RedisConfigProvider, appName string) Branding {
|
||
get := func(key, def string) string {
|
||
if cfg == nil {
|
||
return def
|
||
}
|
||
v, _ := cfg.GetString("parametros:" + key)
|
||
v = strings.TrimSpace(v)
|
||
if v == "" {
|
||
return def
|
||
}
|
||
return v
|
||
}
|
||
if strings.TrimSpace(appName) == "" {
|
||
appName = get("EMAIL_APP_NAME", appName)
|
||
}
|
||
return Branding{
|
||
AppName: appName,
|
||
LogoURL: get("EMAIL_LOGO_URL", ""),
|
||
ColorHeaderBG: get("EMAIL_COLOR_HEADER_BG", "#0e1a2b"),
|
||
ColorAccent: get("EMAIL_COLOR_ACCENT", "#CBA135"),
|
||
ColorFooterText: get("EMAIL_COLOR_FOOTER_TEXT", "#ffffff"),
|
||
ColorFooterMuted: get("EMAIL_COLOR_FOOTER_MUTED", "#bfc6d1"),
|
||
ColorBodyBG: get("EMAIL_COLOR_BODY_BG", "#f4f6f8"),
|
||
Direccion: get("EMAIL_FOOTER_ADDRESS", ""),
|
||
Telefono: get("EMAIL_FOOTER_PHONE", ""),
|
||
EmailContacto: get("EMAIL_FOOTER_EMAIL", ""),
|
||
Year: time.Now().Year(),
|
||
}
|
||
}
|
||
|
||
// --- Plantilla por defecto para la notificación de tarea (Go template con {{.Campo}}) ---
|
||
const DefaultErrorSyncTemplate = `<!doctype html>
|
||
<html lang="es">
|
||
<head>
|
||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>{{.AppName}} – Error de Sincronización</title>
|
||
<style>@media (max-width:620px){.container{width:100% !important}.p-24{padding:20px !important}.h1{font-size:22px !important;line-height:28px !important}}</style>
|
||
</head>
|
||
<body style="margin:0;padding:0;background:#f4f6f8;color:#1c1c1c;">
|
||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background:#f4f6f8;">
|
||
<tr><td align="center" style="padding:24px;">
|
||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" class="container" style="width:600px;max-width:600px;background:#ffffff;border-radius:12px;overflow:hidden;box-shadow:0 4px 18px rgba(0,0,0,.06);">
|
||
<tr><td style="background:{{if .ColorHeaderBG}}{{.ColorHeaderBG}}{{else}}#0e1a2b{{end}};padding:20px 24px;" align="left">
|
||
{{if .LogoURL}}<img src="{{.LogoURL}}" width="140" alt="{{.AppName}}" style="display:block;border:0;max-width:100%">{{else}}<div style="font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:bold;color:#fff;">{{.AppName}}</div>{{end}}
|
||
</td></tr>
|
||
<tr><td class="p-24" style="padding:28px 32px 8px 32px;">
|
||
<h1 class="h1" style="margin:0 0 8px 0;font-family:Arial,Helvetica,sans-serif;font-size:24px;line-height:32px;color:#0e1a2b;">
|
||
Error de sincronización en {{.AppName}}
|
||
</h1>
|
||
<p style="margin:0;font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:22px;color:#4a4a4a;">
|
||
Hola <strong>{{.Nombre}}</strong>, hemos detectado un problema al intentar sincronizar los datos. Aquí están los detalles:
|
||
</p>
|
||
</td></tr>
|
||
<tr><td class="p-24" style="padding:8px 32px 0 32px;">
|
||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background:#f9fafb;border:1px solid #e6e8eb;border-radius:8px;">
|
||
<tr><td style="padding:16px 20px;">
|
||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%">
|
||
<tr><td style="font-family:Arial,Helvetica,sans-serif;font-size:13px;color:#6b7280;padding:4px 0;width:160px;">Descripción del Error</td>
|
||
<td style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#111827;padding:4px 0;"><strong>{{.ErrorDescripcion}}</strong></td></tr>
|
||
<tr><td style="font-family:Arial,Helvetica,sans-serif;font-size:13px;color:#6b7280;padding:4px 0;width:160px;">Hora del Error</td>
|
||
<td style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#111827;padding:4px 0;"><strong>{{.FechaError}}</strong></td></tr>
|
||
|
||
</table>
|
||
</td></tr>
|
||
</table>
|
||
</td></tr>
|
||
<br/><br/><br/><br/>
|
||
<tr><td style="background:{{if .ColorHeaderBG}}{{.ColorHeaderBG}}{{else}}#0e1a2b{{end}};padding:18px 24px;" align="left">
|
||
<p style="margin:0 0 6px 0;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;color:#ffffff;">{{.AppName}}</p>
|
||
<p style="margin:0;font-family:Arial,Helvetica,sans-serif;font-size:11px;line-height:18px;color:#bfc6d1;">
|
||
{{.Direccion}}{{if .Telefono}} · Tel. {{.Telefono}}{{end}}{{if .EmailContacto}} · {{.EmailContacto}}{{end}} · © {{.Year}} {{.AppName}}
|
||
</p>
|
||
</td></tr>
|
||
</table>
|
||
</td></tr>
|
||
</table>
|
||
</body></html>`
|