Skip to content

Add quotes for some commands to support mailbox with whitespace#127

Merged
link2xt merged 2 commits intochatmail:mainfrom
dayo05:main
Feb 6, 2026
Merged

Add quotes for some commands to support mailbox with whitespace#127
link2xt merged 2 commits intochatmail:mainfrom
dayo05:main

Conversation

@dayo05
Copy link
Contributor

@dayo05 dayo05 commented Jan 25, 2026

For current state of project, it sends raw data as:

async-imap/src/client.rs

Lines 839 to 843 in 15f80ea

self.run_command_and_check_ok(&format!(
"COPY {} {}",
sequence_set.as_ref(),
mailbox_name.as_ref()
))

This works well for most cases but not with mailbox with whitespace.

whitespace is separator for argument on IMAP protocol, so this can lead undefined behavior(or not expected error).

This PR adds quotes for all COPY, MOVE, LIST, LSUB mailbox querying.

I am working with icloud mail which seems just ignore if whitespace exists on create command but I am not sure is this standard action.

Thanks for wonderful project :)

@dayo05
Copy link
Contributor Author

dayo05 commented Feb 2, 2026

async-imap/src/client.rs

Lines 2142 to 2164 in 15f80ea

async fn generic_with_uid<'a, F, T, K>(
res: &'a str,
cmd: &'a str,
seq: &'a str,
query: &'a str,
prefix: &'a str,
op: F,
) where
F: 'a + FnOnce(Arc<Mutex<Session<MockStream>>>, &'a str, &'a str) -> K,
K: 'a + Future<Output = Result<T>>,
{
let resp = res.as_bytes().to_vec();
let line = format!("A0001{prefix}{cmd} {seq} {query}\r\n");
let session = Arc::new(Mutex::new(mock_session!(MockStream::new(resp))));
{
let _ = op(session.clone(), seq, query).await.unwrap();
}
assert!(
session.lock().await.stream.inner.written_buf == line.as_bytes().to_vec(),
"Invalid command"
);
}

Also, this commit will make fail the test due to line 2154 generate expected command without quotes and line 2160 asserts that.

async-imap/src/client.rs

Lines 2012 to 2026 in 15f80ea

async fn generic_copy<'a, F, T, K>(prefix: &'a str, op: F)
where
F: 'a + FnOnce(Arc<Mutex<Session<MockStream>>>, &'a str, &'a str) -> K,
K: 'a + Future<Output = Result<T>>,
{
generic_with_uid(
"A0001 OK COPY completed\r\n",
"COPY",
"2:4",
"MEETING",
prefix,
op,
)
.await;
}

Just adding quote to line 2021 is not fit in because Line 2154 and Line 2158 shares the query.
I think the best solution for this is not to construct the expected command in Line 2154 but construct command by each place(like line 2021) and pass into generic_with_uid function.
Is this looks good or can you suggest other option?

@dayo05
Copy link
Contributor Author

dayo05 commented Feb 3, 2026

I rewrite generic_copy function as same as how mv operation does, now test passes

@link2xt link2xt merged commit a3d3055 into chatmail:main Feb 6, 2026
11 checks passed
@link2xt
Copy link
Contributor

link2xt commented Feb 6, 2026

Thanks! I merged it as is. As for add_quote_and_validate_str, feel free to make a separate PR.

I will tag a release somewhere in a few days.

@dayo05
Copy link
Contributor Author

dayo05 commented Feb 12, 2026

While I was taking vacation for few days, I made lots of thinking for validate_str function.
But, I cannot find suitable new name for that function, that function is short but does lots of internal stuff including adding quotes and doing some validation stuff. If I add all into its name then the name of function gonna be too long imo, also its private function so I think its good enough to keep existing name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants