CONDSTORE #71
2 changed files with 71 additions and 20 deletions
|
@ -34,9 +34,9 @@ fn rfc3501_imap4rev1_base() {
|
|||
.context("copy message to the archive mailbox")?;
|
||||
append_email(imap_socket, Email::Basic).context("insert email in INBOX")?;
|
||||
noop_exists(imap_socket, 2).context("noop loop must detect a new email")?;
|
||||
// SEARCH IS NOT TESTED YET
|
||||
//search(imap_socket).expect("search should return something");
|
||||
add_flags_email(imap_socket, Selection::FirstId, Flag::Deleted)
|
||||
// Missing STORE command
|
||||
search(imap_socket).expect("search should return something");
|
||||
store(imap_socket, Selection::FirstId, Flag::Deleted, StoreAction::AddFlags, StoreMod::None)
|
||||
.context("should add delete flag to the email")?;
|
||||
expunge(imap_socket).context("expunge emails")?;
|
||||
rename_mailbox(imap_socket, Mailbox::Archive, Mailbox::Drafts)
|
||||
|
@ -59,7 +59,7 @@ fn rfc3691_imapext_unselect() {
|
|||
login(imap_socket, Account::Alice).context("login test")?;
|
||||
select(imap_socket, Mailbox::Inbox, SelectMod::None, None).context("select inbox")?;
|
||||
noop_exists(imap_socket, 1).context("noop loop must detect a new email")?;
|
||||
add_flags_email(imap_socket, Selection::FirstId, Flag::Deleted)
|
||||
store(imap_socket, Selection::FirstId, Flag::Deleted, StoreAction::AddFlags, StoreMod::None)
|
||||
.context("add delete flags to the email")?;
|
||||
unselect(imap_socket)
|
||||
.context("unselect inbox while preserving email with the \\Delete flag")?;
|
||||
|
@ -133,16 +133,24 @@ fn rfc7888_imapext_literal() {
|
|||
fn rfc4551_imapext_condstore() {
|
||||
println!("🧪 rfc4551_imapext_condstore");
|
||||
common::aerogramme_provider_daemon_dev(|imap_socket, lmtp_socket| {
|
||||
lmtp_handshake(lmtp_socket).context("handshake lmtp done")?;
|
||||
lmtp_deliver_email(lmtp_socket, Email::Basic).context("mail delivered successfully")?;
|
||||
lmtp_deliver_email(lmtp_socket, Email::Multipart).context("mail delivered successfully")?;
|
||||
|
||||
// Setup the test
|
||||
connect(imap_socket).context("server says hello")?;
|
||||
capability(imap_socket, Extension::Condstore).context("check server capabilities")?;
|
||||
login(imap_socket, Account::Alice).context("login test")?;
|
||||
|
||||
// Check that the condstore modifier works
|
||||
select(imap_socket, Mailbox::Inbox, SelectMod::Condstore, None).context("select inbox")?;
|
||||
|
||||
|
||||
lmtp_handshake(lmtp_socket).context("handshake lmtp done")?;
|
||||
lmtp_deliver_email(lmtp_socket, Email::Basic).context("mail delivered successfully")?;
|
||||
lmtp_deliver_email(lmtp_socket, Email::Multipart).context("mail delivered successfully")?;
|
||||
noop_exists(imap_socket, 2).context("noop loop must detect a new email")?;
|
||||
|
||||
|
||||
|
||||
//store(
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.expect("test fully run");
|
||||
|
|
|
@ -63,6 +63,7 @@ pub enum Email {
|
|||
pub enum Selection {
|
||||
FirstId,
|
||||
SecondId,
|
||||
All,
|
||||
}
|
||||
|
||||
pub enum SelectMod {
|
||||
|
@ -70,6 +71,20 @@ pub enum SelectMod {
|
|||
Condstore,
|
||||
}
|
||||
|
||||
pub enum StoreAction {
|
||||
AddFlags,
|
||||
DelFlags,
|
||||
SetFlags,
|
||||
AddFlagsSilent,
|
||||
DelFlagsSilent,
|
||||
SetFlagsSilent,
|
||||
}
|
||||
|
||||
pub enum StoreMod {
|
||||
None,
|
||||
UnchangedSince(u64),
|
||||
}
|
||||
|
||||
pub fn capability(imap: &mut TcpStream, ext: Extension) -> Result<()> {
|
||||
imap.write(&b"5 capability\r\n"[..])?;
|
||||
|
||||
|
@ -308,18 +323,6 @@ pub fn append_email(imap: &mut TcpStream, content: Email) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_flags_email(imap: &mut TcpStream, selection: Selection, flag: Flag) -> Result<()> {
|
||||
let mut buffer: [u8; 1500] = [0; 1500];
|
||||
assert!(matches!(selection, Selection::FirstId));
|
||||
assert!(matches!(flag, Flag::Deleted));
|
||||
imap.write(&b"50 store 1 +FLAGS (\\Deleted)\r\n"[..])?;
|
||||
let _read = read_lines(imap, &mut buffer, Some(&b"50 OK"[..]))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Not yet implemented
|
||||
pub fn search(imap: &mut TcpStream) -> Result<()> {
|
||||
imap.write(&b"55 search text \"OoOoO\"\r\n"[..])?;
|
||||
let mut buffer: [u8; 1500] = [0; 1500];
|
||||
|
@ -327,6 +330,46 @@ pub fn search(imap: &mut TcpStream) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn store(
|
||||
imap: &mut TcpStream,
|
||||
sel: Selection,
|
||||
flag: Flag,
|
||||
action: StoreAction,
|
||||
modifier: StoreMod
|
||||
) -> Result<String> {
|
||||
let mut buffer: [u8; 6000] = [0; 6000];
|
||||
|
||||
let seq = match sel {
|
||||
Selection::FirstId => "1",
|
||||
Selection::SecondId => "2",
|
||||
Selection::All => "1:*",
|
||||
};
|
||||
|
||||
let modif = match modifier {
|
||||
StoreMod::None => "".into(),
|
||||
StoreMod::UnchangedSince(val) => format!(" (UNCHANGEDSINCE {})", val),
|
||||
};
|
||||
|
||||
let flags_str = match flag {
|
||||
Flag::Deleted => "(\\Deleted)",
|
||||
Flag::Important => "(\\Important)",
|
||||
};
|
||||
|
||||
let action_str = match action {
|
||||
StoreAction::AddFlags => "+FLAGS",
|
||||
StoreAction::DelFlags => "-FLAGS",
|
||||
StoreAction::SetFlags => "FLAGS",
|
||||
StoreAction::AddFlagsSilent => "+FLAGS.SILENT",
|
||||
StoreAction::DelFlagsSilent => "-FLAGS.SILENT",
|
||||
StoreAction::SetFlagsSilent => "FLAGS.SILENT",
|
||||
};
|
||||
|
||||
imap.write(format!("57 STORE {}{} {} {}\r\n", seq, modif, action_str, flags_str).as_bytes())?;
|
||||
let read = read_lines(imap, &mut buffer, Some(&b"57 OK"[..]))?;
|
||||
let srv_msg = std::str::from_utf8(read)?;
|
||||
Ok(srv_msg.to_string())
|
||||
}
|
||||
|
||||
pub fn expunge(imap: &mut TcpStream) -> Result<()> {
|
||||
imap.write(&b"60 expunge\r\n"[..])?;
|
||||
let mut buffer: [u8; 1500] = [0; 1500];
|
||||
|
|
Loading…
Reference in a new issue