From 6fe1bcf384a34fdfc1704ff98ee5151a75d031a2 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 5 Jul 2017 19:45:56 +0200 Subject: pkg/email: add AddAddrContext/RemoveAddrContext Replace extractBugID function with more general AddAddrContext/RemoveAddrContext. --- pkg/email/parser.go | 69 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'pkg/email/parser.go') diff --git a/pkg/email/parser.go b/pkg/email/parser.go index 5d8c54d2c..f0297a588 100644 --- a/pkg/email/parser.go +++ b/pkg/email/parser.go @@ -50,11 +50,12 @@ func Parse(r io.Reader, ownEmail string) (*Email, error) { bugID := "" var ccList []string for _, addr := range append(cc, to...) { - bugID1, own := extractBugID(addr.Address, ownEmail) - if bugID == "" { - bugID = bugID1 - } - if !own { + cleaned, context, _ := RemoveAddrContext(addr.Address) + if cleaned == ownEmail { + if bugID == "" { + bugID = context + } + } else { ccList = append(ccList, addr.String()) } } @@ -87,31 +88,39 @@ func Parse(r io.Reader, ownEmail string) (*Email, error) { return email, nil } -// extractBugID extracts bug ID encoded in receiver email. -// We send emails from . -// from is potentially such email address, canonical is . -// This function returns BUG_ID_HASH, or an empty string if from does not contain -// the hash or is different from canonical. -func extractBugID(from, canonical string) (string, bool) { - if email, err := mail.ParseAddress(canonical); err == nil { - canonical = email.Address - } - canonical = strings.ToLower(canonical) - plusPos := strings.IndexByte(from, '+') - if plusPos == -1 { - return "", strings.ToLower(from) == canonical - } - atPos := strings.IndexByte(from[plusPos:], '@') - if atPos == -1 { - return "", false - } - user := from[:plusPos] - domain := from[plusPos+atPos:] - hash := from[plusPos+1 : plusPos+atPos] - if strings.ToLower(user+domain) != canonical { - return "", false - } - return hash, true +// AddAddrContext embeds context into local part of the provided email address using '+'. +// Returns the resulting email address. +func AddAddrContext(email, context string) (string, error) { + addr, err := mail.ParseAddress(email) + if err != nil { + return "", fmt.Errorf("failed to parse %q as email: %v", email, err) + } + at := strings.IndexByte(addr.Address, '@') + if at == -1 { + return "", fmt.Errorf("failed to parse %q as email: no @", email) + } + addr.Address = addr.Address[:at] + "+" + context + addr.Address[at:] + return addr.String(), nil +} + +// RemoveAddrContext extracts context after '+' from the local part of the provided email address. +// Returns address without the context and the context. +func RemoveAddrContext(email string) (string, string, error) { + addr, err := mail.ParseAddress(email) + if err != nil { + return "", "", fmt.Errorf("failed to parse %q as email: %v", email, err) + } + at := strings.IndexByte(addr.Address, '@') + if at == -1 { + return "", "", fmt.Errorf("failed to parse %q as email: no @", email) + } + plus := strings.LastIndexByte(addr.Address[:at], '+') + if plus == -1 { + return email, "", nil + } + context := addr.Address[plus+1 : at] + addr.Address = addr.Address[:plus] + addr.Address[at:] + return addr.String(), context, nil } // extractCommand extracts command to syzbot from email body. -- cgit mrf-deployment