From 162b8401008b9a9a111a32187a20f494858ab84b Mon Sep 17 00:00:00 2001 From: Beowulf Date: Sun, 28 Apr 2024 00:33:03 +0200 Subject: [PATCH 1/4] Add inline attachments to comments If incoming email is configured and an email is sent, inline attachments are currently not added to the comment if it has the `Content-Disposition: inline` instead of `Content-Disposition: attachment` as e.g. with Apple Mail. This adds inline attachments (`Content-Disposition: inline`) that have a filename as attachment to the comment. Fixes #3496 --- services/mailer/incoming/incoming.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/mailer/incoming/incoming.go b/services/mailer/incoming/incoming.go index eade0cf27..a2352773a 100644 --- a/services/mailer/incoming/incoming.go +++ b/services/mailer/incoming/incoming.go @@ -367,6 +367,14 @@ func getContentFromMailReader(env *enmime.Envelope) *MailContent { Content: attachment.Content, }) } + for _, inline := range env.Inlines { + if inline.FileName != "" { + attachments = append(attachments, &Attachment{ + Name: inline.FileName, + Content: inline.Content, + }) + } + } return &MailContent{ Content: reply.FromText(env.Text), From b796694cd5df688105b490edd43aa923743b3113 Mon Sep 17 00:00:00 2001 From: Beowulf Date: Sun, 28 Apr 2024 14:11:17 +0200 Subject: [PATCH 2/4] Skip already handled incoming emails It seems like (at least on my machine) that every mail is processed twice. Added a check if the email is already handled and if so, skip it. --- services/mailer/incoming/incoming.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/mailer/incoming/incoming.go b/services/mailer/incoming/incoming.go index a2352773a..555cdfee8 100644 --- a/services/mailer/incoming/incoming.go +++ b/services/mailer/incoming/incoming.go @@ -219,6 +219,11 @@ loop: } err := func() error { + if handledSet.Contains(msg.SeqNum) { + log.Debug("Skipping already handled message") + return nil + } + r := msg.GetBody(section) if r == nil { return fmt.Errorf("could not get body from message: %w", err) From aeb544aff73430bdb475616468f13ecad6efa463 Mon Sep 17 00:00:00 2001 From: Beowulf Date: Sun, 28 Apr 2024 21:24:46 +0200 Subject: [PATCH 3/4] added test for reading inline attachments --- services/mailer/incoming/incoming.go | 7 +++- services/mailer/incoming/incoming_test.go | 40 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/services/mailer/incoming/incoming.go b/services/mailer/incoming/incoming.go index 555cdfee8..6530b7cc6 100644 --- a/services/mailer/incoming/incoming.go +++ b/services/mailer/incoming/incoming.go @@ -219,7 +219,7 @@ loop: } err := func() error { - if handledSet.Contains(msg.SeqNum) { + if isAlreadyHandled(handledSet, msg) { log.Debug("Skipping already handled message") return nil } @@ -282,6 +282,11 @@ loop: return nil } +// isAlreadyHandled tests if the message was already handled +func isAlreadyHandled(handledSet *imap.SeqSet, msg *imap.Message) bool { + return handledSet.Contains(msg.SeqNum) +} + // isAutomaticReply tests if the headers indicate an automatic reply func isAutomaticReply(env *enmime.Envelope) bool { autoSubmitted := env.GetHeader("Auto-Submitted") diff --git a/services/mailer/incoming/incoming_test.go b/services/mailer/incoming/incoming_test.go index 5d84848e3..f2bb7fc49 100644 --- a/services/mailer/incoming/incoming_test.go +++ b/services/mailer/incoming/incoming_test.go @@ -7,10 +7,24 @@ import ( "strings" "testing" + "github.com/emersion/go-imap" "github.com/jhillyerd/enmime" "github.com/stretchr/testify/assert" ) +func TestNotHandleTwice(t *testing.T) { + handledSet := new(imap.SeqSet) + msg := imap.NewMessage(90, []imap.FetchItem{imap.FetchBody}) + + handled := isAlreadyHandled(handledSet, msg) + assert.Equal(t, false, handled) + + handledSet.AddNum(msg.SeqNum) + + handled = isAlreadyHandled(handledSet, msg) + assert.Equal(t, true, handled) +} + func TestIsAutomaticReply(t *testing.T) { cases := []struct { Headers map[string]string @@ -95,6 +109,32 @@ func TestGetContentFromMailReader(t *testing.T) { assert.Equal(t, "attachment.txt", content.Attachments[0].Name) assert.Equal(t, []byte("attachment content"), content.Attachments[0].Content) + mailString = "Content-Type: multipart/mixed; boundary=message-boundary\r\n" + + "\r\n" + + "--message-boundary\r\n" + + "Content-Type: multipart/alternative; boundary=text-boundary\r\n" + + "\r\n" + + "--text-boundary\r\n" + + "Content-Type: text/plain\r\n" + + "Content-Disposition: inline\r\n" + + "\r\n" + + "mail content\r\n" + + "--text-boundary--\r\n" + + "--message-boundary\r\n" + + "Content-Type: text/plain\r\n" + + "Content-Disposition: inline; filename=attachment.txt\r\n" + + "\r\n" + + "attachment content\r\n" + + "--message-boundary--\r\n" + + env, err = enmime.ReadEnvelope(strings.NewReader(mailString)) + assert.NoError(t, err) + content = getContentFromMailReader(env) + assert.Equal(t, "mail content", content.Content) + assert.Len(t, content.Attachments, 1) + assert.Equal(t, "attachment.txt", content.Attachments[0].Name) + assert.Equal(t, []byte("attachment content"), content.Attachments[0].Content) + mailString = "Content-Type: multipart/mixed; boundary=message-boundary\r\n" + "\r\n" + "--message-boundary\r\n" + From 34134df3a7b9457f091e2e6fc18bdb0cd7dbffb9 Mon Sep 17 00:00:00 2001 From: Beowulf Date: Tue, 30 Apr 2024 12:05:22 +0200 Subject: [PATCH 4/4] added release notes --- release-notes/8.0.0/fix/3504.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 release-notes/8.0.0/fix/3504.md diff --git a/release-notes/8.0.0/fix/3504.md b/release-notes/8.0.0/fix/3504.md new file mode 100644 index 000000000..8ece1557a --- /dev/null +++ b/release-notes/8.0.0/fix/3504.md @@ -0,0 +1 @@ +Fixed that inline attachments of emails (as they occur for example with Apple Mail) are not attached to comments.