fix(vacation): descodifica o assunto e responde a cada pessoa uma vez
O assunto que chegou a uma caixa real: "Fora do escritorio: Re:
=?UTF-8?Q?Re=3A_Fora_do_escrit=C3=B3rio?=". Duas coisas erradas, e a
segunda maior do que parece.
Um assunto com acento viaja como palavra codificada (RFC 2047). Colei o
cabecalho em bruto, portanto aquilo foi lido tal e qual por uma pessoa.
E foi tambem o que derrotou a verificacao do "Re:" ja existente:
codificado, todo o assunto comeca por "=?", nunca por "Re:", e por isso
foi acrescentado outro por cima. Descodificar corrige os dois sintomas
de uma vez. Os prefixos acumulados ("Re: RE: Re:") passam a ser
reduzidos a um.
O que estava por tras: aquele assunto era "Re: Fora do escritorio" -
alguem tinha respondido a propria mensagem automatica, e ela respondeu
de novo. Faltava a supressao por remetente. O RFC 5230 seccao 4.1 pede
exactamente isto e propoe sete dias: sem ela, uma conversa de cinco
mensagens produzia cinco copias do mesmo aviso, e quem respondesse ao
aviso recebia outro - que e como uma pessoa e um respondedor automatico
acabam a falar um para o outro indefinidamente.
A supressao falha aberta: um registo que nao se consegue ler deixa a
resposta sair. Ser avisado duas vezes e uma falha menor do que nunca
saber que a caixa esta ausente, que e o proposito da funcionalidade. O
envio so e registado depois de a resposta estar mesmo na fila, para que
um envio falhado nao silencie a mensagem seguinte da mesma pessoa.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
866bd21846
commit
e4491479ef
10 files changed
+451
-6
No files matched your search
@@ -218,3 +218,65 @@ func TestDeliveredMessageProducesAThreadedReply(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- the subject as it actually arrives ----------------------------------
|
||||
|
||||
// A subject with an accent travels as an RFC 2047 encoded word. Pasting the
|
||||
// raw header into the reply put "=?UTF-8?Q?Re=3A_Fora...?=" in front of a real
|
||||
// person, and it also defeated the check for an existing "Re:" - encoded, the
|
||||
// subject starts with "=?", so a second "Re:" was added on top.
|
||||
func TestOriginalSubjectIsDecodedBeforeUse(t *testing.T) {
|
||||
reply := replyTo("<abc@example.test>", "")
|
||||
reply.OriginalSubject = "=?UTF-8?Q?Proposta_comercial?="
|
||||
|
||||
subject := vacationHeaders(t, reply)["subject"]
|
||||
decoded := decodeHeaderValue(subject)
|
||||
|
||||
if strings.Contains(decoded, "=?UTF-8?") {
|
||||
t.Errorf("an encoded word reached the reader: %q", decoded)
|
||||
}
|
||||
if !strings.Contains(decoded, "Proposta comercial") {
|
||||
t.Errorf("subject %q", decoded)
|
||||
}
|
||||
}
|
||||
|
||||
// The same, for the "Re:" that is only visible once decoded.
|
||||
func TestEncodedReplyPrefixIsNotDuplicated(t *testing.T) {
|
||||
reply := replyTo("<abc@example.test>", "")
|
||||
// "Re: Fora do escritorio", encoded the way a mail client sends it.
|
||||
reply.OriginalSubject = "=?UTF-8?Q?Re=3A_Fora_do_escrit=C3=B3rio?="
|
||||
|
||||
decoded := decodeHeaderValue(vacationHeaders(t, reply)["subject"])
|
||||
if strings.Count(strings.ToLower(decoded), "re:") > 1 {
|
||||
t.Errorf("stacked Re: prefixes: %q", decoded)
|
||||
}
|
||||
}
|
||||
|
||||
// A thread that has been round several times accumulates prefixes. The reply
|
||||
// carries one at most.
|
||||
func TestManyReplyPrefixesCollapseToOne(t *testing.T) {
|
||||
reply := replyTo("<abc@example.test>", "")
|
||||
reply.OriginalSubject = "Re: RE: Re: Proposta comercial"
|
||||
|
||||
decoded := decodeHeaderValue(vacationHeaders(t, reply)["subject"])
|
||||
if strings.Count(strings.ToLower(decoded), "re:") > 1 {
|
||||
t.Errorf("prefixes were not collapsed: %q", decoded)
|
||||
}
|
||||
if !strings.Contains(decoded, "Proposta comercial") {
|
||||
t.Errorf("the subject itself was lost: %q", decoded)
|
||||
}
|
||||
}
|
||||
|
||||
// The reply must not quote back the out-of-office text as though it were the
|
||||
// subject of the conversation, which is what happens when someone replies to
|
||||
// the automatic message itself.
|
||||
func TestReplyToTheAutoReplyDoesNotEchoItself(t *testing.T) {
|
||||
reply := replyTo("<abc@example.test>", "")
|
||||
reply.Subject = "Fora do escritorio"
|
||||
reply.OriginalSubject = "Re: Fora do escritorio"
|
||||
|
||||
decoded := decodeHeaderValue(vacationHeaders(t, reply)["subject"])
|
||||
if strings.Count(strings.ToLower(decoded), "fora do escritorio") > 1 {
|
||||
t.Errorf("the reply repeated its own subject back: %q", decoded)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user