Crate imap_types
source ·Expand description
Misuse-resistant IMAP types
The most prominent types in imap-types are Greeting
, Command
, and Response
, and we use the term “message” to refer to either of them.
Messages can be created in different ways.
However, what all ways have in common is, that the API does not allow the creation of invalid ones.
For example, all commands in IMAP are prefixed with a “tag”.
Although IMAP’s tags are just strings, they have additional rules, such as that no whitespace is allowed.
Thus, imap-types encapsulate them in Tag
struct to ensure that invalid ones can’t be created.
Understanding and using the core types
Similar to Tag
s, there are more “core types” (or “string types”), such as, Atom
, Quoted
, or Literal
.
Besides being used for correctness, these types play a crucial role in IMAP because they determine the IMAP protocol flow.
Sending a password as a literal requires a different protocol flow than sending the password as an atom or a quoted string.
So, even though imap-types can choose the most efficient representation for a datum automatically, it’s good to become familiar with the core
module at some point to master the IMAP protocol.
Construction of messages
imap-types relies a lot on the standard conversion traits, i.e., From
, TryFrom
, Into
, and TryInto
.
Make good use of them.
More convenient constructors are available for types that are more cumbersome to create.
Note: When you are sure that the thing you want to create is valid, you can unlock various unvalidated(...)
functions through the unvalidated
feature.
This allows us to bypass certain checks in release builds.
Example
use imap_types::{
command::{Command, CommandBody},
core::Tag,
};
// # Variant 1
// Create a `Command` with `tag` "A123" and `body` "NOOP".
// (Note: `Command::new()` returns `Err(...)` when the tag is invalid.)
let cmd = Command::new("A123", CommandBody::Noop).unwrap();
// # Variant 2
// Create a `CommandBody` first and finalize it into
// a `Command` by attaching a tag later.
let cmd = CommandBody::Noop.tag("A123").unwrap();
// # Variant 3
// Create a `Command` directly.
let cmd = Command {
tag: Tag::try_from("A123").unwrap(),
body: CommandBody::Noop,
};
More complex messages
Example
The following example is a server fetch response containing the size and MIME structure of a message with the sequence number (or UID) 42.
use std::{borrow::Cow, num::NonZeroU32};
use imap_types::{
body::{BasicFields, Body, BodyStructure, SinglePartExtensionData, SpecificFields},
core::{IString, NString, NonEmptyVec},
fetch::MessageDataItem,
response::{Data, Response},
};
let fetch = {
let data = Data::Fetch {
seq: NonZeroU32::new(42).unwrap(),
items: NonEmptyVec::try_from(vec![
MessageDataItem::Rfc822Size(1337),
MessageDataItem::Body(BodyStructure::Single {
body: Body {
basic: BasicFields {
parameter_list: vec![],
id: NString(None),
description: NString(Some(
IString::try_from("Important message.").unwrap(),
)),
content_transfer_encoding: IString::try_from("base64").unwrap(),
size: 512,
},
specific: SpecificFields::Basic {
r#type: IString::try_from("text").unwrap(),
subtype: IString::try_from("html").unwrap(),
},
},
extension_data: None,
}),
])
.unwrap(),
};
Response::Data(data)
};
Supported IMAP extensions
Description |
---|
IMAP4 Non-synchronizing Literals (RFC 2088, RFC 7888) |
IMAP MOVE Extension (RFC 6851) |
IMAP UNSELECT command (RFC 3691) |
IMAP Extension for SASL Initial Client Response (RFC 4959) |
The IMAP COMPRESS Extension (RFC 4978) |
The IMAP ENABLE Extension (RFC 5161) |
IMAP4 IDLE command (RFC 2177) |
IMAP QUOTA Extension (RFC 9208) |
Features
This crate uses the following features to enable experimental IMAP extensions:
Feature | Description | Status |
---|---|---|
ext_condstore_qresync | Quick Flag Changes Resynchronization and Quick Mailbox Resynchronization (RFC 7162) | Unfinished |
ext_login_referrals | IMAP4 Login Referrals (RFC 2221) | Unfinished |
ext_mailbox_referrals | IMAP4 Mailbox Referrals (RFC 2193) | Unfinished |
starttls | IMAP4rev1 (RFC 3501; section 6.2.1) |
STARTTLS is not an IMAP extension but feature-gated because it should be avoided. For better performance and security, use “implicit TLS”, i.e., IMAP-over-TLS on port 993, and don’t use STARTTLS at all.
Furthermore, imap-types uses the following features to facilitate interoperability:
Feature | Description | Enabled by default |
---|---|---|
arbitrary | Derive Arbitrary implementations. | No |
bounded-static | Derive ToStatic/IntoStatic implementations. | No |
serde | Derive serde s Serialize and Deserialize implementations. | No |
unvalidated | Unlock unvalidated constructors. | No |
When using arbitrary
, all types defined in imap-types implement the Arbitrary trait to ease testing.
This is used, for example, to generate instances during fuzz-testing.
(See, e.g., imap-types/fuzz/fuzz_targets/to_static.rs
)
When using bounded-static
, all types provide a to_static
and into_static
method that converts a type into its “owned” variant.
This is useful when you want to pass objects around, e.g., into other threads, a vector, etc.
When the serde
feature is used, all types implement Serde’s Serialize and
Deserialize traits. (Try running cargo run --example serde_json
.)
Re-exports
pub use bounded_static;
Modules
- Authentication-related types.
- Body(structure)-related types.
- Client Commands.
- Core data types.
- Date and time-related types.
- Envelope-related types.
- Error-related types.
- IMAP extensions.
- Fetch-related types.
- Flag-related types.
- Mailbox-related types.
- 7. Server Responses
- Search-related types.
- Handling of secret values.
- IMAP protocol state.
- Functions that may come in handy.