Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::{AssertResult, ImapConnection, Type, append::assert_append_message};
|
||||
use crate::utils::{server::TestServer, smtp::SmtpConnection};
|
||||
use imap_proto::ResponseType;
|
||||
|
||||
pub async fn test(
|
||||
mut imap_john: &mut ImapConnection,
|
||||
_imap_check: &mut ImapConnection,
|
||||
test: &TestServer,
|
||||
) {
|
||||
// Delivery to support account
|
||||
println!("Running ACL tests...");
|
||||
let mut lmtp = SmtpConnection::connect().await;
|
||||
lmtp.ingest(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
concat!(
|
||||
"From: [email protected]\r\n",
|
||||
"To: [email protected]\r\n",
|
||||
"Subject: TPS Report\r\n",
|
||||
"\r\n",
|
||||
"I'm going to need those TPS reports ASAP. ",
|
||||
"So, if you could do that, that'd be great."
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Connect to all test accounts
|
||||
let mut imap_jane = test.account("[email protected]").imap_client().await;
|
||||
let mut imap_bill = test.account("[email protected]").imap_client().await;
|
||||
|
||||
// Jane should see the Support account
|
||||
imap_jane.send("LIST \"\" \"*\"").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("Shared Folders/[email protected]/INBOX");
|
||||
imap_jane
|
||||
.send("SELECT \"Shared Folders/[email protected]/INBOX\"")
|
||||
.await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap_jane.send("FETCH 1 (PREVIEW)").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("TPS reports ASAP");
|
||||
imap_jane.send("UNSELECT").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Jane should be able to create folders under the Support account
|
||||
imap_jane
|
||||
.send("CREATE \"Shared Folders/[email protected]/inbox/Jane's Folder\"")
|
||||
.await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap_jane.send("LIST \"\" \"*\"").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_equals(
|
||||
"* LIST () \"/\" \"Shared Folders/[email protected]/INBOX/Jane's Folder\"",
|
||||
);
|
||||
imap_jane
|
||||
.send("DELETE \"Shared Folders/[email protected]/INBOX/Jane's Folder\"")
|
||||
.await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// John should have no shared folders
|
||||
imap_john.send("LIST \"\" \"*\"").await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("Shared Folders", 0);
|
||||
imap_john.send("NAMESPACE").await;
|
||||
imap_john.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// List rights
|
||||
imap_jane.send("LISTRIGHTS INBOX [email protected]").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_equals("* LISTRIGHTS \"INBOX\" \"[email protected]\" r l ws i et k x p a");
|
||||
|
||||
// Jane shares her Inbox to John, expect a Shared Folders item in John's list
|
||||
imap_jane.send("SETACL INBOX [email protected] lr").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap_john.send("LIST \"\" \"*\"").await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_equals("* LIST (\\NoSelect) \"/\" \"Shared Folders\"")
|
||||
.assert_equals("* LIST (\\NoSelect) \"/\" \"Shared Folders/[email protected]\"")
|
||||
.assert_equals("* LIST () \"/\" \"Shared Folders/[email protected]/INBOX\"");
|
||||
|
||||
// Grant access to Bill and check ACLs
|
||||
imap_jane.send("GETACL INBOX").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("\"[email protected]\" rl");
|
||||
|
||||
imap_jane
|
||||
.send("SETACL INBOX [email protected] lrxtws")
|
||||
.await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane.send("GETACL INBOX").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("\"[email protected]\" rl")
|
||||
.assert_contains("\"[email protected]\" tewsrxl");
|
||||
|
||||
imap_bill.send("LIST \"\" \"*\"").await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("Shared Folders/[email protected]/INBOX");
|
||||
|
||||
// Namespace should now return the Shared Folders namespace
|
||||
imap_john.send("NAMESPACE").await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_equals("* NAMESPACE ((\"\" \"/\")) ((\"Shared Folders\" \"/\")) NIL");
|
||||
|
||||
// List John's right on Jane's Inbox
|
||||
imap_john
|
||||
.send("MYRIGHTS \"Shared Folders/[email protected]/INBOX\"")
|
||||
.await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_equals("* MYRIGHTS \"Shared Folders/[email protected]/INBOX\" rl");
|
||||
|
||||
// John should not be able to append messages
|
||||
assert_append_message(
|
||||
imap_john,
|
||||
"Shared Folders/[email protected]/INBOX",
|
||||
"From: john\n\ncontents",
|
||||
ResponseType::No,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Grant insert access to John on Jane's Inbox, and try inserting the
|
||||
// message again.
|
||||
imap_jane.send("SETACL INBOX [email protected] +i").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap_john
|
||||
.send("MYRIGHTS \"Shared Folders/[email protected]/INBOX\"")
|
||||
.await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_equals("* MYRIGHTS \"Shared Folders/[email protected]/INBOX\" rli");
|
||||
assert_append_message(
|
||||
imap_john,
|
||||
"Shared Folders/[email protected]/INBOX",
|
||||
"From: john\n\ncontents",
|
||||
ResponseType::Ok,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Only Bill should be allowed to delete messages on Jane's Inbox
|
||||
for imap in [&mut imap_john, &mut imap_bill] {
|
||||
imap.send("SELECT \"Shared Folders/[email protected]/INBOX\"")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
}
|
||||
imap_john.send("UID STORE 1 +FLAGS (\\Deleted)").await;
|
||||
imap_john.assert_read(Type::Tagged, ResponseType::No).await;
|
||||
|
||||
imap_bill.send("UID STORE 1 +FLAGS (\\Deleted)").await;
|
||||
imap_bill.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_john.send("UID EXPUNGE").await;
|
||||
imap_john.assert_read(Type::Tagged, ResponseType::No).await;
|
||||
|
||||
imap_john.send("UID FETCH 1 (PREVIEW)").await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("contents");
|
||||
|
||||
imap_bill.send("UID EXPUNGE").await;
|
||||
imap_bill.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_bill.send("UID FETCH 1 (PREVIEW)").await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("contents", 0);
|
||||
|
||||
imap_bill
|
||||
.send("STATUS \"Shared Folders/[email protected]/INBOX\" (MESSAGES)")
|
||||
.await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("(MESSAGES 0)");
|
||||
|
||||
// Test copying and moving between shared mailboxes
|
||||
let uid = assert_append_message(
|
||||
imap_john,
|
||||
"INBOX",
|
||||
"From: john\n\ncopy test",
|
||||
ResponseType::Ok,
|
||||
)
|
||||
.await
|
||||
.into_append_uid();
|
||||
|
||||
imap_john.send("SELECT INBOX").await;
|
||||
imap_john.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Copy from John's Inbox to Jane's Inbox
|
||||
imap_john
|
||||
.send(&format!(
|
||||
"UID COPY {} \"Shared Folders/[email protected]/INBOX\"",
|
||||
uid
|
||||
))
|
||||
.await;
|
||||
let uid = imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.into_copy_uid();
|
||||
|
||||
// Check that both Bill and Jane can see the message
|
||||
imap_bill.send("NOOP").await;
|
||||
imap_bill.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_bill
|
||||
.send(&format!("UID FETCH {} (PREVIEW)", uid))
|
||||
.await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("copy test");
|
||||
|
||||
imap_jane.send("SELECT INBOX").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane
|
||||
.send(&format!("UID FETCH {} (PREVIEW)", uid))
|
||||
.await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("copy test");
|
||||
|
||||
// Bill now moves the message to his own Inbox
|
||||
imap_bill.send(&format!("UID MOVE {} INBOX", uid)).await;
|
||||
let uid_moved = imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.into_copy_uid();
|
||||
|
||||
// Both Jane and Bill should not see the message on Jane's Inbox anymore
|
||||
imap_bill
|
||||
.send(&format!("UID FETCH {} (PREVIEW)", uid))
|
||||
.await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("copy test", 0);
|
||||
|
||||
imap_jane
|
||||
.send(&format!("UID FETCH {} (PREVIEW)", uid))
|
||||
.await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("copy test", 0);
|
||||
|
||||
// Check that the message has been moved to Bill's Inbox
|
||||
imap_bill.send("SELECT INBOX").await;
|
||||
imap_bill.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_bill
|
||||
.send(&format!("UID FETCH {} (PREVIEW)", uid_moved))
|
||||
.await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("copy test");
|
||||
|
||||
// Repeating a cross-account copy returns the existing destination UID
|
||||
// instead of creating a duplicate, and moving a message that the destination
|
||||
// account already holds still expunges the source.
|
||||
let uid_dedup = assert_append_message(
|
||||
imap_john,
|
||||
"INBOX",
|
||||
concat!(
|
||||
"Message-ID: <[email protected]>\n",
|
||||
"From: john\n",
|
||||
"Subject: dedup\n",
|
||||
"\n",
|
||||
"dedup test"
|
||||
),
|
||||
ResponseType::Ok,
|
||||
)
|
||||
.await
|
||||
.into_append_uid();
|
||||
|
||||
imap_john
|
||||
.send(&format!(
|
||||
"UID COPY {} \"Shared Folders/[email protected]/INBOX\"",
|
||||
uid_dedup
|
||||
))
|
||||
.await;
|
||||
let uid_dedup_dest = imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.into_copy_uid();
|
||||
|
||||
imap_john
|
||||
.send(&format!(
|
||||
"UID COPY {} \"Shared Folders/[email protected]/INBOX\"",
|
||||
uid_dedup
|
||||
))
|
||||
.await;
|
||||
assert_eq!(
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.into_copy_uid(),
|
||||
uid_dedup_dest
|
||||
);
|
||||
|
||||
imap_jane.send("NOOP").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane.send("UID FETCH 1:* (PREVIEW)").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("dedup test", 1);
|
||||
|
||||
imap_john
|
||||
.send(&format!(
|
||||
"UID MOVE {} \"Shared Folders/[email protected]/INBOX\"",
|
||||
uid_dedup
|
||||
))
|
||||
.await;
|
||||
assert_eq!(
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.into_copy_uid(),
|
||||
uid_dedup_dest
|
||||
);
|
||||
|
||||
imap_john
|
||||
.send(&format!("UID FETCH {} (PREVIEW)", uid_dedup))
|
||||
.await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("dedup test", 0);
|
||||
|
||||
// Jane stops sharing with Bill, and removes Insert access to John
|
||||
imap_jane.send("DELETEACL INBOX [email protected]").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane.send("SETACL INBOX [email protected] -i").await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane.send("GETACL INBOX").await;
|
||||
imap_jane
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("\"[email protected]\" rl")
|
||||
.assert_count("[email protected]", 0);
|
||||
|
||||
// Bill should not have access to Jane's Inbox anymore
|
||||
imap_bill.send("LIST \"\" \"*\"").await;
|
||||
imap_bill
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("Shared Folders", 0);
|
||||
|
||||
// And John should still have access
|
||||
imap_john.send("LIST \"\" \"*\"").await;
|
||||
imap_john
|
||||
.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_count("Shared Folders", 3);
|
||||
}
|
||||
Reference in New Issue
Block a user