maddy

git clone git://git.lin.moe/fmaddy/maddy.git

  1//go:build integration && cgo && !nosqlite3
  2// +build integration,cgo,!nosqlite3
  3
  4/*
  5Maddy Mail Server - Composable all-in-one email server.
  6Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
  7
  8This program is free software: you can redistribute it and/or modify
  9it under the terms of the GNU General Public License as published by
 10the Free Software Foundation, either version 3 of the License, or
 11(at your option) any later version.
 12
 13This program is distributed in the hope that it will be useful,
 14but WITHOUT ANY WARRANTY; without even the implied warranty of
 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16GNU General Public License for more details.
 17
 18You should have received a copy of the GNU General Public License
 19along with this program.  If not, see <https://www.gnu.org/licenses/>.
 20*/
 21
 22package tests_test
 23
 24import (
 25	"strings"
 26	"testing"
 27	"time"
 28
 29	"github.com/foxcpp/maddy/tests"
 30)
 31
 32func TestSMTPEndpoint_LargeMessage(tt *testing.T) {
 33	// Send 1.44 MiB message to verify it being handled correctly
 34	// everywhere.
 35	// (Issue 389)
 36
 37	tt.Parallel()
 38	t := tests.NewT(tt)
 39	t.DNS(nil)
 40	t.Port("imap")
 41	t.Port("smtp")
 42	t.Config(`
 43		storage.imapsql test_store {
 44			driver sqlite3
 45			dsn imapsql.db
 46		}
 47
 48		imap tcp://127.0.0.1:{env:TEST_PORT_imap} {
 49			tls off
 50
 51			auth dummy
 52			storage &test_store
 53		}
 54
 55		smtp tcp://127.0.0.1:{env:TEST_PORT_smtp} {
 56			hostname maddy.test
 57			tls off
 58
 59			deliver_to &test_store
 60		}
 61	`)
 62	t.Run(2)
 63	defer t.Close()
 64
 65	imapConn := t.Conn("imap")
 66	defer imapConn.Close()
 67	imapConn.ExpectPattern(`\* OK *`)
 68	imapConn.Writeln(". LOGIN testusr@maddy.test 1234")
 69	imapConn.ExpectPattern(". OK *")
 70	imapConn.Writeln(". SELECT INBOX")
 71	imapConn.ExpectPattern(`\* *`)
 72	imapConn.ExpectPattern(`\* *`)
 73	imapConn.ExpectPattern(`\* *`)
 74	imapConn.ExpectPattern(`\* *`)
 75	imapConn.ExpectPattern(`\* *`)
 76	imapConn.ExpectPattern(`\* *`)
 77	imapConn.ExpectPattern(`. OK *`)
 78
 79	smtpConn := t.Conn("smtp")
 80	defer smtpConn.Close()
 81	smtpConn.SMTPNegotation("localhost", nil, nil)
 82	smtpConn.Writeln("MAIL FROM:<sender@maddy.test>")
 83	smtpConn.ExpectPattern("2*")
 84	smtpConn.Writeln("RCPT TO:<testusr@maddy.test>")
 85	smtpConn.ExpectPattern("2*")
 86	smtpConn.Writeln("DATA")
 87	smtpConn.ExpectPattern("354 *")
 88	smtpConn.Writeln("From: <sender@maddy.test>")
 89	smtpConn.Writeln("To: <testusr@maddy.test>")
 90	smtpConn.Writeln("Subject: Hi!")
 91	smtpConn.Writeln("")
 92	for i := 0; i < 3000; i++ {
 93		smtpConn.Writeln(strings.Repeat("A", 500))
 94	}
 95	// 3000*502 ~ 1.44 MiB not including header side
 96	smtpConn.Writeln(".")
 97
 98	time.Sleep(500 * time.Millisecond)
 99
100	imapConn.Writeln(". NOOP")
101	imapConn.ExpectPattern(`\* 1 EXISTS`)
102	imapConn.ExpectPattern(`\* 1 RECENT`)
103	imapConn.ExpectPattern(". OK *")
104
105	imapConn.Writeln(". FETCH 1 (BODY.PEEK[])")
106	imapConn.ExpectPattern(`\* 1 FETCH (BODY\[\] {1506312}*`)
107	imapConn.Expect(`Delivered-To: testusr@maddy.test`)
108	imapConn.Expect(`Return-Path: <sender@maddy.test>`)
109	imapConn.ExpectPattern(`Received: from localhost (client.maddy.test \[` + tests.DefaultSourceIP.String() + `\]) by maddy.test`)
110	imapConn.ExpectPattern(` (envelope-sender <sender@maddy.test>) with ESMTP id *; *`)
111	imapConn.ExpectPattern(` *`)
112	imapConn.Expect("From: <sender@maddy.test>")
113	imapConn.Expect("To: <testusr@maddy.test>")
114	imapConn.Expect("Subject: Hi!")
115	imapConn.Expect("")
116	for i := 0; i < 3000; i++ {
117		imapConn.Expect(strings.Repeat("A", 500))
118	}
119	imapConn.Expect(")")
120	imapConn.ExpectPattern(`. OK *`)
121}
122
123func TestSMTPEndpoint_FileBuffer(tt *testing.T) {
124	run := func(tt *testing.T, bufferOpt string) {
125		tt.Parallel()
126		t := tests.NewT(tt)
127
128		t.DNS(nil)
129		t.Port("imap")
130		t.Port("smtp")
131		t.Config(`
132		storage.imapsql test_store {
133			driver sqlite3
134			dsn imapsql.db
135		}
136
137		imap tcp://127.0.0.1:{env:TEST_PORT_imap} {
138			tls off
139
140			auth dummy
141			storage &test_store
142		}
143
144		smtp tcp://127.0.0.1:{env:TEST_PORT_smtp} {
145			hostname maddy.test
146			tls off
147			buffer ` + bufferOpt + `
148
149			deliver_to &test_store
150		}
151	`)
152		t.Run(2)
153		defer t.Close()
154
155		imapConn := t.Conn("imap")
156		defer imapConn.Close()
157		imapConn.ExpectPattern(`\* OK *`)
158		imapConn.Writeln(". LOGIN testusr@maddy.test 1234")
159		imapConn.ExpectPattern(". OK *")
160		imapConn.Writeln(". SELECT INBOX")
161		imapConn.ExpectPattern(`\* *`)
162		imapConn.ExpectPattern(`\* *`)
163		imapConn.ExpectPattern(`\* *`)
164		imapConn.ExpectPattern(`\* *`)
165		imapConn.ExpectPattern(`\* *`)
166		imapConn.ExpectPattern(`\* *`)
167		imapConn.ExpectPattern(`. OK *`)
168
169		smtpConn := t.Conn("smtp")
170		defer smtpConn.Close()
171		smtpConn.SMTPNegotation("localhost", nil, nil)
172		smtpConn.Writeln("MAIL FROM:<sender@maddy.test>")
173		smtpConn.ExpectPattern("2*")
174		smtpConn.Writeln("RCPT TO:<testusr@maddy.test>")
175		smtpConn.ExpectPattern("2*")
176		smtpConn.Writeln("DATA")
177		smtpConn.ExpectPattern("354 *")
178		smtpConn.Writeln("From: <sender@maddy.test>")
179		smtpConn.Writeln("To: <testusr@maddy.test>")
180		smtpConn.Writeln("Subject: Hi!")
181		smtpConn.Writeln("")
182		smtpConn.Writeln("AAAAABBBBBB")
183		smtpConn.Writeln(".")
184		smtpConn.ExpectPattern("2*")
185
186		time.Sleep(500 * time.Millisecond)
187
188		imapConn.Writeln(". NOOP")
189		imapConn.ExpectPattern(`\* 1 EXISTS`)
190		imapConn.ExpectPattern(`\* 1 RECENT`)
191		imapConn.ExpectPattern(". OK *")
192
193		imapConn.Writeln(". FETCH 1 (BODY.PEEK[])")
194		imapConn.ExpectPattern(`\* 1 FETCH (BODY\[\] {*}*`)
195		imapConn.Expect(`Delivered-To: testusr@maddy.test`)
196		imapConn.Expect(`Return-Path: <sender@maddy.test>`)
197		imapConn.ExpectPattern(`Received: from localhost (client.maddy.test \[` + tests.DefaultSourceIP.String() + `\]) by maddy.test`)
198		imapConn.ExpectPattern(` (envelope-sender <sender@maddy.test>) with ESMTP id *; *`)
199		imapConn.ExpectPattern(` *`)
200		imapConn.Expect("From: <sender@maddy.test>")
201		imapConn.Expect("To: <testusr@maddy.test>")
202		imapConn.Expect("Subject: Hi!")
203		imapConn.Expect("")
204		imapConn.Expect("AAAAABBBBBB")
205		imapConn.Expect(")")
206		imapConn.ExpectPattern(`. OK *`)
207	}
208
209	tt.Run("ram", func(tt *testing.T) { run(tt, "ram") })
210	tt.Run("fs", func(tt *testing.T) { run(tt, "fs") })
211}
212
213func TestSMTPEndpoint_Autobuffer(tt *testing.T) {
214	tt.Parallel()
215	t := tests.NewT(tt)
216
217	t.DNS(nil)
218	t.Port("imap")
219	t.Port("smtp")
220	t.Config(`
221		storage.imapsql test_store {
222			driver sqlite3
223			dsn imapsql.db
224		}
225
226		imap tcp://127.0.0.1:{env:TEST_PORT_imap} {
227			tls off
228
229			auth dummy
230			storage &test_store
231		}
232
233		smtp tcp://127.0.0.1:{env:TEST_PORT_smtp} {
234			hostname maddy.test
235			tls off
236			buffer auto 5b
237
238			deliver_to &test_store
239		}
240	`)
241	t.Run(2)
242	defer t.Close()
243
244	imapConn := t.Conn("imap")
245	defer imapConn.Close()
246	imapConn.ExpectPattern(`\* OK *`)
247	imapConn.Writeln(". LOGIN testusr@maddy.test 1234")
248	imapConn.ExpectPattern(". OK *")
249	imapConn.Writeln(". SELECT INBOX")
250	imapConn.ExpectPattern(`\* *`)
251	imapConn.ExpectPattern(`\* *`)
252	imapConn.ExpectPattern(`\* *`)
253	imapConn.ExpectPattern(`\* *`)
254	imapConn.ExpectPattern(`\* *`)
255	imapConn.ExpectPattern(`\* *`)
256	imapConn.ExpectPattern(`. OK *`)
257
258	smtpConn := t.Conn("smtp")
259	defer smtpConn.Close()
260	smtpConn.SMTPNegotation("localhost", nil, nil)
261	smtpConn.Writeln("MAIL FROM:<sender@maddy.test>")
262	smtpConn.ExpectPattern("2*")
263	smtpConn.Writeln("RCPT TO:<testusr@maddy.test>")
264	smtpConn.ExpectPattern("2*")
265	smtpConn.Writeln("DATA")
266	smtpConn.ExpectPattern("354 *")
267	smtpConn.Writeln("From: <sender@maddy.test>")
268	smtpConn.Writeln("To: <testusr@maddy.test>")
269	smtpConn.Writeln("Subject: Hi!")
270	smtpConn.Writeln("")
271	smtpConn.Writeln("AAAAABBBBBB")
272	smtpConn.Writeln(".")
273	smtpConn.ExpectPattern("2*")
274
275	smtpConn.Writeln("MAIL FROM:<sender@maddy.test>")
276	smtpConn.ExpectPattern("2*")
277	smtpConn.Writeln("RCPT TO:<testusr@maddy.test>")
278	smtpConn.ExpectPattern("2*")
279	smtpConn.Writeln("DATA")
280	smtpConn.ExpectPattern("354 *")
281	smtpConn.Writeln("From: <sender@maddy.test>")
282	smtpConn.Writeln("To: <testusr@maddy.test>")
283	smtpConn.Writeln("Subject: Hi!")
284	smtpConn.Writeln("")
285	smtpConn.Writeln(".")
286	smtpConn.ExpectPattern("2*")
287
288	smtpConn.Writeln("MAIL FROM:<sender@maddy.test>")
289	smtpConn.ExpectPattern("2*")
290	smtpConn.Writeln("RCPT TO:<testusr@maddy.test>")
291	smtpConn.ExpectPattern("2*")
292	smtpConn.Writeln("DATA")
293	smtpConn.ExpectPattern("354 *")
294	smtpConn.Writeln("From: <sender@maddy.test>")
295	smtpConn.Writeln("To: <testusr@maddy.test>")
296	smtpConn.Writeln("Subject: Hi!")
297	smtpConn.Writeln("")
298	smtpConn.Writeln("AAA")
299	smtpConn.Writeln(".")
300	smtpConn.ExpectPattern("2*")
301
302	time.Sleep(500 * time.Millisecond)
303
304	imapConn.Writeln(". NOOP")
305	// This will break with go-imap v2 upgrade merging updates.
306	imapConn.ExpectPattern(`\* 3 EXISTS`)
307	imapConn.ExpectPattern(`\* 3 RECENT`)
308	imapConn.ExpectPattern(". OK *")
309
310	imapConn.Writeln(". FETCH 1:3 (BODY.PEEK[])")
311	imapConn.ExpectPattern(`\* 1 FETCH (BODY\[\] {*}*`)
312	imapConn.Expect(`Delivered-To: testusr@maddy.test`)
313	imapConn.Expect(`Return-Path: <sender@maddy.test>`)
314	imapConn.ExpectPattern(`Received: from localhost (client.maddy.test \[` + tests.DefaultSourceIP.String() + `\]) by maddy.test`)
315	imapConn.ExpectPattern(` (envelope-sender <sender@maddy.test>) with ESMTP id *; *`)
316	imapConn.ExpectPattern(` *`)
317	imapConn.Expect("From: <sender@maddy.test>")
318	imapConn.Expect("To: <testusr@maddy.test>")
319	imapConn.Expect("Subject: Hi!")
320	imapConn.Expect("")
321	imapConn.Expect("AAAAABBBBBB")
322	imapConn.Expect(")")
323	imapConn.ExpectPattern(`\* 2 FETCH (BODY\[\] {*}*`)
324	imapConn.Expect(`Delivered-To: testusr@maddy.test`)
325	imapConn.Expect(`Return-Path: <sender@maddy.test>`)
326	imapConn.ExpectPattern(`Received: from localhost (client.maddy.test \[` + tests.DefaultSourceIP.String() + `\]) by maddy.test`)
327	imapConn.ExpectPattern(` (envelope-sender <sender@maddy.test>) with ESMTP id *; *`)
328	imapConn.ExpectPattern(` *`)
329	imapConn.Expect("From: <sender@maddy.test>")
330	imapConn.Expect("To: <testusr@maddy.test>")
331	imapConn.Expect("Subject: Hi!")
332	imapConn.Expect("")
333	imapConn.Expect(")")
334	imapConn.ExpectPattern(`\* 3 FETCH (BODY\[\] {*}*`)
335	imapConn.Expect(`Delivered-To: testusr@maddy.test`)
336	imapConn.Expect(`Return-Path: <sender@maddy.test>`)
337	imapConn.ExpectPattern(`Received: from localhost (client.maddy.test \[` + tests.DefaultSourceIP.String() + `\]) by maddy.test`)
338	imapConn.ExpectPattern(` (envelope-sender <sender@maddy.test>) with ESMTP id *; *`)
339	imapConn.ExpectPattern(` *`)
340	imapConn.Expect("From: <sender@maddy.test>")
341	imapConn.Expect("To: <testusr@maddy.test>")
342	imapConn.Expect("Subject: Hi!")
343	imapConn.Expect("")
344	imapConn.Expect("AAA")
345	imapConn.Expect(")")
346	imapConn.ExpectPattern(`. OK *`)
347}