Files
mailgoserver/internal/mailstore/resolve.go
T

67 lines
1.9 KiB
Go

package mailstore
import (
"strings"
"mailgoserver/internal/db"
)
// ResolveRecipient looks up a local mailbox for addr: its primary email first, then
// any active alias, then a "+tag" sub-address stripped down to its base mailbox, then
// finally the recipient's domain's opt-in catch-all mailbox if one is configured — so
// mail sent to an alias, "user+tag@domain", or (if enabled) any other address on the
// domain still lands somewhere sensible instead of bouncing.
func (s *Store) ResolveRecipient(addr string) (*db.Mailbox, error) {
mbox, err := s.DB.GetMailboxByEmail(addr)
if err != nil || mbox != nil {
return mbox, err
}
if alias, err := s.DB.GetAliasByEmail(addr); err != nil {
return nil, err
} else if alias != nil {
return s.DB.GetMailboxByID(alias.MailboxID)
}
// Sub-addressing only applies to a mailbox's own primary address (not aliases) —
// checked above first, so an address that's genuinely registered with a literal
// "+" in its local-part still wins over this fallback.
if base, ok := stripSubaddressTag(addr); ok {
if mbox, err := s.DB.GetMailboxByEmail(base); err != nil || mbox != nil {
return mbox, err
}
}
domain := domainOfEmail(addr)
if domain == "" {
return nil, nil
}
dom, err := s.DB.GetDomainByName(domain)
if err != nil || dom == nil || dom.CatchallMailboxID == nil {
return nil, err
}
return s.DB.GetMailboxByID(*dom.CatchallMailboxID)
}
func domainOfEmail(addr string) string {
i := strings.LastIndex(addr, "@")
if i < 0 {
return ""
}
return addr[i+1:]
}
// stripSubaddressTag turns "user+tag@domain" into "user@domain", ok=true — or
// ok=false if addr has no "+" in its local-part to strip.
func stripSubaddressTag(addr string) (base string, ok bool) {
at := strings.LastIndex(addr, "@")
if at < 0 {
return "", false
}
local, domain := addr[:at], addr[at:]
plus := strings.Index(local, "+")
if plus < 0 {
return "", false
}
return local[:plus] + domain, true
}