1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(
author,
version,
about = "Mail CLI in Rust supporting all mail functions & OAuth2 login"
)]
pub struct Cli {
#[command(subcommand)]
pub resource: Resource,
}
#[derive(Subcommand)]
pub enum Resource {
Account {
#[command(subcommand)]
operation: AccountOperation,
},
Mail {
#[command(subcommand)]
operation: MailOperation,
},
Folder {
#[command(subcommand)]
operation: FolderOperation,
},
}
#[derive(Subcommand)]
pub enum AccountOperation {
/// Add a new mail account
Add,
/// List all configured accounts
///
/// Displays a list of all configured accounts.
/// The currently active account (used by default for mail commands)
/// will be highlighted.
#[command(alias = "ls")]
List,
/// Switch the active account
///
/// Sets the specified account as the default for all following
/// mail and folder operations.
Use {
/// The ID or email of the account to activate
account: String,
},
/// Display information about the currently active account
///
/// Shows details for the account currently in use, including
/// the email address, display name, and connection settings.
Whoami,
/// Modify an existing account's settings
///
/// Update specific details like the name or server. If no flags are
/// provided, the currently active account will be edited.
Edit {
/// The ID or email of the account to edit
#[arg(short, long)]
account: Option<String>,
},
/// Log out of an account and clear configuration
///
/// This command removes the account configuration from your local machine.
/// This action is IRREVERSIBLE and does not delete the actual
/// mail on the server.
Logout {
/// The account ID or email to log out of (defaults to the currently active account)
#[arg(short, long)]
account: Option<String>,
},
}
#[derive(Subcommand)]
pub enum MailOperation {
/// Construct and send a new email
///
/// If required fields (to, subject, body) are missing from the flags,
/// the application will prompt for them interactively.
Send {
/// Recipient email address(es)
#[arg(short, long, value_delimiter = ',')]
to: Option<Vec<String>>,
/// The subject line of the email
#[arg(short, long)]
subject: Option<String>,
/// The message content
#[arg(short, long)]
body: Option<String>,
/// Path to files to attach (can be used multiple times)
#[arg(short, long)]
attachments: Option<Vec<std::path::PathBuf>>,
/// Whether to skip final confirmation
#[arg(short, long)]
yes: bool,
},
/// View the full content of a specific email
///
/// This command fetches the entire message (sender, subject, body) from
/// the server using the index number provided by the 'folder view' command.
Read {
/// The folder where the email is located
folder: String,
/// The index number shown next to the email in 'folder view'
id: u32,
},
/// Download the attachment(s) of a specific email
///
/// This command downloads all attachments into the save folder.
/// If the attachment ID is set, only the attachments with this index
/// will be downloaded.
Download {
/// The folder where the email is located
folder: String,
/// The index number shown next to the email in 'folder view'
id: u32,
/// The index number shown next to the attachments when viewing an email
#[arg(short, long, value_delimiter = ',')]
attachment_id: Option<Vec<u32>>,
/// The folder to save the attachments to
save_folder: String,
},
/// Search for messages matching a specific sender or query
///
/// This command performs a client-side search of your mail.
/// It scans headers, subjects, and body content to find
/// relevant matches.
Search {
/// The search terms or sender to look for
#[arg(short, long)]
query: String,
/// The folder to search within
///
/// Defaults to INBOX. Use 'ALL' to search across every
/// folder available on the account.
#[arg(short, long, default_value = "INBOX")]
folder: String,
},
/// Move a message from one folder to another
///
/// This command transfers a specific email between folders on the
/// server.
Move {
/// The name of the folder where the message is currently located
///
/// Examples: INBOX, Sent, Drafts.
from: String,
/// The name of the destination folder
///
/// If the folder does not exist, the command will fail.
to: String,
/// The index number(s) of the message(s) to move
#[arg(short, long, value_delimiter = ',')]
id: Vec<u32>,
},
/// Delete a message
///
/// This command permanently deletes a message. This action cannot
/// be undone.
Delete {
/// The index number(s) of the message(s) to delete
///
/// If not provided, multiple messages can be selected
/// interactively.
#[arg(short, long, value_delimiter = ',')]
id: Option<Vec<u32>>,
/// The folder where the message(s) are in
#[arg(short, long)]
folder: String,
},
}
#[derive(Subcommand)]
pub enum FolderOperation {
/// List all available mail folders on the server
///
/// Fetches the complete directory tree of your mailbox. This includes
/// standard folders (INBOX, Sent, Trash) and any custom labels or
/// subfolders you have created.
#[command(alias = "ls")]
List {
/// Show the number of messages and unread counts for each folder
///
/// Note: Enabling this may take longer as the program must
/// query the status of each folder individually.
#[arg(short, long)]
stats: bool,
},
/// View all messages within a specific folder
///
/// This command retrieves the message infos (sender, subject, received date)
/// from the requested folder and displays them in a list. It is the
/// primary way to browse through your Mailboxes.
View {
/// The name of the folder to open
///
/// Case-sensitivity depends on your mail provider.
folder: String,
/// Number of messages to show per page
#[arg(short, long, default_value_t = 20)]
page_size: usize,
},
/// Create a new folder on the mail server
///
/// This command adds a new mailbox to your account. You can
/// create top-level folders or subfolders by using the
/// server's delimiter (usually a forward slash or a dot).
Create {
/// The name of the new folder to be created
///
/// Example: 'Projects' or 'Work/Invoices'. Avoid using
/// reserved names like 'INBOX'.
name: String,
/// Automatically create parent folders if they don't exist
#[arg(short, long)]
parents: bool,
},
/// Permanently remove a folder from the server
///
/// This action will delete the folder and, depending on your server
/// configuration, may also delete all messages contained within it.
/// This cannot be undone.
Delete {
/// The name of the folder to delete
name: Vec<String>,
/// Delete the folder even if it contains subfolders
#[arg(short, long)]
recursive: bool,
/// Skip the confirmation
#[arg(short, long)]
yes: bool,
},
/// Delete all messages within a specific folder
///
/// This command permanently removes every email inside the target
/// folder while keeping the folder structure intact. This is
/// commonly used to clear out 'Trash' or 'Spam' folders.
Empty {
/// The name of the folder to empty
name: String,
},
}