From bb7cf4aa7a65cb6c32788b6d7675f5178bd5679e Mon Sep 17 00:00:00 2001 From: Aine Date: Sun, 20 Nov 2022 00:31:59 +0200 Subject: [PATCH] cleanup From, To and Cc. Send replies to all recipients (To+Cc) --- bot/email.go | 31 ++++++++++++++++++++----------- email/email.go | 25 +++++++++++++++---------- email/utils.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/bot/email.go b/bot/email.go index 7aca141..b0f2554 100644 --- a/bot/email.go +++ b/bot/email.go @@ -181,19 +181,28 @@ func (b *Bot) SendEmailReply(ctx context.Context) { return } - queued, err := b.Sendmail(evt.ID, meta.From, meta.To, data) - if queued { - b.log.Error("cannot send email: %v", err) + var queued bool + var hasErr bool + tos := append(email.AddressList(meta.CC), meta.To) + for _, to := range tos { + queued, err = b.Sendmail(evt.ID, meta.From, to, data) + if queued { + b.log.Error("cannot send email: %v", err) + b.saveSentMetadata(ctx, queued, meta.ThreadID, eml, &cfg) + hasErr = true + continue + } + + if err != nil { + b.Error(ctx, evt.RoomID, "cannot send email: %v", err) + hasErr = true + continue + } + } + + if !hasErr { b.saveSentMetadata(ctx, queued, meta.ThreadID, eml, &cfg) - return } - - if err != nil { - b.Error(ctx, evt.RoomID, "cannot send email: %v", err) - return - } - - b.saveSentMetadata(ctx, queued, meta.ThreadID, eml, &cfg) } type parentEmail struct { diff --git a/email/email.go b/email/email.go index 4d503ae..45b482d 100644 --- a/email/email.go +++ b/email/email.go @@ -24,7 +24,7 @@ type Email struct { From string To string RcptTo string - CC string + CC []string Subject string Text string HTML string @@ -38,9 +38,9 @@ func New(messageID, inReplyTo, references, subject, from, to, rcptto, cc, text, MessageID: messageID, InReplyTo: inReplyTo, References: references, - From: from, - To: to, - CC: cc, + From: Address(from), + To: Address(to), + CC: AddressList(cc), RcptTo: rcptto, Subject: subject, Text: text, @@ -77,10 +77,10 @@ func FromEnvelope(rcptto string, envelope *enmime.Envelope) *Email { MessageID: envelope.GetHeader("Message-Id"), InReplyTo: envelope.GetHeader("In-Reply-To"), References: envelope.GetHeader("References"), - From: envelope.GetHeader("From"), - To: envelope.GetHeader("To"), - RcptTo: rcptto, - CC: envelope.GetHeader("Cc"), + From: Address(envelope.GetHeader("From")), + To: Address(envelope.GetHeader("To")), + RcptTo: Address(rcptto), + CC: AddressList(envelope.GetHeader("Cc")), Subject: envelope.GetHeader("Subject"), Text: envelope.Text, HTML: html, @@ -108,9 +108,9 @@ func (e *Email) Content(threadID id.EventID, options *ContentOptions) *event.Con text.WriteString(" ➡️ ") text.WriteString(e.To) } - if options.CC && e.CC != "" { + if options.CC && len(e.CC) > 0 { text.WriteString("\ncc: ") - text.WriteString(e.CC) + text.WriteString(strings.Join(e.CC, ", ")) } if options.Sender || options.Recipient || options.CC { text.WriteString("\n\n") @@ -170,6 +170,11 @@ func (e *Email) Compose(privkey string) string { if e.References != "" { mail = mail.Header("References", e.References) } + if len(e.CC) > 0 { + for _, addr := range e.CC { + mail = mail.CC("", addr) + } + } root, err := mail.Build() if err != nil { diff --git a/email/utils.go b/email/utils.go index 3d844c6..6a83f5f 100644 --- a/email/utils.go +++ b/email/utils.go @@ -22,6 +22,34 @@ func MessageID(eventID id.EventID, domain string) string { return fmt.Sprintf("<%s@%s>", eventID, domain) } +// Address gets email address from a valid email address notation (eg: "Jane Doe" -> jane@example.com) +func Address(email string) string { + addr, _ := mail.ParseAddress(email) //nolint:errcheck // if it fails here, nothing will help + if addr == nil { + return email + } + + return addr.Address +} + +// Address gets email address from a valid email address notation (eg: "Jane Doe" , john.doe@example.com -> jane@example.com, john.doe@example.com) +func AddressList(emailList string) []string { + if emailList == "" { + return []string{} + } + list, _ := mail.ParseAddressList(emailList) //nolint:errcheck // if it fails here, nothing will help + if len(list) == 0 { + return []string{} + } + + addrs := make([]string, 0, len(list)) + for _, addr := range list { + addrs = append(addrs, addr.Address) + } + + return addrs +} + // dateNow returns Date in RFC1123 with numeric timezone func dateNow(original ...time.Time) string { now := time.Now().UTC()