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
|
||||
/// finish the command.
|
||||
pub fn finish(&mut self) -> Result<()> {
|
||||
pub fn finish(&mut self) -> Result<Appended> {
|
||||
let flagstr = self
|
||||
.flags
|
||||
.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(b"\r\n")?;
|
||||
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(
|
||||
lines: Vec<u8>,
|
||||
unsolicited: &mut mpsc::Sender<UnsolicitedResponse>,
|
||||
|
|
@ -698,4 +732,48 @@ mod tests {
|
|||
assert_eq!(del.next(), Some(12));
|
||||
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;
|
||||
pub use self::unsolicited_response::{AttributeValue, UnsolicitedResponse};
|
||||
|
||||
mod appended;
|
||||
pub use self::appended::Appended;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue