Files
emcli/internal/mail/imap_unit_test.go
T
steve 8379fddbb2 perf(mail): fetch only headers for list/search (no body download)
list and search now fetch BODY.PEEK[HEADER] + BODYSTRUCTURE instead of the
whole RFC822 message, so listing a large mailbox no longer downloads every
message body and attachment. Header parsing reuses the same go-message path
(RFC2047 decoding/formatting preserved); has_attachments is derived from the
BODYSTRUCTURE tree. FetchFull keeps fetching the full message for get.

Validated end-to-end against a live IMAP account: list/search/get output
identical to the prior full-fetch behaviour, has_attachments correct.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 07:47:27 +01:00

80 lines
1.9 KiB
Go

package mail
import (
"testing"
"github.com/emersion/go-imap"
)
func TestHasAttachment(t *testing.T) {
cases := []struct {
name string
bs *imap.BodyStructure
want bool
}{
{"nil", nil, false},
{
"single inline text",
&imap.BodyStructure{MIMEType: "text", MIMESubType: "plain", Disposition: "inline"},
false,
},
{
"single attachment",
&imap.BodyStructure{MIMEType: "application", MIMESubType: "pdf", Disposition: "attachment"},
true,
},
{
"disposition case-insensitive",
&imap.BodyStructure{MIMEType: "image", MIMESubType: "png", Disposition: "ATTACHMENT"},
true,
},
{
"multipart with one attachment child",
&imap.BodyStructure{
MIMEType: "multipart",
MIMESubType: "mixed",
Parts: []*imap.BodyStructure{
{MIMEType: "text", MIMESubType: "plain", Disposition: "inline"},
{MIMEType: "application", MIMESubType: "octet-stream", Disposition: "attachment"},
},
},
true,
},
{
"multipart all inline",
&imap.BodyStructure{
MIMEType: "multipart",
MIMESubType: "alternative",
Parts: []*imap.BodyStructure{
{MIMEType: "text", MIMESubType: "plain", Disposition: "inline"},
{MIMEType: "text", MIMESubType: "html", Disposition: "inline"},
},
},
false,
},
{
"nested multipart with deep attachment",
&imap.BodyStructure{
MIMEType: "multipart",
MIMESubType: "mixed",
Parts: []*imap.BodyStructure{
{
MIMEType: "multipart",
MIMESubType: "alternative",
Parts: []*imap.BodyStructure{
{MIMEType: "text", MIMESubType: "plain", Disposition: "inline"},
{MIMEType: "application", MIMESubType: "pdf", Disposition: "attachment"},
},
},
},
},
true,
},
}
for _, c := range cases {
if got := hasAttachment(c.bs); got != c.want {
t.Errorf("%s: hasAttachment = %v, want %v", c.name, got, c.want)
}
}
}