67 lines
1.9 KiB
Go
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
|
|
}
|