Skip to content

Commit 27e26f7

Browse files
authored
Add RFC 5464 response codes (#116)
1 parent 15e599a commit 27e26f7

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

imap-proto/src/parser/rfc3501/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ fn resp_text_code(i: &[u8]) -> IResult<&[u8], ResponseCode> {
176176
rfc4315::resp_text_code_append_uid,
177177
rfc4315::resp_text_code_copy_uid,
178178
rfc4315::resp_text_code_uid_not_sticky,
179+
rfc5464::resp_text_code_metadata_long_entries,
180+
rfc5464::resp_text_code_metadata_max_size,
181+
rfc5464::resp_text_code_metadata_too_many,
182+
rfc5464::resp_text_code_metadata_no_private,
179183
)),
180184
tag(b"]"),
181185
)(i)

imap-proto/src/parser/rfc5464.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,42 @@ pub(crate) fn metadata_unsolicited(i: &[u8]) -> IResult<&[u8], Response> {
179179
))
180180
}
181181

182+
// There are any entries with values larger than the MAXSIZE limit given to GETMETADATA.
183+
// Extends resp-test-code defined in rfc3501.
184+
// [RFC5464 - 4.2.1 MAXSIZE GETMETADATA Command Option](https://tools.ietf.org/html/rfc5464#section-4.2.1)
185+
// [RFC5464 - 5. Formal Syntax - resp-text-code](https://tools.ietf.org/html/rfc5464#section-5)
186+
pub(crate) fn resp_text_code_metadata_long_entries(i: &[u8]) -> IResult<&[u8], ResponseCode> {
187+
let (i, (_, num)) = tuple((tag_no_case("METADATA LONGENTRIES "), number_64))(i)?;
188+
Ok((i, ResponseCode::MetadataLongEntries(num)))
189+
}
190+
191+
// Server is unable to set an annotation because the size of its value is too large.
192+
// Extends resp-test-code defined in rfc3501.
193+
// [RFC5464 - 4.3 SETMETADATA Command](https://tools.ietf.org/html/rfc5464#section-4.3)
194+
// [RFC5464 - 5. Formal Syntax - resp-text-code](https://tools.ietf.org/html/rfc5464#section-5)
195+
pub(crate) fn resp_text_code_metadata_max_size(i: &[u8]) -> IResult<&[u8], ResponseCode> {
196+
let (i, (_, num)) = tuple((tag_no_case("METADATA MAXSIZE "), number_64))(i)?;
197+
Ok((i, ResponseCode::MetadataMaxSize(num)))
198+
}
199+
200+
// Server is unable to set a new annotation because the maximum number of allowed annotations has already been reached.
201+
// Extends resp-test-code defined in rfc3501.
202+
// [RFC5464 - 4.3 SETMETADATA Command](https://tools.ietf.org/html/rfc5464#section-4.3)
203+
// [RFC5464 - 5. Formal Syntax - resp-text-code](https://tools.ietf.org/html/rfc5464#section-5)
204+
pub(crate) fn resp_text_code_metadata_too_many(i: &[u8]) -> IResult<&[u8], ResponseCode> {
205+
let (i, _) = tag_no_case("METADATA TOOMANY")(i)?;
206+
Ok((i, ResponseCode::MetadataTooMany))
207+
}
208+
209+
// Server is unable to set a new annotation because it does not support private annotations on one of the specified mailboxes.
210+
// Extends resp-test-code defined in rfc3501.
211+
// [RFC5464 - 4.3 SETMETADATA Command](https://tools.ietf.org/html/rfc5464#section-4.3)
212+
// [RFC5464 - 5. Formal Syntax - resp-text-code](https://tools.ietf.org/html/rfc5464#section-5)
213+
pub(crate) fn resp_text_code_metadata_no_private(i: &[u8]) -> IResult<&[u8], ResponseCode> {
214+
let (i, _) = tag_no_case("METADATA NOPRIVATE")(i)?;
215+
Ok((i, ResponseCode::MetadataNoPrivate))
216+
}
217+
182218
#[cfg(test)]
183219
mod tests {
184220
use super::{metadata_solicited, metadata_unsolicited};
@@ -292,4 +328,57 @@ mod tests {
292328
_ => panic!("Correct METADATA response is not parsed properly."),
293329
}
294330
}
331+
332+
#[test]
333+
fn test_response_codes() {
334+
use crate::parser::parse_response;
335+
336+
match parse_response(b"* OK [METADATA LONGENTRIES 123] Some entries omitted.\r\n") {
337+
Ok((
338+
_,
339+
Response::Data {
340+
status: Status::Ok,
341+
code: Some(ResponseCode::MetadataLongEntries(123)),
342+
information: Some("Some entries omitted."),
343+
},
344+
)) => {}
345+
rsp => panic!("unexpected response {:?}", rsp),
346+
}
347+
348+
match parse_response(b"* NO [METADATA MAXSIZE 123] Annotation too large.\r\n") {
349+
Ok((
350+
_,
351+
Response::Data {
352+
status: Status::No,
353+
code: Some(ResponseCode::MetadataMaxSize(123)),
354+
information: Some("Annotation too large."),
355+
},
356+
)) => {}
357+
rsp => panic!("unexpected response {:?}", rsp),
358+
}
359+
360+
match parse_response(b"* NO [METADATA TOOMANY] Too many annotations.\r\n") {
361+
Ok((
362+
_,
363+
Response::Data {
364+
status: Status::No,
365+
code: Some(ResponseCode::MetadataTooMany),
366+
information: Some("Too many annotations."),
367+
},
368+
)) => {}
369+
rsp => panic!("unexpected response {:?}", rsp),
370+
}
371+
372+
match parse_response(b"* NO [METADATA NOPRIVATE] Private annotations not supported.\r\n") {
373+
Ok((
374+
_,
375+
Response::Data {
376+
status: Status::No,
377+
code: Some(ResponseCode::MetadataNoPrivate),
378+
information: Some("Private annotations not supported."),
379+
},
380+
)) => {}
381+
rsp => panic!("unexpected response {:?}", rsp),
382+
}
383+
}
295384
}

imap-proto/src/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ pub enum ResponseCode<'a> {
7171
AppendUid(u32, Vec<UidSetMember>),
7272
CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
7373
UidNotSticky,
74+
MetadataLongEntries(u64), // RFC 5464, section 4.2.1
75+
MetadataMaxSize(u64), // RFC 5464, section 4.3
76+
MetadataTooMany, // RFC 5464, section 4.3
77+
MetadataNoPrivate, // RFC 5464, section 4.3
7478
}
7579
#[derive(Clone, Debug, Eq, PartialEq)]
7680
pub enum UidSetMember {

0 commit comments

Comments
 (0)