Skip to content

Handle unsolicited "* OK Searched 91% of the mailbox, ETA 0:01" message #179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,17 @@ fn handle_unilateral<'a>(
Response::Expunge(n) => {
unsolicited.send(UnsolicitedResponse::Expunge(n)).unwrap();
}
Response::Data {
status,
code,
information,
} if imap_proto::Status::Ok == status && code.is_none() => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary for the code to None of this to be considered informational? From what I can tell, it's enough for the response to be untagged for it to be considered unsolicited — or am I missing something?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case we should include the code in the unsolicited response type.

unsolicited
.send(UnsolicitedResponse::Uncategorised(
information.unwrap_or("").to_string(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I'm surprised that the information is an Option. Judging from the spec it doesn't seem like it can be left out? @djc

))
.unwrap();
}
res => {
return Some(res);
}
Expand Down Expand Up @@ -439,6 +450,20 @@ mod tests {
assert_eq!(fetches[0].uid, Some(74));
}

#[test]
fn parse_uncategorised_ok() {
let lines = b"\
* OK Searched 91% of the mailbox, ETA 0:01\r\n";
let (mut send, recv) = mpsc::channel();
parse_fetches(lines.to_vec(), &mut send).unwrap();
assert_eq!(
recv.try_recv(),
Ok(UnsolicitedResponse::Uncategorised(
"Searched 91% of the mailbox, ETA 0:01".to_string()
))
);
}

#[test]
fn parse_names_w_unilateral() {
let lines = b"\
Expand Down
4 changes: 4 additions & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ pub enum UnsolicitedResponse {
/// sequence numbers 9, 8, 7, 6, and 5.
// TODO: the spec doesn't seem to say anything about when these may be received as unsolicited?
Expunge(Seq),
/// An uncategorised response - one which has no code associated with it, just a text
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to be a little more helpful here to potentially-confused receivers of this code. How about:

/// An unsolicited [`OK` response](https://tools.ietf.org/html/rfc3501#section-7.1.1) that
/// indicates an information-only message; the nature of the information MAY be
/// indicated by a response code.
///
/// The untagged OK is also used as one of three possible greetings
/// at connection startup.  It indicates that the connection is not
/// yet authenticated and that a `LOGIN` command is needed.
Notice(String)

/// Dovecot is known to send a status message with an ETA for a long running fetch which
/// has no [] enclosed code.
Uncategorised(String),
}

/// This type wraps an input stream and a type that was constructed by parsing that input stream,
Expand Down