1//go:build integration23/*4Maddy Mail Server - Composable all-in-one email server.5Copyright © 2019-2025 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors67This program is free software: you can redistribute it and/or modify8it under the terms of the GNU General Public License as published by9the Free Software Foundation, either version 3 of the License, or10(at your option) any later version.1112This program is distributed in the hope that it will be useful,13but WITHOUT ANY WARRANTY; without even the implied warranty of14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15GNU General Public License for more details.1617You should have received a copy of the GNU General Public License18along with this program. If not, see <https://www.gnu.org/licenses/>.19*/2021package tests_test2223import (24 "testing"2526 "github.com/foxcpp/maddy/tests"27)2829// Test cases based on https://maddy.email/multiple-domains/3031func 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 off39 hostname test.maddy.email4041 auth.pass_table local_authdb {42 table sql_table {43 driver sqlite344 dsn credentials.db45 table_name passwords46 }47 }48 storage.imapsql local_mailboxes {49 driver sqlite350 dsn imapsql.db51 }5253 submission tcp://0.0.0.0:{env:TEST_PORT_submission} {54 auth &local_authdb55 reject56 }57 imap tcp://127.0.0.1:{env:TEST_PORT_imap} {58 auth &local_authdb59 storage &local_mailboxes60 }61 `)6263 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)7273 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 *`)8081 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)8586 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 *`)9394 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)9899 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 *`)106107 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)111112 user1.Writeln(`. LIST "" "*"`)113 user1.Expect(`* LIST (\HasNoChildren) "." INBOX`)114 user1.Expect(`* LIST (\HasNoChildren) "." "user1"`)115 user1.ExpectPattern(". OK *")116117 user2.Writeln(`. LIST "" "*"`)118 user2.Expect(`* LIST (\HasNoChildren) "." INBOX`)119 user2.Expect(`* LIST (\HasNoChildren) "." "user2"`)120 user2.ExpectPattern(". OK *")121122 user3.Writeln(`. LIST "" "*"`)123 user3.Expect(`* LIST (\HasNoChildren) "." INBOX`)124 user3.Expect(`* LIST (\HasNoChildren) "." "user3"`)125 user3.ExpectPattern(". OK *")126}127128func 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 off136 hostname test.maddy.email137 auth_map email_localpart138139 auth.pass_table local_authdb {140 table sql_table {141 driver sqlite3142 dsn credentials.db143 table_name passwords144 }145 }146 storage.imapsql local_mailboxes {147 driver sqlite3148 dsn imapsql.db149 }150151 submission tcp://0.0.0.0:{env:TEST_PORT_submission} {152 auth &local_authdb153 reject154 }155 imap tcp://127.0.0.1:{env:TEST_PORT_imap} {156 auth &local_authdb157 storage &local_mailboxes158 }159 `)160161 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)169170 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 *`)177178 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)182183 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 *`)190191 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)195196 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 *`)203204 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)208209 user1.Writeln(`. LIST "" "*"`)210 user1.Expect(`* LIST (\HasNoChildren) "." INBOX`)211 user1.Expect(`* LIST (\HasNoChildren) "." "user1"`)212 user1.ExpectPattern(". OK *")213214 user2.Writeln(`. LIST "" "*"`)215 user2.Expect(`* LIST (\HasNoChildren) "." INBOX`)216 user2.Expect(`* LIST (\HasNoChildren) "." "user2"`)217 user2.ExpectPattern(". OK *")218219 user3.Writeln(`. LIST "" "*"`)220 user3.Expect(`* LIST (\HasNoChildren) "." INBOX`)221 user3.Expect(`* LIST (\HasNoChildren) "." "user3"`)222 user3.ExpectPattern(". OK *")223}224225func 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 off233 hostname test.maddy.email234 auth_map email_localpart_optional235236 auth.pass_table local_authdb {237 table sql_table {238 driver sqlite3239 dsn credentials.db240 table_name passwords241 }242 }243 storage.imapsql local_mailboxes {244 driver sqlite3245 dsn imapsql.db246247 delivery_map email_localpart_optional248 }249250 submission tcp://0.0.0.0:{env:TEST_PORT_submission} {251 auth &local_authdb252 reject253 }254 imap tcp://127.0.0.1:{env:TEST_PORT_imap} {255 auth &local_authdb256 storage &local_mailboxes257258 storage_map email_localpart_optional259 }260 `)261262 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)269270 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 *`)277278 user1SMTP := t.Conn("submission")279 defer user1SMTP.Close()280 user1SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)281 user1SMTP.SMTPPlainAuth("user1", "user1", true)282283 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 *`)290291 user2SMTP := t.Conn("submission")292 defer user2SMTP.Close()293 user2SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)294 user2SMTP.SMTPPlainAuth("user2", "user2", true)295296 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 *`)303304 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 *`)311312 user12SMTP := t.Conn("submission")313 defer user12SMTP.Close()314 user12SMTP.SMTPNegotation("localhost", []string{"AUTH PLAIN"}, nil)315 user12SMTP.SMTPPlainAuth("user1", "user1", true)316317 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)321322 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 *")328329 user2.Writeln(`. LIST "" "*"`)330 user2.Expect(`* LIST (\HasNoChildren) "." INBOX`)331 user2.Expect(`* LIST (\HasNoChildren) "." "user2"`)332 user2.ExpectPattern(". OK *")333334 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}