Add append_with_flags (#171)
Allows a client to set flags on a new message as it is appended to a mailbox.
This commit is contained in:
parent
6c43b19f60
commit
ae07c9f31c
3 changed files with 142 additions and 1 deletions
|
|
@ -1078,10 +1078,37 @@ impl<T: Read + Write> Session<T> {
|
||||||
/// `EXISTS` response. If the server does not do so, the client MAY issue a `NOOP` command (or
|
/// `EXISTS` response. If the server does not do so, the client MAY issue a `NOOP` command (or
|
||||||
/// failing that, a `CHECK` command) after one or more `APPEND` commands.
|
/// failing that, a `CHECK` command) after one or more `APPEND` commands.
|
||||||
pub fn append<S: AsRef<str>, B: AsRef<[u8]>>(&mut self, mailbox: S, content: B) -> Result<()> {
|
pub fn append<S: AsRef<str>, B: AsRef<[u8]>>(&mut self, mailbox: S, content: B) -> Result<()> {
|
||||||
|
self.append_with_flags(mailbox, content, &[])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [`APPEND` command](https://tools.ietf.org/html/rfc3501#section-6.3.11) can take
|
||||||
|
/// an optional FLAGS parameter to set the flags on the new message.
|
||||||
|
///
|
||||||
|
/// > If a flag parenthesized list is specified, the flags SHOULD be set
|
||||||
|
/// > in the resulting message; otherwise, the flag list of the
|
||||||
|
/// > resulting message is set to empty by default. In either case, the
|
||||||
|
/// > Recent flag is also set.
|
||||||
|
///
|
||||||
|
/// The [`\Recent` flag](https://tools.ietf.org/html/rfc3501#section-2.3.2) is not
|
||||||
|
/// allowed as an argument to `APPEND` and will be filtered out if present in `flags`.
|
||||||
|
pub fn append_with_flags<S: AsRef<str>, B: AsRef<[u8]>>(
|
||||||
|
&mut self,
|
||||||
|
mailbox: S,
|
||||||
|
content: B,
|
||||||
|
flags: &[Flag<'_>],
|
||||||
|
) -> Result<()> {
|
||||||
let content = content.as_ref();
|
let content = content.as_ref();
|
||||||
|
let flagstr = flags
|
||||||
|
.iter()
|
||||||
|
.filter(|f| **f != Flag::Recent)
|
||||||
|
.map(|f| f.to_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
self.run_command(&format!(
|
self.run_command(&format!(
|
||||||
"APPEND \"{}\" {{{}}}",
|
"APPEND \"{}\" ({}) {{{}}}",
|
||||||
mailbox.as_ref(),
|
mailbox.as_ref(),
|
||||||
|
flagstr,
|
||||||
content.len()
|
content.len()
|
||||||
))?;
|
))?;
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,21 @@ impl Flag<'static> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Display for Flag<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Flag::Seen => write!(f, "{}", "\\Seen"),
|
||||||
|
Flag::Answered => write!(f, "{}", "\\Answered"),
|
||||||
|
Flag::Flagged => write!(f, "{}", "\\Flagged"),
|
||||||
|
Flag::Deleted => write!(f, "{}", "\\Deleted"),
|
||||||
|
Flag::Draft => write!(f, "{}", "\\Draft"),
|
||||||
|
Flag::Recent => write!(f, "{}", "\\Recent"),
|
||||||
|
Flag::MayCreate => write!(f, "{}", "\\*"),
|
||||||
|
Flag::Custom(ref s) => write!(f, "{}", s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<String> for Flag<'a> {
|
impl<'a> From<String> for Flag<'a> {
|
||||||
fn from(s: String) -> Self {
|
fn from(s: String) -> Self {
|
||||||
if let Some(f) = Flag::system(&s) {
|
if let Some(f) = Flag::system(&s) {
|
||||||
|
|
|
||||||
|
|
@ -231,3 +231,102 @@ fn list() {
|
||||||
|
|
||||||
// TODO: make a subdir
|
// TODO: make a subdir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn append() {
|
||||||
|
let to = "inbox-append1@localhost";
|
||||||
|
|
||||||
|
// make a message to append
|
||||||
|
let e: lettre::SendableEmail = lettre_email::Email::builder()
|
||||||
|
.from("sender@localhost")
|
||||||
|
.to(to)
|
||||||
|
.subject("My second e-mail")
|
||||||
|
.text("Hello world")
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
// connect
|
||||||
|
let mut c = session(to);
|
||||||
|
let mbox = "INBOX";
|
||||||
|
c.select(mbox).unwrap();
|
||||||
|
//append
|
||||||
|
c.append(mbox, e.message_to_string().unwrap()).unwrap();
|
||||||
|
|
||||||
|
// now we should see the e-mail!
|
||||||
|
let inbox = c.uid_search("ALL").unwrap();
|
||||||
|
// and the one message should have the first message sequence number
|
||||||
|
assert_eq!(inbox.len(), 1);
|
||||||
|
let uid = inbox.into_iter().next().unwrap();
|
||||||
|
|
||||||
|
// fetch the e-mail
|
||||||
|
let fetch = c.uid_fetch(format!("{}", uid), "(ALL UID)").unwrap();
|
||||||
|
assert_eq!(fetch.len(), 1);
|
||||||
|
let fetch = &fetch[0];
|
||||||
|
assert_eq!(fetch.uid, Some(uid));
|
||||||
|
let e = fetch.envelope().unwrap();
|
||||||
|
assert_eq!(e.subject, Some(&b"My second e-mail"[..]));
|
||||||
|
|
||||||
|
// and let's delete it to clean up
|
||||||
|
c.uid_store(format!("{}", uid), "+FLAGS (\\Deleted)")
|
||||||
|
.unwrap();
|
||||||
|
c.expunge().unwrap();
|
||||||
|
|
||||||
|
// the e-mail should be gone now
|
||||||
|
let inbox = c.search("ALL").unwrap();
|
||||||
|
assert_eq!(inbox.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn append_with_flags() {
|
||||||
|
use imap::types::Flag;
|
||||||
|
|
||||||
|
let to = "inbox-append2@localhost";
|
||||||
|
|
||||||
|
// make a message to append
|
||||||
|
let e: lettre::SendableEmail = lettre_email::Email::builder()
|
||||||
|
.from("sender@localhost")
|
||||||
|
.to(to)
|
||||||
|
.subject("My third e-mail")
|
||||||
|
.text("Hello world")
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
// connect
|
||||||
|
let mut c = session(to);
|
||||||
|
let mbox = "INBOX";
|
||||||
|
c.select(mbox).unwrap();
|
||||||
|
//append
|
||||||
|
let flags: &[Flag] = &[Flag::Seen, Flag::Flagged];
|
||||||
|
c.append_with_flags(mbox, e.message_to_string().unwrap(), flags)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// now we should see the e-mail!
|
||||||
|
let inbox = c.uid_search("ALL").unwrap();
|
||||||
|
// and the one message should have the first message sequence number
|
||||||
|
assert_eq!(inbox.len(), 1);
|
||||||
|
let uid = inbox.into_iter().next().unwrap();
|
||||||
|
|
||||||
|
// fetch the e-mail
|
||||||
|
let fetch = c.uid_fetch(format!("{}", uid), "(ALL UID)").unwrap();
|
||||||
|
assert_eq!(fetch.len(), 1);
|
||||||
|
let fetch = &fetch[0];
|
||||||
|
assert_eq!(fetch.uid, Some(uid));
|
||||||
|
let e = fetch.envelope().unwrap();
|
||||||
|
assert_eq!(e.subject, Some(&b"My third e-mail"[..]));
|
||||||
|
|
||||||
|
// check the flags
|
||||||
|
let setflags = fetch.flags();
|
||||||
|
assert!(setflags.contains(&Flag::Seen));
|
||||||
|
assert!(setflags.contains(&Flag::Flagged));
|
||||||
|
|
||||||
|
// and let's delete it to clean up
|
||||||
|
c.uid_store(format!("{}", uid), "+FLAGS (\\Deleted)")
|
||||||
|
.unwrap();
|
||||||
|
c.expunge().unwrap();
|
||||||
|
|
||||||
|
// the e-mail should be gone now
|
||||||
|
let inbox = c.search("ALL").unwrap();
|
||||||
|
assert_eq!(inbox.len(), 0);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue