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,455 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use imap::op::list::matches_pattern;
|
||||
use imap_proto::ResponseType;
|
||||
|
||||
use crate::utils::server::TestServer;
|
||||
|
||||
use super::{AssertResult, ImapConnection, Type};
|
||||
|
||||
pub async fn test(
|
||||
mut imap: &mut ImapConnection,
|
||||
mut imap_check: &mut ImapConnection,
|
||||
test: &TestServer,
|
||||
) {
|
||||
println!("Running mailbox tests...");
|
||||
|
||||
// Pattern matching tests
|
||||
mailbox_matches_pattern();
|
||||
|
||||
// Create third connection for testing
|
||||
let mut other_conn = test.account("[email protected]").imap_client().await;
|
||||
|
||||
// List folders
|
||||
imap.send("LIST \"\" \"*\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders([("INBOX", [""]), ("Deleted Items", [""])], true);
|
||||
|
||||
// Create folders
|
||||
imap.send("CREATE \"Tofu\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("CREATE \"Fruit\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("CREATE \"Fruit/Apple\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("CREATE \"Fruit/Apple/Green\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("CREATE \"L&APg-bende opgaver\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Select folder from another connection
|
||||
other_conn.send("SELECT \"Tofu\"").await;
|
||||
other_conn.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
other_conn.send("SELECT \"L&APg-bende opgaver\"").await;
|
||||
other_conn.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Make sure folders are visible
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("LIST \"\" \"*\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", [""]),
|
||||
("Deleted Items", [""]),
|
||||
("Fruit", [""]),
|
||||
("Fruit/Apple", [""]),
|
||||
("Fruit/Apple/Green", [""]),
|
||||
("Tofu", [""]),
|
||||
("L&APg-bende opgaver", [""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
}
|
||||
imap.send("DELETE \"L&APg-bende opgaver\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Special use folders that already exist should not be allowed
|
||||
imap.send("CREATE \"Second trash\" (USE (\\Trash))").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::No).await;
|
||||
|
||||
// Every command in a pipelined batch is answered, even after a failure
|
||||
imap.send_raw(concat!(
|
||||
"_p1 STATUS \"Tofu\" (MESSAGES)\r\n",
|
||||
"_p2 STATUS \"Does Not Exist\" (MESSAGES)\r\n",
|
||||
"_x STATUS \"Fruit/Apple\" (MESSAGES)\r\n"
|
||||
))
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_contains("_p1 OK")
|
||||
.assert_contains("_p2 NO [NONEXISTENT]")
|
||||
.assert_contains("* STATUS \"Fruit/Apple\"");
|
||||
|
||||
// Enable IMAP4rev2
|
||||
imap.send("ENABLE IMAP4rev2").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Create and delete using IMAP4rev2
|
||||
imap.send("CREATE \"L&APg-bende opgaver\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("SELECT \"L&APg-bende opgaver\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("UNSELECT \"L&APg-bende opgaver\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("DELETE \"L&APg-bende opgaver\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Create missing parent folders
|
||||
imap.send("CREATE \"/Vegetable/Broccoli\" (USE (\\Important))")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap.send("CREATE \" Cars/Electric /4 doors/ Red/\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("LIST \"\" \"*\" RETURN (CHILDREN SPECIAL-USE)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", ["HasNoChildren", ""]),
|
||||
("Deleted Items", ["HasNoChildren", "Trash"]),
|
||||
("Cars/Electric/4 doors/Red", ["HasNoChildren", ""]),
|
||||
("Cars/Electric/4 doors", ["HasChildren", ""]),
|
||||
("Cars/Electric", ["HasChildren", ""]),
|
||||
("Cars", ["HasChildren", ""]),
|
||||
("Fruit", ["HasChildren", ""]),
|
||||
("Fruit/Apple", ["HasChildren", ""]),
|
||||
("Fruit/Apple/Green", ["HasNoChildren", ""]),
|
||||
("Vegetable", ["HasChildren", ""]),
|
||||
("Vegetable/Broccoli", ["HasNoChildren", "\\Important"]),
|
||||
("Tofu", ["HasNoChildren", ""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
// Rename folders
|
||||
imap.send("RENAME \"Fruit/Apple/Green\" \"Fruit/Apple/Red\"")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("RENAME \"Cars\" \"Vehicles\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("RENAME \"Vegetable/Broccoli\" \"Veggies/Green/Broccoli\"")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("RENAME \"Tofu\" \"INBOX\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::No).await;
|
||||
imap.send("RENAME \"Tofu\" \"Inbox/Tofu\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("RENAME \"Deleted Items\" \"Recycle Bin\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("LIST \"\" \"*\" RETURN (CHILDREN SPECIAL-USE)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", ["HasChildren", ""]),
|
||||
("INBOX/Tofu", ["HasNoChildren", ""]),
|
||||
("Recycle Bin", ["HasNoChildren", "Trash"]),
|
||||
("Vehicles/Electric/4 doors/Red", ["HasNoChildren", ""]),
|
||||
("Vehicles/Electric/4 doors", ["HasChildren", ""]),
|
||||
("Vehicles/Electric", ["HasChildren", ""]),
|
||||
("Vehicles", ["HasChildren", ""]),
|
||||
("Fruit", ["HasChildren", ""]),
|
||||
("Fruit/Apple", ["HasChildren", ""]),
|
||||
("Fruit/Apple/Red", ["HasNoChildren", ""]),
|
||||
("Vegetable", ["HasNoChildren", ""]),
|
||||
("Veggies", ["HasChildren", ""]),
|
||||
("Veggies/Green", ["HasChildren", ""]),
|
||||
("Veggies/Green/Broccoli", ["HasNoChildren", ""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
// Delete folders
|
||||
imap.send("DELETE \"INBOX/Tofu\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("DELETE \"Vegetable\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("DELETE \"Vehicles\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::No).await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("LIST \"\" \"*\" RETURN (CHILDREN SPECIAL-USE)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", ["HasNoChildren", ""]),
|
||||
("Recycle Bin", ["HasNoChildren", "Trash"]),
|
||||
("Vehicles/Electric/4 doors/Red", ["HasNoChildren", ""]),
|
||||
("Vehicles/Electric/4 doors", ["HasChildren", ""]),
|
||||
("Vehicles/Electric", ["HasChildren", ""]),
|
||||
("Vehicles", ["HasChildren", ""]),
|
||||
("Fruit", ["HasChildren", ""]),
|
||||
("Fruit/Apple", ["HasChildren", ""]),
|
||||
("Fruit/Apple/Red", ["HasNoChildren", ""]),
|
||||
("Veggies", ["HasChildren", ""]),
|
||||
("Veggies/Green", ["HasChildren", ""]),
|
||||
("Veggies/Green/Broccoli", ["HasNoChildren", ""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
// Subscribe
|
||||
imap.send("SUBSCRIBE \"INBOX\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
imap.send("SUBSCRIBE \"Vehicles/Electric/4 doors/Red\"")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("LIST \"\" \"*\" RETURN (SUBSCRIBED SPECIAL-USE)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", ["Subscribed", ""]),
|
||||
("Recycle Bin", ["", "Trash"]),
|
||||
("Vehicles/Electric/4 doors/Red", ["Subscribed", ""]),
|
||||
("Vehicles/Electric/4 doors", ["", ""]),
|
||||
("Vehicles/Electric", ["", ""]),
|
||||
("Vehicles", ["", ""]),
|
||||
("Fruit", ["", ""]),
|
||||
("Fruit/Apple", ["", ""]),
|
||||
("Fruit/Apple/Red", ["", ""]),
|
||||
("Veggies", ["", ""]),
|
||||
("Veggies/Green", ["", ""]),
|
||||
("Veggies/Green/Broccoli", ["", ""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
// Filter by subscribed including children
|
||||
imap.send("LIST (SUBSCRIBED) \"\" \"*\" RETURN (CHILDREN)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", ["Subscribed", "HasNoChildren"]),
|
||||
(
|
||||
"Vehicles/Electric/4 doors/Red",
|
||||
["Subscribed", "HasNoChildren"],
|
||||
),
|
||||
],
|
||||
true,
|
||||
);
|
||||
|
||||
// Recursive match including children
|
||||
imap.send("LIST (SUBSCRIBED RECURSIVEMATCH) \"\" \"*\" RETURN (CHILDREN)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", ["Subscribed", "HasNoChildren"]),
|
||||
(
|
||||
"Vehicles/Electric/4 doors/Red",
|
||||
["Subscribed", "HasNoChildren"],
|
||||
),
|
||||
(
|
||||
"Vehicles/Electric/4 doors",
|
||||
["\"CHILDINFO\" (\"SUBSCRIBED\")", "HasChildren"],
|
||||
),
|
||||
(
|
||||
"Vehicles/Electric",
|
||||
["\"CHILDINFO\" (\"SUBSCRIBED\")", "HasChildren"],
|
||||
),
|
||||
(
|
||||
"Vehicles",
|
||||
["\"CHILDINFO\" (\"SUBSCRIBED\")", "HasChildren"],
|
||||
),
|
||||
],
|
||||
true,
|
||||
);
|
||||
|
||||
// Imap4rev1 LSUB
|
||||
imap.send("LSUB \"\" \"*\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[("INBOX", [""]), ("Vehicles/Electric/4 doors/Red", [""])],
|
||||
true,
|
||||
);
|
||||
|
||||
// Unsubscribe
|
||||
imap.send("UNSUBSCRIBE \"Vehicles/Electric/4 doors/Red\"")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
for imap in [&mut imap, &mut imap_check] {
|
||||
imap.send("LIST (SUBSCRIBED RECURSIVEMATCH) \"\" \"*\" RETURN (CHILDREN)")
|
||||
.await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders([("INBOX", ["Subscribed", "HasNoChildren"])], true);
|
||||
}
|
||||
|
||||
// LIST Filters
|
||||
imap.send("LIST \"\" \"%\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("INBOX", [""]),
|
||||
("Recycle Bin", [""]),
|
||||
("Vehicles", [""]),
|
||||
("Fruit", [""]),
|
||||
("Veggies", [""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
|
||||
imap.send("LIST \"\" \"*/Red\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders(
|
||||
[
|
||||
("Vehicles/Electric/4 doors/Red", [""]),
|
||||
("Fruit/Apple/Red", [""]),
|
||||
],
|
||||
true,
|
||||
);
|
||||
|
||||
imap.send("LIST \"\" \"Fruit/*\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders([("Fruit/Apple/Red", [""]), ("Fruit/Apple", [""])], true);
|
||||
|
||||
imap.send("LIST \"\" \"Fruit/%\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok)
|
||||
.await
|
||||
.assert_folders([("Fruit/Apple", [""])], true);
|
||||
|
||||
// Restore Trash folder's original name
|
||||
imap.send("RENAME \"Recycle Bin\" \"Deleted Items\"").await;
|
||||
imap.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
// Shared folder creation tests
|
||||
let mut imap_jane = test.account("[email protected]").imap_client().await;
|
||||
imap_jane
|
||||
.send("CREATE \"Shared Folders/[email protected]/INBOX/Test\"")
|
||||
.await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane
|
||||
.send("CREATE \"Shared Folders/[email protected]/Test\"")
|
||||
.await;
|
||||
imap_jane.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
|
||||
imap_jane
|
||||
.send("CREATE \"Shared Folders/[email protected]/Test/TestSubfolder\"")
|
||||
.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_folders(
|
||||
[
|
||||
("INBOX", [""]),
|
||||
("Deleted Items", [""]),
|
||||
("Drafts", [""]),
|
||||
("Junk Mail", [""]),
|
||||
("Sent Items", [""]),
|
||||
("Shared Folders", [""]),
|
||||
("Shared Folders/[email protected]", [""]),
|
||||
("Shared Folders/[email protected]/Deleted Items", [""]),
|
||||
("Shared Folders/[email protected]/Drafts", [""]),
|
||||
("Shared Folders/[email protected]/INBOX", [""]),
|
||||
("Shared Folders/[email protected]/INBOX/Test", [""]),
|
||||
("Shared Folders/[email protected]/Junk Mail", [""]),
|
||||
("Shared Folders/[email protected]/Sent Items", [""]),
|
||||
("Shared Folders/[email protected]/Test", [""]),
|
||||
(
|
||||
"Shared Folders/[email protected]/Test/TestSubfolder",
|
||||
[""],
|
||||
),
|
||||
],
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
fn mailbox_matches_pattern() {
|
||||
let mailboxes = [
|
||||
"imaptest",
|
||||
"imaptest/test",
|
||||
"imaptest/test2",
|
||||
"imaptest/test3",
|
||||
"imaptest/test3/test4",
|
||||
"imaptest/test3/test4/test5",
|
||||
"foobar/test",
|
||||
"foobar/test/test",
|
||||
"foobar/test1/test1",
|
||||
];
|
||||
|
||||
for (pattern, expected_match) in [
|
||||
(
|
||||
"imaptest/%",
|
||||
vec!["imaptest/test", "imaptest/test2", "imaptest/test3"],
|
||||
),
|
||||
("imaptest/%/%", vec!["imaptest/test3/test4"]),
|
||||
(
|
||||
"imaptest/*",
|
||||
vec![
|
||||
"imaptest/test",
|
||||
"imaptest/test2",
|
||||
"imaptest/test3",
|
||||
"imaptest/test3/test4",
|
||||
"imaptest/test3/test4/test5",
|
||||
],
|
||||
),
|
||||
("imaptest/*test4", vec!["imaptest/test3/test4"]),
|
||||
(
|
||||
"imaptest/*test*",
|
||||
vec![
|
||||
"imaptest/test",
|
||||
"imaptest/test2",
|
||||
"imaptest/test3",
|
||||
"imaptest/test3/test4",
|
||||
"imaptest/test3/test4/test5",
|
||||
],
|
||||
),
|
||||
("imaptest/%3/%", vec!["imaptest/test3/test4"]),
|
||||
("imaptest/%3/%4", vec!["imaptest/test3/test4"]),
|
||||
("imaptest/%t*4", vec!["imaptest/test3/test4"]),
|
||||
("*st/%3/%4/%5", vec!["imaptest/test3/test4/test5"]),
|
||||
(
|
||||
"*%*%*%",
|
||||
vec![
|
||||
"imaptest",
|
||||
"imaptest/test",
|
||||
"imaptest/test2",
|
||||
"imaptest/test3",
|
||||
"imaptest/test3/test4",
|
||||
"imaptest/test3/test4/test5",
|
||||
"foobar/test",
|
||||
"foobar/test/test",
|
||||
"foobar/test1/test1",
|
||||
],
|
||||
),
|
||||
("foobar*test", vec!["foobar/test", "foobar/test/test"]),
|
||||
] {
|
||||
let patterns = vec![pattern.into()];
|
||||
let mut matched_mailboxes = Vec::new();
|
||||
for mailbox in mailboxes {
|
||||
if matches_pattern(&patterns, mailbox) {
|
||||
matched_mailboxes.push(mailbox);
|
||||
}
|
||||
}
|
||||
assert_eq!(matched_mailboxes, expected_match, "for pattern {}", pattern);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user