Add support for APPENDUID response data
If the `UIDPLUS` extension is supported, the server will reply to `APPEND` commands with the UID of the new message. This can even be a list of UIDs if the `MULTIAPPEND` extension is also supported. Make this information available to the user as the result of an `AppendCmd`. The added doc strings have links to the relevant RFCs. Related to #131.
This commit is contained in:
parent
f616ea992e
commit
75e5d7cf79
4 changed files with 81 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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
34
src/parse.rs
34
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>,
|
||||||
|
|
|
||||||
40
src/types/appended.rs
Normal file
40
src/types/appended.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
use imap_proto::UidSetMember;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Appended {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"uid_validity: {:?}, uids: {:?}",
|
||||||
|
self.uid_validity, self.uids,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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