Crate imap_codec
source ·Expand description
IMAP protocol library
imap-codec provides complete and detailed parsing and construction of IMAP4rev1 commands and responses. It is based on imap-types and extends it with parsing support using nom.
Example
use imap_codec::{
codec::{Decode, Encode},
command::Command,
};
// We assume here that the message is already complete.
let input = b"ABCD UID FETCH 1,2:* (BODY.PEEK[1.2.3.4.MIME]<42.1337>)\r\n";
let (_remainder, parsed) = Command::decode(input).unwrap();
println!("// Parsed:");
println!("{parsed:#?}");
let serialized = parsed.encode().dump();
// Not every IMAP message is valid UTF-8.
// We ignore that here, so that we can print the message.
let serialized = String::from_utf8(serialized).unwrap();
println!("// Serialized:");
println!("// {serialized}");
Decoding
Parsing is implemented through the Decode
trait.
The main entry points for parsing are
Greeting::decode(...)
(to parse the first message from a server),
Command::decode(...)
(to parse commands from a client), and
Response::decode(...)
(to parse responses or results from a server).
Note, however, that certain message flows require other parsers as well.
Every parser takes an input (&[u8]
) and produces a remainder and a parsed value.
Example
Have a look at the parse_command example to see how a real-world application could decode IMAP.
IMAP literals make separating the parsing logic from the application logic difficult.
When a server recognizes a literal (e.g. “{42}”), it first needs to agree to receive more data by sending a so-called “continuation request” (+ ...
).
Without a continuation request, a client won’t send more data, and the parser on the server would always return Incomplete(42)
.
This makes real-world decoding of IMAP a bit more elaborate.
Encoding
The Encode::encode(...)
method will return an instance of Encoded
that facilitates handling of literals. The idea is that the encoder not only “dumps” the final serialization of a message but can be iterated over.
Example
#[cfg(feature = "ext_literal")]
use imap_codec::core::LiteralMode;
use imap_codec::{
codec::{Decode, Encode, Fragment},
command::{Command, CommandBody},
};
let command = Command::new("A1", CommandBody::login("Alice", "Pa²²W0rD").unwrap()).unwrap();
for fragment in command.encode() {
match fragment {
Fragment::Line { data } => {
// A line that is ready to be send.
println!("C: {}", String::from_utf8(data).unwrap());
}
#[cfg(not(feature = "ext_literal"))]
Fragment::Literal { data } => {
// Wait for a continuation request.
println!("S: + ...")
}
#[cfg(feature = "ext_literal")]
Fragment::Literal { data, mode } => match mode {
LiteralMode::Sync => {
// Wait for a continuation request.
println!("S: + ...")
}
LiteralMode::NonSync => {
// We don't need to wait for a continuation request
// as the server will also not send it.
}
},
}
}
Output of example:
C: A1 LOGIN alice {10}
S: + ...
C: Pa²²W0rD
Features
imap-codec forwards many features to imap-types. See imap-types features for a comprehensive list.
In addition, imap-codec defines the following features:
Feature | Description | Enabled by default |
---|---|---|
quirk_crlf_relaxed | Make \r in \r\n optional. | No |
quirk_rectify_numbers | Rectify (invalid) numbers. | No |
quirk_missing_text | Rectify missing text element. | No |
tokio | Tokio support. | No |
Quirks
Features starting with quirk_
are used to cope with existing interoperability issues.
Unfortunately, we already observed some standard violations, such as, negative numbers, and missing syntax elements.
Our policy is as follows: If we see an interoperability issue, we file an issue in the corresponding implementation.
If, for any reason, the issue cannot be fixed, and the implementation is “important enough”, e.g., because a user of
imap-codec can’t otherwise access their emails, we may add a quirk_
feature to quickly resolve the problem.
Of course, imap-codec should never violate the IMAP standard itself. So, we need to do this carefully.
Tokio support
The tokio
feature unlocks an implementation of tokio_util::codec.
See the tokio client and tokio server demos.
Modules
- Please refer to
imap_types::auth
. - Please refer to
imap_types::body
. - (De)serialization of messages.
- Please refer to
imap_types::command
. - Please refer to
imap_types::core
. - Please refer to
imap_types::datetime
. - Please refer to
imap_types::envelope
. - extensions
ext_*
Please refer toimap_types::extensions
. - Please refer to
imap_types::fetch
. - Please refer to
imap_types::flag
. - Please refer to
imap_types::mailbox
. - Please refer to
imap_types::response
. - Please refer to
imap_types::search
. - Handling of secret values.
- Please refer to
imap_types::section
. - Please refer to
imap_types::sequence
. - IMAP protocol state.
- Please refer to
imap_types::status
. - tokio
tokio
Support for tokio and (tokio_util::codec). - Functions that may come in handy.