package usecase import ( "context" "log" "strings" "github.com/google/uuid" "lambdamail/protocols/internal/application/port" ) // SetTrustedSenders lets a mailbox's trusted senders skip the spam folder. // Optional: without it a spam verdict files the message in Junk for everyone. func (uc *ProcessInboundEmailUseCase) SetTrustedSenders(trusted port.TrustedSenders) { uc.trusted = trusted } // rescuedFromJunk reports whether a message the spam filter condemned should // reach the inbox because this mailbox trusts who it is from. // // The From header is what a person trusts, and it is also the easiest field to // forge, so it only counts when the message proves it came from that address: // DMARC passed, or SPF passed for the very domain written in From. Without the // proof, trusting a contact would hand a spammer a way in by writing that // contact's address on their mail. // // Fails closed: a lookup that errors leaves the message in Junk, which is where // it was going anyway. func (uc *ProcessInboundEmailUseCase) rescuedFromJunk( ctx context.Context, mailboxID uuid.UUID, fromAddress, envelopeSender string, auth port.InboundAuthResult, ) bool { if uc.trusted == nil || fromAddress == "" { return false } if !provesSender(fromAddress, envelopeSender, auth) { return false } trusted, err := uc.trusted.IsTrusted(ctx, mailboxID, fromAddress) if err != nil { log.Printf("trusted senders: %v", err) return false } return trusted } func provesSender(fromAddress, envelopeSender string, auth port.InboundAuthResult) bool { if auth.DMARC == port.AuthResultPass { return true } return auth.SPF == port.AuthResultPass && domainOf(fromAddress) != "" && domainOf(fromAddress) == domainOf(normaliseAddress(envelopeSender)) } func domainOf(address string) string { at := strings.LastIndex(address, "@") if at < 0 || at == len(address)-1 { return "" } return address[at+1:] }