fix(sieve): reconhece endereços automáticos com sufixo
Encontrado a correr o script guardado na caixa real antes de o pôr no ar. O Google envia os relatórios DMARC de noreply-dmarc-support@google.com, e a verificação só reconhecia a palavra exacta ou um sufixo com "+": a caixa teria respondido automaticamente a todos os relatórios diários que recebe. O prefixo passa a ser comparado com os separadores que os remetentes usam de facto - "+", "-", "." e "_" - e a lista cresce com os nomes correntes deste tipo de endereço. Continua a responder a uma pessoa cujo endereço apenas começa por uma dessas palavras, o que também tem teste: "bouncer" é gente, "bounces-123" não é. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d403c47a71
commit
caec501ec5
2 files changed
+58
-2
No files matched your search
@@ -392,3 +392,44 @@ func TestEscapedQuestionMarkIsALiteralCharacter(t *testing.T) {
|
|||||||
t.Errorf("the escaped question mark matched any character: %q", out.Folder)
|
t.Errorf("the escaped question mark matched any character: %q", out.Folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A reserved local part is recognised however the sender joined it to the rest
|
||||||
|
// of the address.
|
||||||
|
//
|
||||||
|
// Found by running the script stored on a real mailbox: Google sends its DMARC
|
||||||
|
// reports from noreply-dmarc-support@google.com, and matching only the exact
|
||||||
|
// word or a "+" suffix let that through - so the responder would have replied
|
||||||
|
// to every daily report, forever.
|
||||||
|
func TestVacationStaysSilentForReservedAddressesWithSuffixes(t *testing.T) {
|
||||||
|
senders := []string{
|
||||||
|
"noreply-dmarc-support@google.com",
|
||||||
|
"no-reply.billing@example.test",
|
||||||
|
"bounces+abc123@example.test",
|
||||||
|
"mailer-daemon@example.test",
|
||||||
|
"notifications-noreply@example.test",
|
||||||
|
"MAILER-DAEMON@EXAMPLE.TEST",
|
||||||
|
}
|
||||||
|
for _, sender := range senders {
|
||||||
|
out := evaluate(t, vacationScript, Message{
|
||||||
|
Sender: sender,
|
||||||
|
Headers: map[string][]string{"from": {sender}},
|
||||||
|
})
|
||||||
|
if out.Vacation != nil {
|
||||||
|
t.Errorf("would have replied to %s", sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The guard must not swallow a real person whose address merely starts with
|
||||||
|
// one of those words.
|
||||||
|
func TestVacationStillRepliesToAPersonWithASimilarAddress(t *testing.T) {
|
||||||
|
for _, sender := range []string{"noreplygames@example.test", "bouncer@example.test", "postmasters@example.test"} {
|
||||||
|
out := evaluate(t, vacationScript, Message{
|
||||||
|
Sender: sender,
|
||||||
|
Headers: map[string][]string{"from": {sender}},
|
||||||
|
})
|
||||||
|
if out.Vacation == nil {
|
||||||
|
t.Errorf("stayed silent for %s, which is a person", sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,10 +26,25 @@ func shouldAutoReply(msg Message) bool {
|
|||||||
}
|
}
|
||||||
// Addresses that exist to carry automated mail. Answering one is at best
|
// Addresses that exist to carry automated mail. Answering one is at best
|
||||||
// noise and at worst a loop.
|
// noise and at worst a loop.
|
||||||
for _, reserved := range []string{"mailer-daemon", "postmaster", "no-reply", "noreply", "bounce", "bounces"} {
|
//
|
||||||
if local == reserved || strings.HasPrefix(local, reserved+"+") {
|
// The prefix is matched against every separator a real sender uses, not
|
||||||
|
// just "+". Google sends its DMARC reports from
|
||||||
|
// noreply-dmarc-support@google.com: checking only for the exact word or a
|
||||||
|
// "+" suffix let that through, and this mailbox would have auto-replied to
|
||||||
|
// every daily report it receives.
|
||||||
|
for _, reserved := range []string{
|
||||||
|
"mailer-daemon", "mailerdaemon", "postmaster", "no-reply", "noreply",
|
||||||
|
"donotreply", "do-not-reply", "bounce", "bounces", "notification",
|
||||||
|
"notifications", "automated", "auto-reply", "autoreply",
|
||||||
|
} {
|
||||||
|
if local == reserved {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
for _, separator := range []string{"+", "-", ".", "_"} {
|
||||||
|
if strings.HasPrefix(local, reserved+separator) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Headers that say, in one way or another, "this was not typed by a
|
// Headers that say, in one way or another, "this was not typed by a
|
||||||
|
|||||||
Reference in new issue
Block a user