make thread replies CC-aware and multi-domain aware

This commit is contained in:
Aine
2022-11-19 17:38:13 +02:00
parent 5fe8603506
commit 8aac16aca8
3 changed files with 44 additions and 12 deletions

View File

@@ -438,7 +438,7 @@ func (b *Bot) runSend(ctx context.Context) {
from := mailbox + "@" + domain from := mailbox + "@" + domain
ID := email.MessageID(evt.ID, domain) ID := email.MessageID(evt.ID, domain)
for _, to := range tos { for _, to := range tos {
eml := email.New(ID, "", " "+ID, subject, from, to, body, htmlBody, nil) eml := email.New(ID, "", " "+ID, subject, from, to, to, "", body, htmlBody, nil)
data := eml.Compose(b.getBotSettings().DKIMPrivateKey()) data := eml.Compose(b.getBotSettings().DKIMPrivateKey())
if data == "" { if data == "" {
b.SendError(ctx, evt.RoomID, "email body is empty") b.SendError(ctx, evt.RoomID, "email body is empty")

View File

@@ -155,13 +155,8 @@ func (b *Bot) SendEmailReply(ctx context.Context) {
b.lock(evt.RoomID.String()) b.lock(evt.RoomID.String())
defer b.unlock(evt.RoomID.String()) defer b.unlock(evt.RoomID.String())
fromMailbox := mailbox + "@" + domain
meta := b.getParentEmail(evt, domain) meta := b.getParentEmail(evt, domain)
// when email was sent from matrix and reply was sent from matrix again meta.fixtofrom(mailbox, domain, b.domains)
if fromMailbox != meta.From {
meta.To = meta.From
}
meta.From = fromMailbox
if meta.To == "" { if meta.To == "" {
b.Error(ctx, evt.RoomID, "cannot find parent email and continue the thread. Please, start a new email thread") b.Error(ctx, evt.RoomID, "cannot find parent email and continue the thread. Please, start a new email thread")
@@ -181,7 +176,7 @@ func (b *Bot) SendEmailReply(ctx context.Context) {
meta.MessageID = email.MessageID(evt.ID, domain) meta.MessageID = email.MessageID(evt.ID, domain)
meta.References = meta.References + " " + meta.MessageID meta.References = meta.References + " " + meta.MessageID
b.log.Debug("send email reply: %+v", meta) b.log.Debug("send email reply: %+v", meta)
eml := email.New(meta.MessageID, meta.InReplyTo, meta.References, meta.Subject, meta.From, meta.To, body, htmlBody, nil) eml := email.New(meta.MessageID, meta.InReplyTo, meta.References, meta.Subject, meta.From, meta.To, meta.RcptTo, meta.CC, body, htmlBody, nil)
data := eml.Compose(b.getBotSettings().DKIMPrivateKey()) data := eml.Compose(b.getBotSettings().DKIMPrivateKey())
if data == "" { if data == "" {
b.SendError(ctx, evt.RoomID, "email body is empty") b.SendError(ctx, evt.RoomID, "email body is empty")
@@ -208,11 +203,45 @@ type parentEmail struct {
ThreadID id.EventID ThreadID id.EventID
From string From string
To string To string
RcptTo string
CC string
InReplyTo string InReplyTo string
References string References string
Subject string Subject string
} }
// fixtofrom attempts to "fix" or rather reverse the To, From and CC headers
// of parent email by using parent email as metadata source for a new email
// that will be sent from postmoogle.
// To do so, we need to reverse From and To headers, but Cc should be adjusted as well,
// thus that hacky workaround below:
func (e *parentEmail) fixtofrom(newSenderMailbox string, preferredDomain string, domains []string) {
newSenders := make(map[string]struct{}, len(domains))
newSenderPref := newSenderMailbox + "@" + preferredDomain
for _, domain := range domains {
sender := newSenderMailbox + "@" + domain
newSenders[sender] = struct{}{}
}
originalFrom := e.From
// reverse From if needed
_, ok := newSenders[e.From]
if !ok {
e.From = newSenderPref
}
// reverse To if needed
_, ok = newSenders[e.To]
if ok {
e.To = originalFrom
}
// replace previous recipient of the email which is sender now with the original From
for newSender := range newSenders {
if strings.Contains(e.CC, newSender) {
e.CC = strings.ReplaceAll(e.CC, newSender, originalFrom)
}
}
}
func (b *Bot) getParentEvent(evt *event.Event) (id.EventID, *event.Event) { func (b *Bot) getParentEvent(evt *event.Event) (id.EventID, *event.Event) {
content := evt.Content.AsMessage() content := evt.Content.AsMessage()
threadID := utils.EventParent(evt.ID, content) threadID := utils.EventParent(evt.ID, content)
@@ -249,8 +278,8 @@ func (b *Bot) getParentEvent(evt *event.Event) (id.EventID, *event.Event) {
return threadID, decrypted return threadID, decrypted
} }
func (b *Bot) getParentEmail(evt *event.Event, domain string) parentEmail { func (b *Bot) getParentEmail(evt *event.Event, domain string) *parentEmail {
var parent parentEmail parent := &parentEmail{}
threadID, parentEvt := b.getParentEvent(evt) threadID, parentEvt := b.getParentEvent(evt)
parent.ThreadID = threadID parent.ThreadID = threadID
if parentEvt == nil { if parentEvt == nil {
@@ -263,6 +292,8 @@ func (b *Bot) getParentEmail(evt *event.Event, domain string) parentEmail {
parent.MessageID = email.MessageID(parentEvt.ID, domain) parent.MessageID = email.MessageID(parentEvt.ID, domain)
parent.From = utils.EventField[string](&parentEvt.Content, eventFromKey) parent.From = utils.EventField[string](&parentEvt.Content, eventFromKey)
parent.To = utils.EventField[string](&parentEvt.Content, eventToKey) parent.To = utils.EventField[string](&parentEvt.Content, eventToKey)
parent.CC = utils.EventField[string](&parentEvt.Content, eventCcKey)
parent.RcptTo = utils.EventField[string](&parentEvt.Content, eventRcptToKey)
parent.InReplyTo = utils.EventField[string](&parentEvt.Content, eventMessageIDkey) parent.InReplyTo = utils.EventField[string](&parentEvt.Content, eventMessageIDkey)
parent.References = utils.EventField[string](&parentEvt.Content, eventReferencesKey) parent.References = utils.EventField[string](&parentEvt.Content, eventReferencesKey)
if parent.InReplyTo == "" { if parent.InReplyTo == "" {

View File

@@ -32,7 +32,7 @@ type Email struct {
} }
// New constructs Email object // New constructs Email object
func New(messageID, inReplyTo, references, subject, from, to, text, html string, files []*utils.File) *Email { func New(messageID, inReplyTo, references, subject, from, to, rcptto, cc, text, html string, files []*utils.File) *Email {
email := &Email{ email := &Email{
Date: dateNow(), Date: dateNow(),
MessageID: messageID, MessageID: messageID,
@@ -40,7 +40,8 @@ func New(messageID, inReplyTo, references, subject, from, to, text, html string,
References: references, References: references,
From: from, From: from,
To: to, To: to,
RcptTo: to, CC: cc,
RcptTo: rcptto,
Subject: subject, Subject: subject,
Text: text, Text: text,
HTML: html, HTML: html,