daaki-imap 0.1.0

An IMAP4rev1/IMAP4rev2 async client library
Documentation

daaki-imap

An async IMAP client that takes the specs seriously.

Highlights

  • IMAP4rev1 and IMAP4rev2 — support for both RFC 3501 and RFC 9051.
  • 30+ extensions — IDLE, CONDSTORE/QRESYNC, MOVE, COMPRESS=DEFLATE, THREAD, OBJECTID, and many more.
  • Async with explicit timeouts — built on tokio. Every operation takes a Duration — no hidden infinite waits.
  • TLS by default — rustls-based TLS with implicit TLS (port 993) and STARTTLS.
  • Zero unsafe code — enforced by #![deny(unsafe_code)] crate-wide.
  • Owned types everywhere — all public API types use String/Vec<u8>.

Quick Start

[dependencies]
daaki-imap = "0.1"

Connect, log in, and fetch the subjects of the first 5 messages in INBOX:

use daaki_imap::{ImapConnection, TlsMode};
use std::time::Duration;

#[tokio::main]
async fn main() -> daaki_imap::Result<()> {
    let timeout = Duration::from_secs(30);

    let mut conn = ImapConnection::connect(
        "imap.example.com", 993, TlsMode::Implicit, timeout,
    ).await?;
    conn.login("user@example.com", "password", timeout).await?;

    let mailbox = conn.select("INBOX", timeout).await?;
    println!("INBOX has {} messages", mailbox.exists);

    let messages = conn.fetch("1:5", "ENVELOPE", timeout).await?;
    for msg in &messages {
        if let Some(env) = &msg.envelope {
            println!("Subject: {}", env.subject.as_deref().unwrap_or("(none)"));
        }
    }

    conn.logout(timeout).await?;
    Ok(())
}

IDLE

Wait for new messages without polling. Pass a cancellation token to break out from another task:

# use daaki_imap::{IdleEvent, ImapConnection};
# use tokio_util::sync::CancellationToken;
# use std::time::Duration;
# async fn example(conn: &mut ImapConnection) -> daaki_imap::Result<()> {
let cancel = CancellationToken::new();

match conn.idle(Duration::from_secs(300), cancel.clone()).await? {
    IdleEvent::Exists(n) => println!("mailbox now has {n} messages"),
    IdleEvent::Expunge(n) => println!("message {n} was deleted"),
    IdleEvent::Timeout => println!("idle timed out"),
    IdleEvent::Cancelled => println!("cancelled"),
    _ => {}
}
# Ok(())
# }

COMPRESS=DEFLATE

Enable wire-level compression — all subsequent traffic is compressed transparently:

# async fn example(conn: &mut daaki_imap::ImapConnection) -> daaki_imap::Result<()> {
conn.compress(std::time::Duration::from_secs(10)).await?;
# Ok(())
# }

Supported Extensions

Category Extensions
Real-time IDLE, NOTIFY
Search ESEARCH, SEARCHRES, THREAD, SORT
Mailbox management MOVE, UNSELECT, CHILDREN, SPECIAL-USE, LIST-EXTENDED, LIST-STATUS, STATUS=SIZE, NAMESPACE
Message metadata CONDSTORE, QRESYNC, OBJECTID, SAVEDATE, $Important
Append MULTIAPPEND, APPENDLIMIT, UIDPLUS
Encoding & transport COMPRESS=DEFLATE, BINARY, LITERAL+, UTF8=ACCEPT
Access control ACL, QUOTA, METADATA
Auth SASL-IR, ENABLE, ID

License

The contents of this package are licensed under the terms of the MIT license.