Los clientes escriben a soporte@ desde su correo de siempre. Hasta ahora eso solo llegaba si un proveedor (SendGrid/Mailgun) nos hacía POST; si nadie lo configuraba, los correos quedaban sin leer en el buzón. Ahora el cron entra al buzón cada 2 minutos, baja los no leídos, abre ticket (o los engancha al hilo si son respuesta) y los marca como leídos. La lógica de ingesta se movió a services para que webhook e IMAP se comporten igual. La contraseña del buzón se guarda cifrada (AES-GCM con APP_KEY) y no vuelve al navegador. De paso, dos bugs que impedían guardar la configuración: el formulario mandaba id=0 (gorm.Model serializa "ID"), así que cada guardado creaba una fila nueva en vez de editar la que se usa; y Updates con struct ignoraba los booleanos en false, así que desactivar algo no tenía efecto. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
57 lines
1.6 KiB
Go
57 lines
1.6 KiB
Go
package services
|
|
|
|
import "testing"
|
|
|
|
func TestParsearCorreoMultipartQuotedPrintable(t *testing.T) {
|
|
crudo := "From: =?UTF-8?Q?Juan_P=C3=A9rez?= <juan@cliente.com>\r\n" +
|
|
"Subject: =?UTF-8?Q?No_puedo_entrar_a_la_plataforma?=\r\n" +
|
|
"Message-Id: <abc123@cliente.com>\r\n" +
|
|
"Content-Type: multipart/alternative; boundary=\"XX\"\r\n" +
|
|
"\r\n" +
|
|
"--XX\r\n" +
|
|
"Content-Type: text/plain; charset=UTF-8\r\n" +
|
|
"Content-Transfer-Encoding: quoted-printable\r\n" +
|
|
"\r\n" +
|
|
"Hola, la contrase=C3=B1a no me sirve.\r\n" +
|
|
"\r\n" +
|
|
"El 3 de marzo, Soporte escribi=C3=B3:\r\n" +
|
|
"> proba de nuevo\r\n" +
|
|
"--XX\r\n" +
|
|
"Content-Type: text/html; charset=UTF-8\r\n" +
|
|
"\r\n" +
|
|
"<p>ignorame</p>\r\n" +
|
|
"--XX--\r\n"
|
|
|
|
c, err := parsearCorreo([]byte(crudo))
|
|
if err != nil {
|
|
t.Fatalf("parsearCorreo: %v", err)
|
|
}
|
|
if c.FromName != "Juan Pérez" {
|
|
t.Errorf("FromName = %q, want %q", c.FromName, "Juan Pérez")
|
|
}
|
|
if ExtraerEmail(c.From) != "juan@cliente.com" {
|
|
t.Errorf("From = %q", c.From)
|
|
}
|
|
if c.Subject != "No puedo entrar a la plataforma" {
|
|
t.Errorf("Subject = %q", c.Subject)
|
|
}
|
|
if c.MessageID != "<abc123@cliente.com>" {
|
|
t.Errorf("MessageID = %q", c.MessageID)
|
|
}
|
|
// Cuerpo decodificado, sin la cita del hilo anterior ni el HTML.
|
|
if c.Texto != "Hola, la contraseña no me sirve." {
|
|
t.Errorf("Texto = %q", c.Texto)
|
|
}
|
|
}
|
|
|
|
func TestParsearCorreoPlano(t *testing.T) {
|
|
crudo := "From: ana@cliente.com\r\nSubject: Consulta\r\n\r\nHola\r\n"
|
|
c, err := parsearCorreo([]byte(crudo))
|
|
if err != nil {
|
|
t.Fatalf("parsearCorreo: %v", err)
|
|
}
|
|
if c.Texto != "Hola" || c.Subject != "Consulta" {
|
|
t.Errorf("got %+v", c)
|
|
}
|
|
}
|