Merge pull request #232 from bitfehler/bitfehler/append-uid
Add support for APPENDUID response data
This commit is contained in:
commit
8c2250297a
4 changed files with 114 additions and 2 deletions
|
|
@ -215,7 +215,7 @@ impl<'a, T: Read + Write> AppendCmd<'a, T> {
|
||||||
///
|
///
|
||||||
/// Note: be sure to set flags and optional date before you
|
/// Note: be sure to set flags and optional date before you
|
||||||
/// finish the command.
|
/// finish the command.
|
||||||
pub fn finish(&mut self) -> Result<()> {
|
pub fn finish(&mut self) -> Result<Appended> {
|
||||||
let flagstr = self
|
let flagstr = self
|
||||||
.flags
|
.flags
|
||||||
.clone()
|
.clone()
|
||||||
|
|
@ -246,7 +246,9 @@ impl<'a, T: Read + Write> AppendCmd<'a, T> {
|
||||||
self.session.stream.write_all(self.content)?;
|
self.session.stream.write_all(self.content)?;
|
||||||
self.session.stream.write_all(b"\r\n")?;
|
self.session.stream.write_all(b"\r\n")?;
|
||||||
self.session.stream.flush()?;
|
self.session.stream.flush()?;
|
||||||
self.session.read_response().map(|_| ())
|
self.session
|
||||||
|
.read_response()
|
||||||
|
.and_then(|(lines, _)| parse_append(&lines, &mut self.session.unsolicited_responses_tx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
78
src/parse.rs
78
src/parse.rs
|
|
@ -124,6 +124,40 @@ pub fn parse_expunge(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_append(
|
||||||
|
mut lines: &[u8],
|
||||||
|
unsolicited: &mut mpsc::Sender<UnsolicitedResponse>,
|
||||||
|
) -> Result<Appended> {
|
||||||
|
let mut appended = Appended::default();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match imap_proto::parser::parse_response(lines) {
|
||||||
|
Ok((rest, Response::Done { status, code, .. })) => {
|
||||||
|
lines = rest;
|
||||||
|
assert_eq!(status, imap_proto::Status::Ok);
|
||||||
|
|
||||||
|
if let Some(ResponseCode::AppendUid(validity, uids)) = code {
|
||||||
|
appended.uid_validity = Some(validity);
|
||||||
|
appended.uids = Some(uids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((rest, data)) => {
|
||||||
|
lines = rest;
|
||||||
|
if let Some(resp) = try_handle_unilateral(data, unsolicited) {
|
||||||
|
break Err(resp.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::Parse(ParseError::Invalid(lines.to_vec())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if lines.is_empty() {
|
||||||
|
break Ok(appended);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_noop(
|
pub fn parse_noop(
|
||||||
lines: Vec<u8>,
|
lines: Vec<u8>,
|
||||||
unsolicited: &mut mpsc::Sender<UnsolicitedResponse>,
|
unsolicited: &mut mpsc::Sender<UnsolicitedResponse>,
|
||||||
|
|
@ -698,4 +732,48 @@ mod tests {
|
||||||
assert_eq!(del.next(), Some(12));
|
assert_eq!(del.next(), Some(12));
|
||||||
assert_eq!(del.next(), None);
|
assert_eq!(del.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_append_uid() {
|
||||||
|
// If the user has enabled UIDPLUS (RFC 4315), the response contains an APPENDUID
|
||||||
|
// response code followed by the UIDVALIDITY of the destination mailbox and the
|
||||||
|
// UID assigned to the appended message in the destination mailbox.
|
||||||
|
// If the MULTIAPPEND extension is also used, there can be multiple UIDs.
|
||||||
|
let lines = b"A003 OK [APPENDUID 38505 3955] APPEND completed\r\n";
|
||||||
|
let (mut send, recv) = mpsc::channel();
|
||||||
|
let resp = parse_append(lines, &mut send).unwrap();
|
||||||
|
|
||||||
|
assert!(recv.try_recv().is_err());
|
||||||
|
assert_eq!(resp.uid_validity, Some(38505));
|
||||||
|
match resp.uids {
|
||||||
|
Some(uid_list) => {
|
||||||
|
let mut it = uid_list.iter();
|
||||||
|
assert_eq!(it.next(), Some(&UidSetMember::Uid(3955)));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
}
|
||||||
|
None => panic!("Missing UIDs in APPEND response"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_multiappend_uid() {
|
||||||
|
// If the user has enabled UIDPLUS (RFC 4315), the response contains an APPENDUID
|
||||||
|
// response code followed by the UIDVALIDITY of the destination mailbox and the
|
||||||
|
// UID assigned to the appended message in the destination mailbox.
|
||||||
|
// If the MULTIAPPEND extension is also used, there can be multiple UIDs.
|
||||||
|
let lines = b"A003 OK [APPENDUID 38505 3955:3957] APPEND completed\r\n";
|
||||||
|
let (mut send, recv) = mpsc::channel();
|
||||||
|
let resp = parse_append(lines, &mut send).unwrap();
|
||||||
|
|
||||||
|
assert!(recv.try_recv().is_err());
|
||||||
|
assert_eq!(resp.uid_validity, Some(38505));
|
||||||
|
match resp.uids {
|
||||||
|
Some(uid_list) => {
|
||||||
|
let mut it = uid_list.iter();
|
||||||
|
assert_eq!(it.next(), Some(&UidSetMember::UidRange(3955..=3957)));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
}
|
||||||
|
None => panic!("Missing UIDs in APPEND response"),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
src/types/appended.rs
Normal file
29
src/types/appended.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use imap_proto::UidSetMember;
|
||||||
|
|
||||||
|
/// Meta-information about a message, as returned by
|
||||||
|
/// [`APPEND`](https://tools.ietf.org/html/rfc3501#section-6.3.11).
|
||||||
|
/// Note that `APPEND` only returns any data if certain extensions are enabled,
|
||||||
|
/// for example [`UIDPLUS`](https://tools.ietf.org/html/rfc4315).
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct Appended {
|
||||||
|
/// The unique identifier validity value of the mailbox that the message was appended to.
|
||||||
|
/// See [`Uid`] for more details. Only present if server supports [`UIDPLUS`](https://tools.ietf.org/html/rfc4315).
|
||||||
|
pub uid_validity: Option<u32>,
|
||||||
|
|
||||||
|
/// The unique identifier value of the messages that were appended.
|
||||||
|
/// Only present if server supports [`UIDPLUS`](https://tools.ietf.org/html/rfc4315).
|
||||||
|
/// Contains only a single value unless the [`MULTIAPPEND`](https://tools.ietf.org/html/rfc3502) extension
|
||||||
|
/// was used to upload multiple messages.
|
||||||
|
pub uids: Option<Vec<UidSetMember>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derivable_impls)]
|
||||||
|
impl Default for Appended {
|
||||||
|
fn default() -> Appended {
|
||||||
|
Appended {
|
||||||
|
uid_validity: None,
|
||||||
|
uids: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -123,3 +123,6 @@ pub use self::deleted::Deleted;
|
||||||
|
|
||||||
mod unsolicited_response;
|
mod unsolicited_response;
|
||||||
pub use self::unsolicited_response::{AttributeValue, UnsolicitedResponse};
|
pub use self::unsolicited_response::{AttributeValue, UnsolicitedResponse};
|
||||||
|
|
||||||
|
mod appended;
|
||||||
|
pub use self::appended::Appended;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue