parent
4c4fd89232
commit
72925cf1d8
2 changed files with 51 additions and 3 deletions
|
|
@ -298,6 +298,12 @@ impl<T: Read + Write> Client<T> {
|
|||
}
|
||||
|
||||
/// Selects a mailbox
|
||||
///
|
||||
/// Note that the server *is* allowed to unilaterally send things to the client for messages in
|
||||
/// a selected mailbox whose status has changed. See the note on [unilateral server responses
|
||||
/// in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7). This means that if you use
|
||||
/// [`Client::run_command_and_read_response`], you *may* see additional untagged `RECENT`,
|
||||
/// `EXISTS`, `FETCH`, and `EXPUNGE` responses!
|
||||
pub fn select(&mut self, mailbox_name: &str) -> Result<Mailbox> {
|
||||
self.run_command_and_read_response(&format!("SELECT {}", validate_str(mailbox_name)?))
|
||||
.and_then(|lines| parse_mailbox(&lines[..]))
|
||||
|
|
@ -309,12 +315,21 @@ impl<T: Read + Write> Client<T> {
|
|||
.and_then(|lines| parse_mailbox(&lines[..]))
|
||||
}
|
||||
|
||||
/// Fetch retreives data associated with a message in the mailbox.
|
||||
/// Fetch retreives data associated with a set of messages in the mailbox.
|
||||
///
|
||||
/// Note that the server *is* allowed to unilaterally include `FETCH` responses for other
|
||||
/// messages in the selected mailbox whose status has changed. See the note on [unilateral
|
||||
/// server responses in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7).
|
||||
pub fn fetch(&mut self, sequence_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> {
|
||||
self.run_command_and_read_response(&format!("FETCH {} {}", sequence_set, query))
|
||||
.and_then(|lines| parse_fetches(lines))
|
||||
}
|
||||
|
||||
/// Fetch retreives data associated with a set of messages by UID in the mailbox.
|
||||
///
|
||||
/// Note that the server *is* allowed to unilaterally include `FETCH` responses for other
|
||||
/// messages in the selected mailbox whose status has changed. See the note on [unilateral
|
||||
/// server responses in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7).
|
||||
pub fn uid_fetch(&mut self, uid_set: &str, query: &str) -> ZeroCopyResult<Vec<Fetch>> {
|
||||
self.run_command_and_read_response(&format!("UID FETCH {} {}", uid_set, query))
|
||||
.and_then(|lines| parse_fetches(lines))
|
||||
|
|
@ -472,6 +487,12 @@ impl<T: Read + Write> Client<T> {
|
|||
self.write_line(command.into_bytes().as_slice())
|
||||
}
|
||||
|
||||
/// Run a raw IMAP command and read back its response.
|
||||
///
|
||||
/// Note that the server *is* allowed to unilaterally send things to the client for messages in
|
||||
/// a selected mailbox whose status has changed. See the note on [unilateral server responses
|
||||
/// in RFC 3501](https://tools.ietf.org/html/rfc3501#section-7). This means that you *may* see
|
||||
/// additional untagged `RECENT`, `EXISTS`, `FETCH`, and `EXPUNGE` responses!
|
||||
pub fn run_command_and_read_response(&mut self, untagged_command: &str) -> Result<Vec<u8>> {
|
||||
self.run_command(untagged_command)?;
|
||||
self.read_response()
|
||||
|
|
|
|||
31
src/parse.rs
31
src/parse.rs
|
|
@ -1,4 +1,4 @@
|
|||
use imap_proto::{self, Response};
|
||||
use imap_proto::{self, MailboxDatum, Response};
|
||||
use nom::IResult;
|
||||
use regex::Regex;
|
||||
|
||||
|
|
@ -19,6 +19,8 @@ pub fn parse_authenticate_response(line: String) -> Result<String> {
|
|||
enum MapOrNot<T> {
|
||||
Map(T),
|
||||
Not(Response<'static>),
|
||||
#[allow(dead_code)]
|
||||
Ignore,
|
||||
}
|
||||
|
||||
unsafe fn parse_many<T, F>(lines: Vec<u8>, mut map: F) -> ZeroCopyResult<Vec<T>>
|
||||
|
|
@ -38,7 +40,20 @@ where
|
|||
|
||||
match map(resp) {
|
||||
MapOrNot::Map(t) => things.push(t),
|
||||
MapOrNot::Not(resp) => break Err(resp.into()),
|
||||
MapOrNot::Not(resp) => {
|
||||
// check if this is simply a unilateral server response
|
||||
// (see Section 7 of RFC 3501):
|
||||
match resp {
|
||||
Response::MailboxData(MailboxDatum::Recent { .. })
|
||||
| Response::MailboxData(MailboxDatum::Exists { .. })
|
||||
| Response::Fetch(..)
|
||||
| Response::Expunge(..) => {
|
||||
continue;
|
||||
}
|
||||
resp => break Err(resp.into()),
|
||||
}
|
||||
}
|
||||
MapOrNot::Ignore => continue,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -264,4 +279,16 @@ mod tests {
|
|||
assert_eq!(fetches[1].uid, None);
|
||||
assert_eq!(fetches[1].rfc822(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fetches_w_unilateral() {
|
||||
// https://github.com/mattnenterprise/rust-imap/issues/81
|
||||
let lines = b"\
|
||||
* 37 FETCH (UID 74)\r\n\
|
||||
* 1 RECENT\r\n";
|
||||
let fetches = parse_fetches(lines.to_vec()).unwrap();
|
||||
assert_eq!(fetches.len(), 1);
|
||||
assert_eq!(fetches[0].message, 37);
|
||||
assert_eq!(fetches[0].uid, Some(74));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue