maddy

Fork https://github.com/foxcpp/maddy

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

  1//go:build integration
  2
  3/*
  4Maddy Mail Server - Composable all-in-one email server.
  5Copyright © 2019-2025 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
  6
  7This program is free software: you can redistribute it and/or modify
  8it under the terms of the GNU General Public License as published by
  9the Free Software Foundation, either version 3 of the License, or
 10(at your option) any later version.
 11
 12This program is distributed in the hope that it will be useful,
 13but WITHOUT ANY WARRANTY; without even the implied warranty of
 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15GNU General Public License for more details.
 16
 17You should have received a copy of the GNU General Public License
 18along with this program.  If not, see <https://www.gnu.org/licenses/>.
 19*/
 20
 21package tests_test
 22
 23import (
 24	"testing"
 25
 26	"github.com/foxcpp/maddy/tests"
 27)
 28
 29// Test cases based on https://maddy.email/multiple-domains/
 30
 31func TestMultipleDomains_SeparateNamespace(tt *testing.T) {
 32	tt.Parallel()
 33	t := tests.NewT(tt)
 34	t.DNS(nil)
 35	t.Port("submission")
 36	t.Port("imap")
 37	t.Config(`
 38		tls off
 39		hostname test.maddy.email
 40
 41		auth.pass_table local_authdb {
 42			table sql_table {
 43				driver sqlite3
 44				dsn credentials.db
 45				table_name passwords
 46			}
 47		}
 48		storage.imapsql local_mailboxes {
 49			driver sqlite3
 50			dsn imapsql.db
 51		}
 52
 53		submission tcp://0.0.0.0:{env:TEST_PORT_submission} {
 54			auth &local_authdb
 55			reject
 56		}
 57		imap tcp://127.0.0.1:{env:TEST_PORT_imap} {
 58			auth &local_authdb
 59			storage &local_mailboxes
 60		}
 61	`)
 62
 63	t.MustRunCLIGroup(
 64		[]string{"creds", "create", "-p", "user1", "user1@test1.maddy.email"},
 65		[]string{"creds", "create", "-p", "user2", "user2@test1.maddy.email"},
 66		[]string{"creds", "create", "-p", "user3", "user1@test2.maddy.email"},
 67		[]string{"imap-acct", "create", "--no-specialuse", "user1@test1.maddy.email"},
 68		[]string{"imap-acct", "create", "--no-specialuse", "user2@test1.maddy.email"},
 69		[]string{"imap-acct", "create", "--no-specialuse", "user1@test2.maddy.email"},
 70	)
 71	t.Run(2)
 72
 73	user1 := t.Conn("imap")
 74	defer user1.Close()
 75	user1.ExpectPattern(`\* OK *`)
 76	user1.Writeln(`. LOGIN user1@test1.maddy.email user1`)
 77	user1.ExpectPattern(`. OK *`)
 78	user1.Writeln(`. CREATE user1`)
 79	user1.ExpectPattern(`. OK *`)
 80
 81	user1SMTP := t.Conn("submission")
 82	defer user1SMTP.Close()
 83	user1SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
 84	user1SMTP.SMTPPlainAuth("user1@test1.maddy.email", "user1", true)
 85
 86	user2 := t.Conn("imap")
 87	defer user2.Close()
 88	user2.ExpectPattern(`\* OK *`)
 89	user2.Writeln(`. LOGIN user2@test1.maddy.email user2`)
 90	user2.ExpectPattern(`. OK *`)
 91	user2.Writeln(`. CREATE user2`)
 92	user2.ExpectPattern(`. OK *`)
 93
 94	user2SMTP := t.Conn("submission")
 95	defer user2SMTP.Close()
 96	user2SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
 97	user2SMTP.SMTPPlainAuth("user2@test1.maddy.email", "user2", true)
 98
 99	user3 := t.Conn("imap")
100	defer user3.Close()
101	user3.ExpectPattern(`\* OK *`)
102	user3.Writeln(`. LOGIN user1@test2.maddy.email user3`)
103	user3.ExpectPattern(`. OK *`)
104	user3.Writeln(`. CREATE user3`)
105	user3.ExpectPattern(`. OK *`)
106
107	user3SMTP := t.Conn("submission")
108	defer user3SMTP.Close()
109	user3SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
110	user3SMTP.SMTPPlainAuth("user1@test2.maddy.email", "user3", true)
111
112	user1.Writeln(`. LIST "" "*"`)
113	user1.Expect(`* LIST (\HasNoChildren) "." INBOX`)
114	user1.Expect(`* LIST (\HasNoChildren) "." "user1"`)
115	user1.ExpectPattern(". OK *")
116
117	user2.Writeln(`. LIST "" "*"`)
118	user2.Expect(`* LIST (\HasNoChildren) "." INBOX`)
119	user2.Expect(`* LIST (\HasNoChildren) "." "user2"`)
120	user2.ExpectPattern(". OK *")
121
122	user3.Writeln(`. LIST "" "*"`)
123	user3.Expect(`* LIST (\HasNoChildren) "." INBOX`)
124	user3.Expect(`* LIST (\HasNoChildren) "." "user3"`)
125	user3.ExpectPattern(". OK *")
126}
127
128func TestMultipleDomains_SharedCredentials_DistinctMailboxes(tt *testing.T) {
129	tt.Parallel()
130	t := tests.NewT(tt)
131	t.DNS(nil)
132	t.Port("submission")
133	t.Port("imap")
134	t.Config(`
135		tls off
136		hostname test.maddy.email
137		auth_map email_localpart
138
139		auth.pass_table local_authdb {
140			table sql_table {
141				driver sqlite3
142				dsn credentials.db
143				table_name passwords
144			}
145		}
146		storage.imapsql local_mailboxes {
147			driver sqlite3
148			dsn imapsql.db
149		}
150
151		submission tcp://0.0.0.0:{env:TEST_PORT_submission} {
152			auth &local_authdb
153			reject
154		}
155		imap tcp://127.0.0.1:{env:TEST_PORT_imap} {
156			auth &local_authdb
157			storage &local_mailboxes
158		}
159	`)
160
161	t.MustRunCLIGroup(
162		[]string{"creds", "create", "-p", "user1", "user1"},
163		[]string{"creds", "create", "-p", "user2", "user2"},
164		[]string{"imap-acct", "create", "--no-specialuse", "user1@test1.maddy.email"},
165		[]string{"imap-acct", "create", "--no-specialuse", "user2@test1.maddy.email"},
166		[]string{"imap-acct", "create", "--no-specialuse", "user1@test2.maddy.email"},
167	)
168	t.Run(2)
169
170	user1 := t.Conn("imap")
171	defer user1.Close()
172	user1.ExpectPattern(`\* OK *`)
173	user1.Writeln(`. LOGIN user1@test1.maddy.email user1`)
174	user1.ExpectPattern(`. OK *`)
175	user1.Writeln(`. CREATE user1`)
176	user1.ExpectPattern(`. OK *`)
177
178	user1SMTP := t.Conn("submission")
179	defer user1SMTP.Close()
180	user1SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
181	user1SMTP.SMTPPlainAuth("user1@test1.maddy.email", "user1", true)
182
183	user2 := t.Conn("imap")
184	defer user2.Close()
185	user2.ExpectPattern(`\* OK *`)
186	user2.Writeln(`. LOGIN user2@test1.maddy.email user2`)
187	user2.ExpectPattern(`. OK *`)
188	user2.Writeln(`. CREATE user2`)
189	user2.ExpectPattern(`. OK *`)
190
191	user2SMTP := t.Conn("submission")
192	defer user2SMTP.Close()
193	user2SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
194	user2SMTP.SMTPPlainAuth("user2@test1.maddy.email", "user2", true)
195
196	user3 := t.Conn("imap")
197	defer user3.Close()
198	user3.ExpectPattern(`\* OK *`)
199	user3.Writeln(`. LOGIN user1@test2.maddy.email user1`)
200	user3.ExpectPattern(`. OK *`)
201	user3.Writeln(`. CREATE user3`)
202	user3.ExpectPattern(`. OK *`)
203
204	user3SMTP := t.Conn("submission")
205	defer user3SMTP.Close()
206	user3SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
207	user3SMTP.SMTPPlainAuth("user1@test2.maddy.email", "user1", true)
208
209	user1.Writeln(`. LIST "" "*"`)
210	user1.Expect(`* LIST (\HasNoChildren) "." INBOX`)
211	user1.Expect(`* LIST (\HasNoChildren) "." "user1"`)
212	user1.ExpectPattern(". OK *")
213
214	user2.Writeln(`. LIST "" "*"`)
215	user2.Expect(`* LIST (\HasNoChildren) "." INBOX`)
216	user2.Expect(`* LIST (\HasNoChildren) "." "user2"`)
217	user2.ExpectPattern(". OK *")
218
219	user3.Writeln(`. LIST "" "*"`)
220	user3.Expect(`* LIST (\HasNoChildren) "." INBOX`)
221	user3.Expect(`* LIST (\HasNoChildren) "." "user3"`)
222	user3.ExpectPattern(". OK *")
223}
224
225func TestMultipleDomains_SharedCredentials_SharedMailboxes(tt *testing.T) {
226	tt.Parallel()
227	t := tests.NewT(tt)
228	t.DNS(nil)
229	t.Port("submission")
230	t.Port("imap")
231	t.Config(`
232		tls off
233		hostname test.maddy.email
234		auth_map email_localpart_optional
235
236		auth.pass_table local_authdb {
237			table sql_table {
238				driver sqlite3
239				dsn credentials.db
240				table_name passwords
241			}
242		}
243		storage.imapsql local_mailboxes {
244			driver sqlite3
245			dsn imapsql.db
246
247			delivery_map email_localpart_optional
248		}
249
250		submission tcp://0.0.0.0:{env:TEST_PORT_submission} {
251			auth &local_authdb
252			reject
253		}
254		imap tcp://127.0.0.1:{env:TEST_PORT_imap} {
255			auth &local_authdb
256			storage &local_mailboxes
257
258			storage_map email_localpart_optional
259		}
260	`)
261
262	t.MustRunCLIGroup(
263		[]string{"creds", "create", "-p", "user1", "user1"},
264		[]string{"creds", "create", "-p", "user2", "user2"},
265		[]string{"imap-acct", "create", "--no-specialuse", "user1"},
266		[]string{"imap-acct", "create", "--no-specialuse", "user2"},
267	)
268	t.Run(2)
269
270	user1 := t.Conn("imap")
271	defer user1.Close()
272	user1.ExpectPattern(`\* OK *`)
273	user1.Writeln(`. LOGIN user1 user1`)
274	user1.ExpectPattern(`. OK *`)
275	user1.Writeln(`. CREATE user1`)
276	user1.ExpectPattern(`. OK *`)
277
278	user1SMTP := t.Conn("submission")
279	defer user1SMTP.Close()
280	user1SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
281	user1SMTP.SMTPPlainAuth("user1", "user1", true)
282
283	user2 := t.Conn("imap")
284	defer user2.Close()
285	user2.ExpectPattern(`\* OK *`)
286	user2.Writeln(`. LOGIN user2@test1.maddy.email user2`)
287	user2.ExpectPattern(`. OK *`)
288	user2.Writeln(`. CREATE user2`)
289	user2.ExpectPattern(`. OK *`)
290
291	user2SMTP := t.Conn("submission")
292	defer user2SMTP.Close()
293	user2SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
294	user2SMTP.SMTPPlainAuth("user2", "user2", true)
295
296	user12 := t.Conn("imap")
297	defer user12.Close()
298	user12.ExpectPattern(`\* OK *`)
299	user12.Writeln(`. LOGIN user1@test2.maddy.email user1`)
300	user12.ExpectPattern(`. OK *`)
301	user12.Writeln(`. CREATE user12`)
302	user12.ExpectPattern(`. OK *`)
303
304	user13 := t.Conn("imap")
305	defer user13.Close()
306	user13.ExpectPattern(`\* OK *`)
307	user13.Writeln(`. LOGIN user1@test.maddy.email user1`)
308	user13.ExpectPattern(`. OK *`)
309	user13.Writeln(`. CREATE user13`)
310	user13.ExpectPattern(`. OK *`)
311
312	user12SMTP := t.Conn("submission")
313	defer user12SMTP.Close()
314	user12SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
315	user12SMTP.SMTPPlainAuth("user1", "user1", true)
316
317	user13SMTP := t.Conn("submission")
318	defer user13SMTP.Close()
319	user13SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)
320	user13SMTP.SMTPPlainAuth("user1@test.maddy.email", "user1", true)
321
322	user1.Writeln(`. LIST "" "*"`)
323	user1.Expect(`* LIST (\HasNoChildren) "." INBOX`)
324	user1.Expect(`* LIST (\HasNoChildren) "." "user1"`)
325	user1.Expect(`* LIST (\HasNoChildren) "." "user12"`)
326	user1.Expect(`* LIST (\HasNoChildren) "." "user13"`)
327	user1.ExpectPattern(". OK *")
328
329	user2.Writeln(`. LIST "" "*"`)
330	user2.Expect(`* LIST (\HasNoChildren) "." INBOX`)
331	user2.Expect(`* LIST (\HasNoChildren) "." "user2"`)
332	user2.ExpectPattern(". OK *")
333
334	user12.Writeln(`. LIST "" "*"`)
335	user12.Expect(`* LIST (\HasNoChildren) "." INBOX`)
336	user12.Expect(`* LIST (\HasNoChildren) "." "user1"`)
337	user12.Expect(`* LIST (\HasNoChildren) "." "user12"`)
338	user12.Expect(`* LIST (\HasNoChildren) "." "user13"`)
339	user12.ExpectPattern(". OK *")
340}