blob: 3e66364873b87d2ff1e5c24d8147338cdb4ae878 [file] [log] [blame]
Dusan Kasanc2129de2017-04-13 10:42:21 +02001package parsemail
Dusan Kasan17e497e2017-04-10 22:44:22 +02002
3import (
Dusan Kasan17e497e2017-04-10 22:44:22 +02004 "encoding/base64"
5 "io/ioutil"
Edwin Lovef8d8da22019-04-02 14:07:32 +01006 "fmt"
Dusan Kasan4595dfe2017-04-13 00:38:24 +02007 "net/mail"
8 "strings"
9 "testing"
10 "time"
Dusan Kasan17e497e2017-04-10 22:44:22 +020011)
12
13func TestParseEmail(t *testing.T) {
Dusan Kasan4595dfe2017-04-13 00:38:24 +020014 var testData = map[int]struct {
Dusan Kasan17e497e2017-04-10 22:44:22 +020015 mailData string
16
Dusan Kasan4595dfe2017-04-13 00:38:24 +020017 subject string
18 date time.Time
19 from []mail.Address
20 sender mail.Address
21 to []mail.Address
22 replyTo []mail.Address
23 cc []mail.Address
24 bcc []mail.Address
25 messageID string
26 resentDate time.Time
27 resentFrom []mail.Address
28 resentSender mail.Address
29 resentTo []mail.Address
30 resentReplyTo []mail.Address
31 resentCc []mail.Address
32 resentBcc []mail.Address
Dusan Kasanb49ceb62017-04-13 00:00:36 +020033 resentMessageID string
Dusan Kasan4595dfe2017-04-13 00:38:24 +020034 inReplyTo []string
35 references []string
36 htmlBody string
37 textBody string
38 attachments []attachmentData
39 embeddedFiles []embeddedFileData
40 headerCheck func(mail.Header, *testing.T)
Dusan Kasan17e497e2017-04-10 22:44:22 +020041 }{
Dusan Kasanb49ceb62017-04-13 00:00:36 +020042 1: {
Dusan Kasan45ca2642017-04-18 10:39:35 +020043 mailData: rfc5322exampleA11,
Dusan Kasan4595dfe2017-04-13 00:38:24 +020044 subject: "Saying Hello",
Dusan Kasanb49ceb62017-04-13 00:00:36 +020045 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +020046 {
47 Name: "John Doe",
48 Address: "jdoe@machine.example",
49 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +020050 },
51 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +020052 {
53 Name: "Mary Smith",
54 Address: "mary@example.net",
55 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +020056 },
Dusan Kasan45ca2642017-04-18 10:39:35 +020057 sender: mail.Address{
58 Name: "Michael Jones",
59 Address: "mjones@machine.example",
60 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +020061 messageID: "1234@local.machine.example",
Dusan Kasan4595dfe2017-04-13 00:38:24 +020062 date: parseDate("Fri, 21 Nov 1997 09:55:06 -0600"),
Dusan Kasanb49ceb62017-04-13 00:00:36 +020063 textBody: `This is a message just to say hello.
64So, "Hello".`,
65 },
66 2: {
Dusan Kasan45ca2642017-04-18 10:39:35 +020067 mailData: rfc5322exampleA12,
Dusan Kasanb49ceb62017-04-13 00:00:36 +020068 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +020069 {
70 Name: "Joe Q. Public",
71 Address: "john.q.public@example.com",
72 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +020073 },
74 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +020075 {
76 Name: "Mary Smith",
77 Address: "mary@x.test",
78 },
79 {
80 Name: "",
81 Address: "jdoe@example.org",
82 },
83 {
84 Name: "Who?",
85 Address: "one@y.test",
86 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +020087 },
88 cc: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +020089 {
90 Name: "",
91 Address: "boss@nil.test",
92 },
93 {
94 Name: "Giant; \"Big\" Box",
95 Address: "sysservices@example.net",
96 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +020097 },
98 messageID: "5678.21-Nov-1997@example.com",
Dusan Kasan4595dfe2017-04-13 00:38:24 +020099 date: parseDate("Tue, 01 Jul 2003 10:52:37 +0200"),
100 textBody: `Hi everyone.`,
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200101 },
102 3: {
Dusan Kasan45ca2642017-04-18 10:39:35 +0200103 mailData: rfc5322exampleA2a,
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200104 subject: "Re: Saying Hello",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200105 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200106 {
107 Name: "Mary Smith",
108 Address: "mary@example.net",
109 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200110 },
111 replyTo: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200112 {
113 Name: "Mary Smith: Personal Account",
114 Address: "smith@home.example",
115 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200116 },
117 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200118 {
119 Name: "John Doe",
120 Address: "jdoe@machine.example",
121 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200122 },
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200123 messageID: "3456@example.net",
124 inReplyTo: []string{"1234@local.machine.example"},
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200125 references: []string{"1234@local.machine.example"},
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200126 date: parseDate("Fri, 21 Nov 1997 10:01:10 -0600"),
127 textBody: `This is a reply to your hello.`,
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200128 },
129 4: {
Dusan Kasan45ca2642017-04-18 10:39:35 +0200130 mailData: rfc5322exampleA2b,
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200131 subject: "Re: Saying Hello",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200132 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200133 {
134 Name: "John Doe",
135 Address: "jdoe@machine.example",
136 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200137 },
138 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200139 {
140 Name: "Mary Smith: Personal Account",
141 Address: "smith@home.example",
142 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200143 },
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200144 messageID: "abcd.1234@local.machine.test",
145 inReplyTo: []string{"3456@example.net"},
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200146 references: []string{"1234@local.machine.example", "3456@example.net"},
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200147 date: parseDate("Fri, 21 Nov 1997 11:00:00 -0600"),
148 textBody: `This is a reply to your reply.`,
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200149 },
150 5: {
Dusan Kasan45ca2642017-04-18 10:39:35 +0200151 mailData: rfc5322exampleA3,
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200152 subject: "Saying Hello",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200153 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200154 {
155 Name: "John Doe",
156 Address: "jdoe@machine.example",
157 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200158 },
159 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200160 {
161 Name: "Mary Smith",
162 Address: "mary@example.net",
163 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200164 },
165 messageID: "1234@local.machine.example",
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200166 date: parseDate("Fri, 21 Nov 1997 09:55:06 -0600"),
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200167 resentFrom: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200168 {
169 Name: "Mary Smith",
170 Address: "mary@example.net",
171 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200172 },
173 resentTo: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200174 {
175 Name: "Jane Brown",
176 Address: "j-brown@other.example",
177 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200178 },
179 resentMessageID: "78910@example.net",
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200180 resentDate: parseDate("Mon, 24 Nov 1997 14:22:01 -0800"),
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200181 textBody: `This is a message just to say hello.
182So, "Hello".`,
183 },
184 6: {
Dusan Kasan45ca2642017-04-18 10:39:35 +0200185 mailData: data1,
Dusan Kasanf4376a62017-05-23 21:03:55 +0200186 subject: "Peter Paholík",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200187 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200188 {
189 Name: "Peter Paholík",
190 Address: "peter.paholik@gmail.com",
191 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200192 },
193 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200194 {
195 Name: "",
196 Address: "dusan@kasan.sk",
197 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200198 },
Dusan Kasan17e497e2017-04-10 22:44:22 +0200199 messageID: "CACtgX4kNXE7T5XKSKeH_zEcfUUmf2vXVASxYjaaK9cCn-3zb_g@mail.gmail.com",
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200200 date: parseDate("Fri, 07 Apr 2017 09:17:26 +0200"),
201 htmlBody: "<div dir=\"ltr\"><br></div>",
Dusan Kasan17e497e2017-04-10 22:44:22 +0200202 attachments: []attachmentData{
203 {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200204 filename: "Peter Paholík 1 4 2017 2017-04-07.pdf",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200205 contentType: "application/pdf",
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200206 base64data: "JVBERi0xLjQNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhlbi1VUykgL1N0cnVjdFRyZWVSb290IDY3IDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4vT3V0cHV0SW50ZW50c1s8PC9UeXBlL091dHB1dEludGVudC9TL0dUU19QREZBMS9PdXRwdXRDb25kZXYgMzk1MzYyDQo+Pg0Kc3RhcnR4cmVmDQo0MTk4ODUNCiUlRU9GDQo=",
Dusan Kasan17e497e2017-04-10 22:44:22 +0200207 },
208 },
209 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200210 7: {
Dusan Kasan45ca2642017-04-18 10:39:35 +0200211 mailData: data2,
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200212 subject: "Re: Test Subject 2",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200213 from: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200214 {
215 Name: "Sender Man",
216 Address: "sender@domain.com",
217 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200218 },
219 to: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200220 {
221 Name: "",
222 Address: "info@receiver.com",
223 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200224 },
225 cc: []mail.Address{
Dusan Kasan45ca2642017-04-18 10:39:35 +0200226 {
227 Name: "Cc Man",
228 Address: "ccman@gmail.com",
229 },
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200230 },
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200231 messageID: "0e9a21b4-01dc-e5c1-dcd6-58ce5aa61f4f@receiver.com",
232 inReplyTo: []string{"9ff38d03-c4ab-89b7-9328-e99d5e24e3ba@receiver.eu"},
Dusan Kasan17e497e2017-04-10 22:44:22 +0200233 references: []string{"2f6b7595-c01e-46e5-42bc-f263e1c4282d@receiver.com", "9ff38d03-c4ab-89b7-9328-e99d5e24e3ba@domain.com"},
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200234 date: parseDate("Fri, 07 Apr 2017 12:59:55 +0200"),
235 htmlBody: `<html>data<img src="part2.9599C449.04E5EC81@develhell.com"/></html>`,
Dusan Kasan17e497e2017-04-10 22:44:22 +0200236 textBody: `First level
237> Second level
238>> Third level
239>
240`,
241 embeddedFiles: []embeddedFileData{
242 {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200243 cid: "part2.9599C449.04E5EC81@develhell.com",
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200244 contentType: "image/png",
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200245 base64data: "iVBORw0KGgoAAAANSUhEUgAAAQEAAAAYCAIAAAB1IN9NAAAACXBIWXMAAAsTAAALEwEAmpwYYKUKF+Os3baUndC0pDnwNAmLy1SUr2Gw0luxQuV/AwC6cEhVV5VRrwAAAABJRU5ErkJggg==",
Dusan Kasan17e497e2017-04-10 22:44:22 +0200246 },
247 },
248 },
Edwin Lovef8d8da22019-04-02 14:07:32 +0100249 8: {
250 mailData: data3,
251 subject: "Peter Foobar",
252 from: []mail.Address{
253 {
254 Name: "Peter Foobar",
255 Address: "peter.foobar@gmail.com",
256 },
257 },
258 to: []mail.Address{
259 {
260 Name: "",
261 Address: "dusan@kasan.sk",
262 },
263 },
264 messageID: "CACtgX4kNXE7T5XKSKeH_zEcfUUmf2vXVASxYjaaK9cCn-3zb_g@mail.gmail.com",
265 date: parseDate("Tue, 02 Apr 2019 11:12:26 +0000"),
266 htmlBody: "<div dir=\"ltr\"><br></div>",
267 attachments: []attachmentData{
268 {
269 filename: "unencoded.csv",
270 contentType: "application/csv",
271 unencodedData: fmt.Sprintf("\n"+`"%s", "%s", "%s", "%s", "%s"`+"\n"+`"%s", "%s", "%s", "%s", "%s"`+"\n", "Some", "Data", "In", "Csv", "Format", "Foo", "Bar", "Baz", "Bum", "Poo"),
272 },
273 },
274 },
275
Dusan Kasan17e497e2017-04-10 22:44:22 +0200276 }
277
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200278 for index, td := range testData {
Edwin Lovefc3e6452019-04-02 11:17:35 +0100279 e, err := Parse(strings.NewReader(td.mailData))
Dusan Kasan17e497e2017-04-10 22:44:22 +0200280 if err != nil {
281 t.Error(err)
282 }
283
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200284 if td.subject != e.Subject {
285 t.Errorf("[Test Case %v] Wrong subject. Expected: %s, Got: %s", index, td.subject, e.Subject)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200286 }
287
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200288 if td.messageID != e.MessageID {
289 t.Errorf("[Test Case %v] Wrong messageID. Expected: '%s', Got: '%s'", index, td.messageID, e.MessageID)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200290 }
291
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200292 if !td.date.Equal(e.Date) {
293 t.Errorf("[Test Case %v] Wrong date. Expected: %v, Got: %v", index, td.date, e.Date)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200294 }
295
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200296 d := dereferenceAddressList(e.From)
297 if !assertAddressListEq(td.from, d) {
298 t.Errorf("[Test Case %v] Wrong from. Expected: %s, Got: %s", index, td.from, d)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200299 }
300
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200301 var sender mail.Address
302 if e.Sender != nil {
303 sender = *e.Sender
304 }
305 if td.sender != sender {
306 t.Errorf("[Test Case %v] Wrong sender. Expected: %s, Got: %s", index, td.sender, sender)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200307 }
308
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200309 d = dereferenceAddressList(e.To)
310 if !assertAddressListEq(td.to, d) {
311 t.Errorf("[Test Case %v] Wrong to. Expected: %s, Got: %s", index, td.to, d)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200312 }
313
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200314 d = dereferenceAddressList(e.Cc)
315 if !assertAddressListEq(td.cc, d) {
316 t.Errorf("[Test Case %v] Wrong cc. Expected: %s, Got: %s", index, td.cc, d)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200317 }
318
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200319 d = dereferenceAddressList(e.Bcc)
320 if !assertAddressListEq(td.bcc, d) {
321 t.Errorf("[Test Case %v] Wrong bcc. Expected: %s, Got: %s", index, td.bcc, d)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200322 }
323
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200324 if td.resentMessageID != e.ResentMessageID {
325 t.Errorf("[Test Case %v] Wrong resent messageID. Expected: '%s', Got: '%s'", index, td.resentMessageID, e.ResentMessageID)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200326 }
327
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200328 if !td.resentDate.Equal(e.ResentDate) && !td.resentDate.IsZero() && !e.ResentDate.IsZero() {
329 t.Errorf("[Test Case %v] Wrong resent date. Expected: %v, Got: %v", index, td.resentDate, e.ResentDate)
330 }
331
332 d = dereferenceAddressList(e.ResentFrom)
333 if !assertAddressListEq(td.resentFrom, d) {
334 t.Errorf("[Test Case %v] Wrong resent from. Expected: %s, Got: %s", index, td.resentFrom, d)
335 }
336
337 var resentSender mail.Address
338 if e.ResentSender != nil {
339 resentSender = *e.ResentSender
340 }
341 if td.resentSender != resentSender {
342 t.Errorf("[Test Case %v] Wrong resent sender. Expected: %s, Got: %s", index, td.resentSender, resentSender)
343 }
344
345 d = dereferenceAddressList(e.ResentTo)
346 if !assertAddressListEq(td.resentTo, d) {
347 t.Errorf("[Test Case %v] Wrong resent to. Expected: %s, Got: %s", index, td.resentTo, d)
348 }
349
350 d = dereferenceAddressList(e.ResentCc)
351 if !assertAddressListEq(td.resentCc, d) {
352 t.Errorf("[Test Case %v] Wrong resent cc. Expected: %s, Got: %s", index, td.resentCc, d)
353 }
354
355 d = dereferenceAddressList(e.ResentBcc)
356 if !assertAddressListEq(td.resentBcc, d) {
357 t.Errorf("[Test Case %v] Wrong resent bcc. Expected: %s, Got: %s", index, td.resentBcc, d)
358 }
359
360 if !assertSliceEq(td.inReplyTo, e.InReplyTo) {
361 t.Errorf("[Test Case %v] Wrong in reply to. Expected: %s, Got: %s", index, td.inReplyTo, e.InReplyTo)
362 }
363
364 if !assertSliceEq(td.references, e.References) {
365 t.Errorf("[Test Case %v] Wrong references. Expected: %s, Got: %s", index, td.references, e.References)
366 }
367
368 d = dereferenceAddressList(e.ReplyTo)
369 if !assertAddressListEq(td.replyTo, d) {
370 t.Errorf("[Test Case %v] Wrong reply to. Expected: %s, Got: %s", index, td.replyTo, d)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200371 }
372
373 if td.htmlBody != e.HTMLBody {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200374 t.Errorf("[Test Case %v] Wrong html body. Expected: '%s', Got: '%s'", index, td.htmlBody, e.HTMLBody)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200375 }
376
377 if td.textBody != e.TextBody {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200378 t.Errorf("[Test Case %v] Wrong text body. Expected: '%s', Got: '%s'", index, td.textBody, e.TextBody)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200379 }
380
Dusan Kasan17e497e2017-04-10 22:44:22 +0200381 if len(td.attachments) != len(e.Attachments) {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200382 t.Errorf("[Test Case %v] Incorrect number of attachments! Expected: %v, Got: %v.", index, len(td.attachments), len(e.Attachments))
Dusan Kasan17e497e2017-04-10 22:44:22 +0200383 } else {
384 attachs := e.Attachments[:]
385
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200386 for _, ad := range td.attachments {
Dusan Kasan17e497e2017-04-10 22:44:22 +0200387 found := false
388
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200389 for i, ra := range attachs {
Dusan Kasan17e497e2017-04-10 22:44:22 +0200390 b, err := ioutil.ReadAll(ra.Data)
391 if err != nil {
392 t.Error(err)
393 }
Edwin Lovef8d8da22019-04-02 14:07:32 +0100394 actual := "actual"
395 expected := "expected"
396 if ad.base64data != "" {
397 actual = base64.StdEncoding.EncodeToString(b)
398 expected = ad.base64data
399 } else if ad.unencodedData != "" {
400 actual = string(b)
401 expected = ad.unencodedData
402 }
403 if ra.Filename == ad.filename && actual == expected && ra.ContentType == ad.contentType {
Dusan Kasan17e497e2017-04-10 22:44:22 +0200404 found = true
405 attachs = append(attachs[:i], attachs[i+1:]...)
406 }
407 }
408
409 if !found {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200410 t.Errorf("[Test Case %v] Attachment not found: %s", index, ad.filename)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200411 }
412 }
413
414 if len(attachs) != 0 {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200415 t.Errorf("[Test Case %v] Email contains %v unexpected attachments: %v", index, len(attachs), attachs)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200416 }
417 }
418
419 if len(td.embeddedFiles) != len(e.EmbeddedFiles) {
Dusan Kasan1a966482017-04-18 10:45:25 +0200420 t.Errorf("[Test Case %v] Incorrect number of embedded files! Expected: %v, Got: %v.", index, len(td.embeddedFiles), len(e.EmbeddedFiles))
Dusan Kasan17e497e2017-04-10 22:44:22 +0200421 } else {
422 embeds := e.EmbeddedFiles[:]
423
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200424 for _, ad := range td.embeddedFiles {
Dusan Kasan17e497e2017-04-10 22:44:22 +0200425 found := false
426
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200427 for i, ra := range embeds {
Dusan Kasan17e497e2017-04-10 22:44:22 +0200428 b, err := ioutil.ReadAll(ra.Data)
429 if err != nil {
430 t.Error(err)
431 }
432
433 encoded := base64.StdEncoding.EncodeToString(b)
434
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200435 if ra.CID == ad.cid && encoded == ad.base64data && ra.ContentType == ad.contentType {
Dusan Kasan17e497e2017-04-10 22:44:22 +0200436 found = true
437 embeds = append(embeds[:i], embeds[i+1:]...)
438 }
439 }
440
441 if !found {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200442 t.Errorf("[Test Case %v] Embedded file not found: %s", index, ad.cid)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200443 }
444 }
445
446 if len(embeds) != 0 {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200447 t.Errorf("[Test Case %v] Email contains %v unexpected embedded files: %v", index, len(embeds), embeds)
Dusan Kasan17e497e2017-04-10 22:44:22 +0200448 }
449 }
450 }
451}
452
453func parseDate(in string) time.Time {
454 out, err := time.Parse(time.RFC1123Z, in)
455 if err != nil {
456 panic(err)
457 }
458
459 return out
460}
461
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200462type attachmentData struct {
Edwin Lovef8d8da22019-04-02 14:07:32 +0100463 filename string
464 contentType string
465 base64data string
466 unencodedData string
Dusan Kasan17e497e2017-04-10 22:44:22 +0200467}
468
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200469type embeddedFileData struct {
470 cid string
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200471 contentType string
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200472 base64data string
Dusan Kasan17e497e2017-04-10 22:44:22 +0200473}
474
475func assertSliceEq(a, b []string) bool {
476 if len(a) == len(b) && len(a) == 0 {
477 return true
478 }
479
480 if a == nil && b == nil {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200481 return true
Dusan Kasan17e497e2017-04-10 22:44:22 +0200482 }
483
484 if a == nil || b == nil {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200485 return false
Dusan Kasan17e497e2017-04-10 22:44:22 +0200486 }
487
488 if len(a) != len(b) {
489 return false
490 }
491
492 for i := range a {
493 if a[i] != b[i] {
494 return false
495 }
496 }
497
498 return true
499}
500
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200501func assertAddressListEq(a, b []mail.Address) bool {
502 if len(a) == len(b) && len(a) == 0 {
503 return true
504 }
505
506 if a == nil && b == nil {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200507 return true
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200508 }
509
510 if a == nil || b == nil {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200511 return false
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200512 }
513
514 if len(a) != len(b) {
515 return false
516 }
517
518 for i := range a {
519 if a[i] != b[i] {
520 return false
521 }
522 }
523
524 return true
525}
526
527func dereferenceAddressList(al []*mail.Address) (result []mail.Address) {
Dusan Kasan4595dfe2017-04-13 00:38:24 +0200528 for _, a := range al {
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200529 result = append(result, *a)
530 }
531
532 return
533}
534
Dusan Kasan45ca2642017-04-18 10:39:35 +0200535var data1 = `From: =?UTF-8?Q?Peter_Pahol=C3=ADk?= <peter.paholik@gmail.com>
Dusan Kasan17e497e2017-04-10 22:44:22 +0200536Date: Fri, 7 Apr 2017 09:17:26 +0200
537Message-ID: <CACtgX4kNXE7T5XKSKeH_zEcfUUmf2vXVASxYjaaK9cCn-3zb_g@mail.gmail.com>
Dusan Kasanf4376a62017-05-23 21:03:55 +0200538Subject: =?UTF-8?Q?Peter_Pahol=C3=ADk?=
Dusan Kasan17e497e2017-04-10 22:44:22 +0200539To: dusan@kasan.sk
540Content-Type: multipart/mixed; boundary=f403045f1dcc043a44054c8e6bbf
541
542--f403045f1dcc043a44054c8e6bbf
543Content-Type: multipart/alternative; boundary=f403045f1dcc043a3f054c8e6bbd
544
545--f403045f1dcc043a3f054c8e6bbd
546Content-Type: text/plain; charset=UTF-8
547
548
549
550--f403045f1dcc043a3f054c8e6bbd
551Content-Type: text/html; charset=UTF-8
552
553<div dir="ltr"><br></div>
554
555--f403045f1dcc043a3f054c8e6bbd--
556--f403045f1dcc043a44054c8e6bbf
557Content-Type: application/pdf;
558 name="=?UTF-8?Q?Peter_Paholi=CC=81k_1?=
559 =?UTF-8?Q?_4_2017_2017=2D04=2D07=2Epdf?="
560Content-Disposition: attachment;
561 filename="=?UTF-8?Q?Peter_Paholi=CC=81k_1?=
562 =?UTF-8?Q?_4_2017_2017=2D04=2D07=2Epdf?="
563Content-Transfer-Encoding: base64
564X-Attachment-Id: f_j17i0f0d0
565
566JVBERi0xLjQNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFu
567Zyhlbi1VUykgL1N0cnVjdFRyZWVSb290IDY3IDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4v
568T3V0cHV0SW50ZW50c1s8PC9UeXBlL091dHB1dEludGVudC9TL0dUU19QREZBMS9PdXRwdXRDb25k
569ZXYgMzk1MzYyDQo+Pg0Kc3RhcnR4cmVmDQo0MTk4ODUNCiUlRU9GDQo=
570--f403045f1dcc043a44054c8e6bbf--
571`
572
Dusan Kasan45ca2642017-04-18 10:39:35 +0200573var data2 = `Subject: Re: Test Subject 2
Dusan Kasan17e497e2017-04-10 22:44:22 +0200574To: info@receiver.com
575References: <2f6b7595-c01e-46e5-42bc-f263e1c4282d@receiver.com>
576 <9ff38d03-c4ab-89b7-9328-e99d5e24e3ba@domain.com>
577Cc: Cc Man <ccman@gmail.com>
578From: Sender Man <sender@domain.com>
579Message-ID: <0e9a21b4-01dc-e5c1-dcd6-58ce5aa61f4f@receiver.com>
580Date: Fri, 7 Apr 2017 12:59:55 +0200
581User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0)
582 Gecko/20100101 Thunderbird/45.8.0
583MIME-Version: 1.0
584In-Reply-To: <9ff38d03-c4ab-89b7-9328-e99d5e24e3ba@receiver.eu>
585Content-Type: multipart/alternative;
586 boundary="------------C70C0458A558E585ACB75FB4"
587
588This is a multi-part message in MIME format.
589--------------C70C0458A558E585ACB75FB4
590Content-Type: text/plain; charset=utf-8; format=flowed
591Content-Transfer-Encoding: 8bit
592
593First level
594> Second level
595>> Third level
596>
597
598
599--------------C70C0458A558E585ACB75FB4
600Content-Type: multipart/related;
601 boundary="------------5DB4A1356834BB602A5F88B2"
602
603
604--------------5DB4A1356834BB602A5F88B2
605Content-Type: text/html; charset=utf-8
606Content-Transfer-Encoding: 8bit
607
608<html>data<img src="part2.9599C449.04E5EC81@develhell.com"/></html>
609
610--------------5DB4A1356834BB602A5F88B2
611Content-Type: image/png
612Content-Transfer-Encoding: base64
613Content-ID: <part2.9599C449.04E5EC81@develhell.com>
614
615iVBORw0KGgoAAAANSUhEUgAAAQEAAAAYCAIAAAB1IN9NAAAACXBIWXMAAAsTAAALEwEAmpwY
616YKUKF+Os3baUndC0pDnwNAmLy1SUr2Gw0luxQuV/AwC6cEhVV5VRrwAAAABJRU5ErkJggg==
617--------------5DB4A1356834BB602A5F88B2
618
619--------------C70C0458A558E585ACB75FB4--
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200620`
621
Edwin Lovef8d8da22019-04-02 14:07:32 +0100622var data3 = `From: =?UTF-8?Q?Peter_Foobar?= <peter.foobar@gmail.com>
623Date: Tue, 2 Apr 2019 11:12:26 +0000
624Message-ID: <CACtgX4kNXE7T5XKSKeH_zEcfUUmf2vXVASxYjaaK9cCn-3zb_g@mail.gmail.com>
625Subject: =?UTF-8?Q?Peter_Foobar?=
626To: dusan@kasan.sk
627Content-Type: multipart/mixed; boundary=f403045f1dcc043a44054c8e6bbf
628
629--f403045f1dcc043a44054c8e6bbf
630Content-Type: multipart/alternative; boundary=f403045f1dcc043a3f054c8e6bbd
631
632--f403045f1dcc043a3f054c8e6bbd
633Content-Type: text/plain; charset=UTF-8
634
635
636
637--f403045f1dcc043a3f054c8e6bbd
638Content-Type: text/html; charset=UTF-8
639
640<div dir="ltr"><br></div>
641
642--f403045f1dcc043a3f054c8e6bbd--
643--f403045f1dcc043a44054c8e6bbf
644Content-Type: application/csv;
645 name="unencoded.csv"
646Content-Transfer-Encoding: 7bit
647Content-Disposition: attachment;
648 filename="unencoded.csv"
649
650
651"Some", "Data", "In", "Csv", "Format"
652"Foo", "Bar", "Baz", "Bum", "Poo"
653
654--f403045f1dcc043a44054c8e6bbf--
655`
656
Dusan Kasan45ca2642017-04-18 10:39:35 +0200657var rfc5322exampleA11 = `From: John Doe <jdoe@machine.example>
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200658Sender: Michael Jones <mjones@machine.example>
659To: Mary Smith <mary@example.net>
660Subject: Saying Hello
661Date: Fri, 21 Nov 1997 09:55:06 -0600
662Message-ID: <1234@local.machine.example>
663
664This is a message just to say hello.
665So, "Hello".
666`
667
Dusan Kasan45ca2642017-04-18 10:39:35 +0200668var rfc5322exampleA12 = `From: "Joe Q. Public" <john.q.public@example.com>
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200669To: Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>
670Cc: <boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>
671Date: Tue, 1 Jul 2003 10:52:37 +0200
672Message-ID: <5678.21-Nov-1997@example.com>
673
674Hi everyone.
675`
676
677//todo: not yet implemented in net/mail
678//once there is support for this, add it
Dusan Kasan45ca2642017-04-18 10:39:35 +0200679var rfc5322exampleA13 = `From: Pete <pete@silly.example>
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200680To: A Group:Ed Jones <c@a.test>,joe@where.test,John <jdoe@one.test>;
681Cc: Undisclosed recipients:;
682Date: Thu, 13 Feb 1969 23:32:54 -0330
683Message-ID: <testabcd.1234@silly.example>
684
685Testing.
686`
687
688//we skipped the first message bcause it's the same as A 1.1
Dusan Kasan45ca2642017-04-18 10:39:35 +0200689var rfc5322exampleA2a = `From: Mary Smith <mary@example.net>
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200690To: John Doe <jdoe@machine.example>
691Reply-To: "Mary Smith: Personal Account" <smith@home.example>
692Subject: Re: Saying Hello
693Date: Fri, 21 Nov 1997 10:01:10 -0600
694Message-ID: <3456@example.net>
695In-Reply-To: <1234@local.machine.example>
696References: <1234@local.machine.example>
697
698This is a reply to your hello.
699`
700
Dusan Kasan45ca2642017-04-18 10:39:35 +0200701var rfc5322exampleA2b = `To: "Mary Smith: Personal Account" <smith@home.example>
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200702From: John Doe <jdoe@machine.example>
703Subject: Re: Saying Hello
704Date: Fri, 21 Nov 1997 11:00:00 -0600
705Message-ID: <abcd.1234@local.machine.test>
706In-Reply-To: <3456@example.net>
707References: <1234@local.machine.example> <3456@example.net>
708
709This is a reply to your reply.
710`
711
Dusan Kasan45ca2642017-04-18 10:39:35 +0200712var rfc5322exampleA3 = `Resent-From: Mary Smith <mary@example.net>
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200713Resent-To: Jane Brown <j-brown@other.example>
714Resent-Date: Mon, 24 Nov 1997 14:22:01 -0800
715Resent-Message-ID: <78910@example.net>
716From: John Doe <jdoe@machine.example>
717To: Mary Smith <mary@example.net>
718Subject: Saying Hello
719Date: Fri, 21 Nov 1997 09:55:06 -0600
720Message-ID: <1234@local.machine.example>
721
722This is a message just to say hello.
723So, "Hello".`
724
Dusan Kasan45ca2642017-04-18 10:39:35 +0200725var rfc5322exampleA4 = `Received: from x.y.test
Dusan Kasanb49ceb62017-04-13 00:00:36 +0200726 by example.net
727 via TCP
728 with ESMTP
729 id ABC12345
730 for <mary@example.net>; 21 Nov 1997 10:05:43 -0600
731Received: from node.example by x.y.test; 21 Nov 1997 10:01:22 -0600
732From: John Doe <jdoe@node.example>
733To: Mary Smith <mary@example.net>
734Subject: Saying Hello
735Date: Fri, 21 Nov 1997 09:55:06 -0600
736Message-ID: <1234@local.node.example>
737
738This is a message just to say hello.
739So, "Hello".`