aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/email/parser.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2022-11-17 18:47:15 +0000
committerAleksandr Nogikh <wp32pw@gmail.com>2022-11-21 16:36:47 +0100
commitb42d86eb82846fe9a1d830bc5df4869a5d285be3 (patch)
tree2851c3bec207c88603935828e87122e2223d8ade /pkg/email/parser.go
parent6989c64a48428b1563c52419d978dac64c53434f (diff)
pkg/email: detect author and mailing list
Handle two types of mailing list responses: * From contains the original author. * From is replaced by the mailing list.
Diffstat (limited to 'pkg/email/parser.go')
-rw-r--r--pkg/email/parser.go66
1 files changed, 47 insertions, 19 deletions
diff --git a/pkg/email/parser.go b/pkg/email/parser.go
index 6c0fb22d4..ff7eeb7ec 100644
--- a/pkg/email/parser.go
+++ b/pkg/email/parser.go
@@ -22,9 +22,9 @@ type Email struct {
MessageID string
Link string
Subject string
- From string
+ MailingList string
+ Author string
Cc []string
- Sender string
Body string // text/plain part
Patch string // attached patch, if any
Command Command // command to bot
@@ -52,7 +52,18 @@ const (
var groupsLinkRe = regexp.MustCompile("\nTo view this discussion on the web visit" +
" (https://groups\\.google\\.com/.*?)\\.(?:\r)?\n")
-func Parse(r io.Reader, ownEmails []string) (*Email, error) {
+func prepareEmails(list []string) map[string]bool {
+ ret := make(map[string]bool)
+ for _, email := range list {
+ ret[email] = true
+ if addr, err := mail.ParseAddress(email); err == nil {
+ ret[addr.Address] = true
+ }
+ }
+ return ret
+}
+
+func Parse(r io.Reader, ownEmails []string, goodLists []string) (*Email, error) {
msg, err := mail.ReadMessage(r)
if err != nil {
return nil, fmt.Errorf("failed to read email: %v", err)
@@ -70,13 +81,7 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
cc, _ := msg.Header.AddressList("Cc")
bugID := ""
var ccList []string
- ownAddrs := make(map[string]bool)
- for _, email := range ownEmails {
- ownAddrs[email] = true
- if addr, err := mail.ParseAddress(email); err == nil {
- ownAddrs[addr.Address] = true
- }
- }
+ ownAddrs := prepareEmails(ownEmails)
fromMe := false
for _, addr := range from {
cleaned, _, _ := RemoveAddrContext(addr.Address)
@@ -84,7 +89,16 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
fromMe = true
}
}
- for _, addr := range append(append(cc, to...), from...) {
+
+ originalFrom := ""
+ // Ignore error since the header might not be present.
+ originalFroms, _ := msg.Header.AddressList("X-Original-From")
+ if len(originalFroms) > 0 {
+ originalFrom = originalFroms[0].String()
+ }
+
+ rawCcList := append(append(append(cc, to...), from...), originalFroms...)
+ for _, addr := range rawCcList {
cleaned, context, _ := RemoveAddrContext(addr.Address)
if addr, err := mail.ParseAddress(cleaned); err == nil {
cleaned = addr.Address
@@ -100,12 +114,9 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
ccList = MergeEmailLists(ccList)
sender := ""
- senders, err := msg.Header.AddressList("Sender")
- if err != nil {
- if err != mail.ErrHeaderNotPresent {
- return nil, err
- }
- } else if len(senders) > 0 {
+ // Ignore error since the header might not be present.
+ senders, _ := msg.Header.AddressList("Sender")
+ if len(senders) > 0 {
sender = senders[0].Address
}
@@ -133,14 +144,31 @@ func Parse(r io.Reader, ownEmails []string) (*Email, error) {
if match := groupsLinkRe.FindStringSubmatchIndex(bodyStr); match != nil {
link = bodyStr[match[2]:match[3]]
}
+
+ author := CanonicalEmail(from[0].Address)
+ mailingList := ""
+
+ goodListsMap := prepareEmails(goodLists)
+ if goodListsMap[author] {
+ // In some cases, the mailing list would change From and introduce X-Original-From.
+ mailingList = author
+ if originalFrom != "" {
+ author = CanonicalEmail(originalFrom)
+ }
+ // Not sure if `else` can happen here, but let it be mailingList == author in this case.
+ } else if goodListsMap[CanonicalEmail(sender)] {
+ // In other cases, the mailing list would preserve From and just change Sender.
+ mailingList = CanonicalEmail(sender)
+ }
+
email := &Email{
BugID: bugID,
MessageID: msg.Header.Get("Message-ID"),
Link: link,
+ Author: author,
+ MailingList: mailingList,
Subject: subject,
- From: CanonicalEmail(from[0].Address),
Cc: ccList,
- Sender: sender,
Body: bodyStr,
Patch: patch,
Command: cmd,