diff options
| author | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 18:47:40 -0300 |
|---|---|---|
| committer | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 18:47:40 -0300 |
| commit | d9738b4be2add82ff955f061c79316b0dc91768f (patch) | |
| tree | e0f31bb9f72dff315fc475f9e9f30322b69602ff /src/cli.rs | |
| download | posta-main.tar.gz posta-main.zip | |
Diffstat (limited to 'src/cli.rs')
| -rw-r--r-- | src/cli.rs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..920f7bf --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,133 @@ +//! Command-line interface definition. + +use std::path::PathBuf; + +use clap::{Parser, Subcommand, ValueEnum}; + +#[derive(Parser)] +#[command( + name = "posta", + version, + about = "A tiny, generic IMAP/SMTP mail CLI", + long_about = "posta — manage any IMAP/SMTP mailbox from your terminal.\n\ + Accounts live in a TOML config file; every command prints JSON \ + by default so it plays nicely with jq and scripts." +)] +pub struct Cli { + /// Config file (default: $POSTA_CONFIG or ~/.config/posta/config.toml) + #[arg(long, global = true, value_name = "FILE")] + pub config: Option<PathBuf>, + + /// Account name from the config (default: $POSTA_ACCOUNT or `default_account`) + #[arg(long, short = 'a', global = true, value_name = "NAME")] + pub account: Option<String>, + + /// Output format + #[arg(long, global = true, value_enum, default_value_t = Format::Json)] + pub format: Format, + + #[command(subcommand)] + pub cmd: Cmd, +} + +#[derive(Clone, Copy, PartialEq, Eq, ValueEnum)] +pub enum Format { + Json, + Table, +} + +#[derive(Subcommand)] +pub enum Cmd { + /// List the accounts defined in the config file + Accounts, + /// List mailbox folders + Folders, + /// Message and unread counts for a folder + Status { + #[arg(long, default_value = "INBOX")] + folder: String, + }, + /// List messages, newest first + List { + #[arg(long, default_value = "INBOX")] + folder: String, + /// Only unread messages (shorthand for --query UNSEEN) + #[arg(long)] + unread: bool, + /// Raw IMAP SEARCH query, e.g. 'FROM bank SINCE 1-Jul-2026' + #[arg(long)] + query: Option<String>, + #[arg(long, default_value_t = 20)] + max: usize, + }, + /// Show a message by UID + Get { + uid: u32, + #[arg(long, default_value = "INBOX")] + folder: String, + /// Print the raw RFC 822 source + #[arg(long)] + raw: bool, + /// Prefer the text/html part over text/plain + #[arg(long)] + html: bool, + /// Mark the message as read after fetching it + #[arg(long)] + mark_read: bool, + }, + /// Send a message (body from --body, --body-file, or stdin) + Send { + #[arg(long, required = true)] + to: Vec<String>, + #[arg(long)] + cc: Vec<String>, + #[arg(long)] + subject: String, + #[arg(long)] + body: Option<String>, + #[arg(long)] + body_file: Option<PathBuf>, + /// Skip saving a copy to the sent folder + #[arg(long)] + no_record: bool, + }, + /// Add or remove message flags + Mark { + #[arg(value_enum)] + state: MarkState, + #[arg(required = true)] + uids: Vec<u32>, + #[arg(long, default_value = "INBOX")] + folder: String, + }, + /// Move messages to another folder + Move { + #[arg(required = true)] + uids: Vec<u32>, + #[arg(long)] + to: String, + #[arg(long, default_value = "INBOX")] + folder: String, + }, + /// Move messages to the trash folder + Delete { + #[arg(required = true)] + uids: Vec<u32>, + #[arg(long, default_value = "INBOX")] + folder: String, + }, + /// Run an IMAP SEARCH query and print matching UIDs + Search { + query: String, + #[arg(long, default_value = "INBOX")] + folder: String, + }, +} + +#[derive(Clone, Copy, ValueEnum)] +pub enum MarkState { + Read, + Unread, + Flagged, + Unflagged, +} |