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:

FeatureDescriptionEnabled by default
quirk_crlf_relaxedMake \r in \r\n optional.No
quirk_rectify_numbersRectify (invalid) numbers.No
quirk_missing_textRectify missing text element.No
tokioTokio 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