Files
soft_usite/pkg/services/soporte_imap_test.go
Lizandro GuarnizoandClaude Opus 5 8c3ab79e88 feat(soporte): leer el buzón por IMAP, no solo esperar el webhook
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>
2026-08-17 18:36:08 -05:00

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)
}
}