CLI and lib to discover PIM-related services, written in Rust.
This repository ships three things:
- Low-level I/O-free coroutines (no_std state machines that emit read/write requests)
- Mid-level clients, based on coroutines (standard, blocking)
- High-level CLI, based on std clients
- Mozilla Thunderbird Autoconfiguration support wiki (requires
autoconfigfeature):- ISP main and
/.well-known/URL lookups - Thunderbird ISPDB lookup
- DNS MX-based retry against the MX target's parent domain
- DNS TXT
mailconf=<URL>redirect
- ISP main and
- RFC 6186 SRV mail service discovery rfc6186 (requires
rfc6186feature):_imap._tcp,_imaps._tcp,_submission._tcpassembly into a single report
- RFC 6764 SRV CalDAV/CardDAV discovery rfc6764 (requires
rfc6764feature):_caldav._tcp,_caldavs._tcp,_carddav._tcp,_carddavs._tcpassembly into a single report
- PACC discovery support draft-ietf-mailmaint-pacc-02 (requires
paccfeature):- Well-known JSON configuration fetch
- SHA-256 digest verification against the
_ua-auto-configTXT record
- TLS support:
- Rustls with ring crypto (requires
rustls-ringfeature) - Rustls with aws crypto (requires
rustls-awsfeature) - Native TLS (requires
native-tlsfeature)
- Rustls with ring crypto (requires
- JSON output via
--json
Tip
pimconf is written in Rust and uses cargo features to gate functionality. The default feature set is declared in Cargo.toml.
The CLI binary pimconf has not been officially released yet. Check the releases GitHub workflow and look for the Artifacts section. These pre-built binaries are built from the master branch.
Note
Pre-built binaries are built with the default cargo features, plus cli. If you need more features, please use another installation method.
cargo install pimconf --lockedYou can also use the git repository for a more up-to-date (but less stable) version:
cargo install --locked --git https://github.com/pimalaya/pimconf.gitTo use pimconf as a library, add it to your Cargo.toml:
[dependencies]
pimconf = { version = "0.1", default-features = false, features = ["autoconfig", "pacc", "rfc6186", "rfc6764", "client"] }The client feature pulls in the std-blocking helpers. Drop it (and pick any combination of autoconfig / pacc / rfc6186 / rfc6764) for a no_std-friendly, pure-coroutine build.
If you have the Flakes feature enabled:
nix profile install github:pimalaya/pimconfOr run without installing:
nix run github:pimalaya/pimconf -- autoconfig <local-part> <domain>git clone https://github.com/pimalaya/pimconf
cd pimconf
nix runUsing a low-level DNS MX I/O-free coroutine:
use std::{io::{Read, Write}, net::TcpStream};
use pimconf::{
autoconfig::mx::DiscoveryDnsMx,
coroutine::{DiscoveryCoroutine, DiscoveryCoroutineState, DiscoveryYield},
};
use url::Url;
let resolver = Url::parse("tcp://1.1.1.1:53").unwrap();
let mut stream = TcpStream::connect("1.1.1.1:53").unwrap();
let mut coroutine = DiscoveryDnsMx::new("fastmail.com", resolver);
let mut buf = [0u8; 4096];
let mut arg: Option<&[u8]> = None;
let records = loop {
match coroutine.resume(arg.take()) {
DiscoveryCoroutineState::Complete(Ok(records)) => break records,
DiscoveryCoroutineState::Complete(Err(err)) => panic!("{err}"),
DiscoveryCoroutineState::Yielded(DiscoveryYield::WantsWrite { bytes, .. }) => {
stream.write_all(&bytes).unwrap();
}
DiscoveryCoroutineState::Yielded(DiscoveryYield::WantsRead { .. }) => {
let n = stream.read(&mut buf).unwrap();
arg = Some(&buf[..n]);
}
}
};
for record in records {
println!("- {} {}", record.rdata.preference.get(), record.rdata.exchange);
}Using a mid-level std PACC client:
use pimconf::pacc::client::DiscoveryPaccClientStd;
use pimalaya_stream::tls::Tls;
use url::Url;
let dns = Url::parse("tcp://1.1.1.1:53").unwrap();
let mut client = DiscoveryPaccClientStd::new(dns).with_tls(Tls::default());
let config = client.discover("fastmail.com").unwrap();
println!("{config:#?}");Run the full Thunderbird Autoconfiguration chain on <local_part> <domain>:
pimconf autoconfig user fastmail.comThe chain tries, in order: every ISP main URL (secure then plain), every /.well-known/ URL (secure then plain), the Thunderbird ISPDB, then re-tries the same against the MX target's parent domain, then logs the mailconf=<URL> TXT redirect if one is published.
Run a single primitive instead:
pimconf autoconfig user fastmail.com isp --secure
pimconf autoconfig user fastmail.com isp-fallback --secure
pimconf autoconfig user fastmail.com ispdb --secure
pimconf autoconfig user fastmail.com mx
pimconf autoconfig user fastmail.com mailconfRun RFC 6186 SRV discovery (top-level subcommand):
pimconf srv fastmail.comRun RFC 6764 CalDAV/CardDAV SRV discovery:
pimconf rfc6764 fastmail.comRun PACC discovery:
pimconf pacc fastmail.comJSON output:
pimconf --json autoconfig user fastmail.comPick a specific TLS stack and crypto provider:
pimconf --tls rustls --rustls-crypto ring autoconfig user fastmail.com
pimconf --tls native-tls pacc fastmail.com
pimconf --tls-cert /path/to/extra-root.pem autoconfig user fastmail.comHow to debug the CLI?
Use --log <level> where <level> is one of off, error, warn, info, debug, trace:
pimconf --log trace autoconfig user fastmail.comThe RUST_LOG environment variable, when set, overrides --log and supports per-target filters (see the env_logger documentation). RUST_BACKTRACE=1 enables full error backtraces.
Logs are written to stderr, so they can be redirected easily to a file:
pimconf --log trace autoconfig user fastmail.com 2>/tmp/pimconf.logThis project is licensed under either of:
at your option.
This project is developed with AI assistance. This section documents how, so users and downstream packagers can make informed decisions.
-
Tools: Claude Code (Anthropic), Opus 4.7, invoked locally with a persistent project-scoped memory and a small set of repo-specific rules.
-
Used for: Refactors, mechanical multi-file edits, boilerplate (feature gates, error enums, derive macros, trait impls), test scaffolding, doc polish, exploratory design conversations.
-
Not used for: Engineering, critical code, git manipulation (commit, merge, rebase…), real-world tests.
-
Verification: Every AI-assisted change is read, compiled, tested, and formatted before commit (
nix develop --command cargo check / cargo test / cargo fmt). Behavioural correctness is verified against the relevant RFC or upstream spec, not assumed from the model output. Tests are never adjusted to fit AI-generated code; the code is adjusted to fit correct behaviour. -
Limitations: AI models occasionally produce code that compiles and passes tests but is subtly wrong: off-by-one errors, missed edge cases, plausible but nonexistent APIs, stale RFC references. The verification workflow catches most of this; it does not catch all of it. Bug reports are welcome and taken seriously.
-
Last reviewed: 31/05/2026
- Chat on Matrix
- News on Mastodon or RSS
- Mail at pimalaya.org@posteo.net
Special thanks to the NLnet foundation and the European Commission that have been financially supporting the project for years:
- 2022 → 2023: NGI Assure
- 2023 → 2024: NGI Zero Entrust
- 2024 → 2026: NGI Zero Core
- 2027 in preparation…
If you appreciate the project, feel free to donate using one of the following providers:
