forgejo/services/mailer/incoming/incoming_test.go
Beowulf 2810b9ae0a Replace reply with a forked version to fix the cut-off of the incoming mail text (#3747)
replace reply with forgejos forked version

If plain text is selected as the message format in e.g. Apple Mail, the inline attachments are no longer at the end of the mail, but instead directly where they are in the mail. When parsing the mail, these inline attachments are replaced by "--". The new reply version no longer cuts the text at the first "--".

Tests for this are present in reply (7dc5750c6d).

Fixes https://codeberg.org/forgejo/forgejo/issues/3496#issuecomment-1798416

---

Additionally, I reduced the allocations for the inline attachments.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3747
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Beowulf <beowulf@beocode.eu>
Co-committed-by: Beowulf <beowulf@beocode.eu>
2024-05-13 21:24:58 +00:00

191 lines
5.2 KiB
Go

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package incoming
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
Expected bool
}{
{
Headers: map[string]string{},
Expected: false,
},
{
Headers: map[string]string{
"Auto-Submitted": "no",
},
Expected: false,
},
{
Headers: map[string]string{
"Auto-Submitted": "yes",
},
Expected: true,
},
{
Headers: map[string]string{
"X-Autoreply": "no",
},
Expected: false,
},
{
Headers: map[string]string{
"X-Autoreply": "yes",
},
Expected: true,
},
{
Headers: map[string]string{
"X-Autorespond": "yes",
},
Expected: true,
},
}
for _, c := range cases {
b := enmime.Builder().
From("Dummy", "dummy@gitea.io").
To("Dummy", "dummy@gitea.io")
for k, v := range c.Headers {
b = b.Header(k, v)
}
root, err := b.Build()
assert.NoError(t, err)
env, err := enmime.EnvelopeFromPart(root)
assert.NoError(t, err)
assert.Equal(t, c.Expected, isAutomaticReply(env))
}
}
func TestGetContentFromMailReader(t *testing.T) {
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: attachment; 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" +
"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" +
"Content-Type: text/html\r\n" +
"Content-Disposition: inline; filename=attachment.html\r\n" +
"\r\n" +
"<p>html attachment content</p>\r\n" +
"--message-boundary\r\n" +
"Content-Type: image/png\r\n" +
"Content-Disposition: inline; filename=attachment.png\r\n" +
"Content-Transfer-Encoding: base64\r\n" +
"\r\n" +
"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII\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\n--\nattachment content", content.Content)
assert.Len(t, content.Attachments, 2)
assert.Equal(t, "attachment.html", content.Attachments[0].Name)
assert.Equal(t, []byte("<p>html attachment content</p>"), content.Attachments[0].Content)
assert.Equal(t, "attachment.png", content.Attachments[1].Name)
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/html\r\n" +
"Content-Disposition: inline\r\n" +
"\r\n" +
"<p>mail content</p>\r\n" +
"--text-boundary--\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.Empty(t, content.Attachments)
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 without signature\r\n" +
"----\r\n" +
"signature\r\n" +
"--text-boundary--\r\n" +
"--message-boundary--\r\n"
env, err = enmime.ReadEnvelope(strings.NewReader(mailString))
assert.NoError(t, err)
content = getContentFromMailReader(env)
assert.NoError(t, err)
assert.Equal(t, "mail content without signature", content.Content)
assert.Empty(t, content.Attachments)
}