@cli4ai/gmail 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +214 -0
  2. package/c4ai.json +46 -0
  3. package/package.json +42 -0
  4. package/run.ts +316 -0
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # Gmail
2
+
3
+ Full-featured Gmail CLI via Google API. Fast, powerful search, send/reply/forward.
4
+
5
+ ## Commands
6
+
7
+ ### Reading
8
+ ```bash
9
+ ./run.js inbox [limit] # Recent inbox messages (default: 20)
10
+ ./run.js unread [limit] # Unread messages only
11
+ ./run.js search <query> [limit] # Search with Gmail syntax
12
+ ./run.js read <id> # Read full message
13
+ ./run.js thread <id> # Full conversation thread
14
+ ./run.js threads [limit] [query] # List recent threads
15
+ ```
16
+
17
+ ### Actions
18
+ ```bash
19
+ ./run.js archive <id> # Archive (remove from inbox)
20
+ ./run.js trash <id> # Move to trash
21
+ ./run.js untrash <id> # Restore from trash
22
+ ./run.js star <id> # Star message
23
+ ./run.js unstar <id> # Unstar message
24
+ ./run.js markread <id> # Mark as read
25
+ ./run.js markunread <id> # Mark as unread
26
+ ```
27
+
28
+ ### Sending
29
+ ```bash
30
+ ./run.js send <to> <subject> <body> # Send new email
31
+ ./run.js reply <id> <body> # Reply to message
32
+ ./run.js replyall <id> <body> # Reply to all
33
+ ./run.js forward <id> <to> [body] # Forward message
34
+ ./run.js draft <to> <subject> <body> # Create draft (legacy)
35
+ ```
36
+
37
+ ### Drafts
38
+ ```bash
39
+ ./run.js drafts # List all drafts
40
+ ./run.js draft-get <id> # Get draft content
41
+ ./run.js draft-create <to> <subj> <body> # Create new draft
42
+ ./run.js draft-reply <msg-id> <body> # Create draft reply to message
43
+ ./run.js draft-update <id> <to> <s> <b> # Update existing draft
44
+ ./run.js draft-delete <id> # Delete draft
45
+ ./run.js draft-send <id> # Send draft
46
+ ```
47
+
48
+ ### Attachments
49
+ ```bash
50
+ ./run.js attachments <id> # List attachments in message
51
+ ./run.js download <id> [filename] [out] # Download specific attachment
52
+ ./run.js download-all <id> [dir] # Download all attachments
53
+ ```
54
+
55
+ ### Labels
56
+ ```bash
57
+ ./run.js labels # List all labels
58
+ ./run.js label <id> <label> # Add label to message
59
+ ./run.js unlabel <id> <label> # Remove label
60
+ ./run.js label-info <label> # Get label with counts
61
+ ./run.js label-create <name> # Create new label
62
+ ./run.js label-delete <name> # Delete label
63
+ ```
64
+
65
+ ## Output Flags
66
+
67
+ ```bash
68
+ --raw, -r # Full JSON output
69
+ --compact, -c # One-line per message (great for quick scans)
70
+ --body, -b # Include body in search results
71
+ --full, -f # Full body (no truncation)
72
+ --limit=N # Override default limit
73
+ --cc=email # Add CC recipient
74
+ --bcc=email # Add BCC recipient
75
+ --attach=/path/file # Add attachment (repeatable)
76
+ ```
77
+
78
+ ## Gmail Search Syntax
79
+
80
+ The search command uses Gmail's powerful search syntax:
81
+
82
+ ```bash
83
+ # By sender/recipient
84
+ ./run.js search "from:boss@company.com"
85
+ ./run.js search "to:me"
86
+ ./run.js search "cc:team@company.com"
87
+
88
+ # By status
89
+ ./run.js search "is:unread"
90
+ ./run.js search "is:starred"
91
+ ./run.js search "is:important"
92
+
93
+ # By content
94
+ ./run.js search "subject:meeting"
95
+ ./run.js search "has:attachment"
96
+ ./run.js search "filename:pdf"
97
+
98
+ # By date
99
+ ./run.js search "after:2024/12/01"
100
+ ./run.js search "before:2024/12/31"
101
+ ./run.js search "newer_than:7d"
102
+ ./run.js search "older_than:1m"
103
+
104
+ # By label/location
105
+ ./run.js search "label:work"
106
+ ./run.js search "in:inbox"
107
+ ./run.js search "in:sent"
108
+
109
+ # Combine queries
110
+ ./run.js search "from:boss@company.com is:unread newer_than:7d"
111
+ ./run.js search "has:attachment larger:5M"
112
+ ```
113
+
114
+ ## Examples
115
+
116
+ ```bash
117
+ # Quick inbox scan
118
+ ./run.js inbox 10 --compact
119
+
120
+ # Find unread from specific sender
121
+ ./run.js search "from:important@client.com is:unread"
122
+
123
+ # Read a specific email
124
+ ./run.js read 19b176a2f49b681f
125
+
126
+ # View full conversation thread
127
+ ./run.js thread 19b176a2f49b681f
128
+
129
+ # Send an email
130
+ ./run.js send "john@example.com" "Meeting tomorrow" "Hi John,\n\nAre we still on for tomorrow?\n\nThanks"
131
+
132
+ # Reply to an email
133
+ ./run.js reply 19b176a2f49b681f "Thanks for the update, looks good!"
134
+
135
+ # Forward an email
136
+ ./run.js forward 19b176a2f49b681f "colleague@example.com" "FYI - see below"
137
+
138
+ # Archive old emails
139
+ ./run.js archive 19b176a2f49b681f
140
+
141
+ # Label management
142
+ ./run.js label 19b176a2f49b681f "Work"
143
+ ./run.js label-info "INBOX"
144
+
145
+ # Send with attachment
146
+ ./run.js send "john@example.com" "Report" "See attached" --attach=./report.pdf
147
+
148
+ # Multiple attachments
149
+ ./run.js send "john@example.com" "Files" "Here are the files" --attach=./a.pdf --attach=./b.pdf
150
+
151
+ # List and download attachments
152
+ ./run.js attachments 19b176a2f49b681f
153
+ ./run.js download 19b176a2f49b681f "report.pdf" ./downloads/report.pdf
154
+ ./run.js download-all 19b176a2f49b681f ./downloads/
155
+
156
+ # Draft management
157
+ ./run.js drafts
158
+ ./run.js draft-create "john@example.com" "Draft" "Will finish later"
159
+ ./run.js draft-reply 19b176a2f49b681f "Thanks, need to think about this"
160
+ ./run.js draft-send r123456789
161
+ ```
162
+
163
+ ## Setup
164
+
165
+ ### 1. Google Cloud Project
166
+
167
+ 1. Go to [Google Cloud Console](https://console.cloud.google.com)
168
+ 2. Create a project (or use existing)
169
+ 3. Enable Gmail API
170
+ 4. Create OAuth 2.0 credentials (Desktop app type)
171
+ 5. Download `credentials.json`
172
+
173
+ ### 2. Place Credentials
174
+
175
+ Put `credentials.json` in the `gmail/` directory, or set path in `.env`:
176
+
177
+ ```bash
178
+ GMAIL_CREDENTIALS_PATH=/path/to/credentials.json
179
+ GMAIL_TOKEN_PATH=/path/to/token.json
180
+ ```
181
+
182
+ ### 3. First Run
183
+
184
+ On first run, you'll be prompted to authorize:
185
+
186
+ 1. Visit the OAuth URL shown
187
+ 2. Sign in with your Google account
188
+ 3. Copy the authorization code
189
+ 4. Paste it in the terminal
190
+
191
+ Token is saved and auto-refreshes.
192
+
193
+ ## Project Structure
194
+
195
+ ```
196
+ gmail/
197
+ ├── run.js # CLI entry point
198
+ ├── lib/
199
+ │ ├── api.js # Gmail API client + OAuth
200
+ │ ├── messages.js # inbox, unread, search, read, archive...
201
+ │ ├── threads.js # Thread operations
202
+ │ ├── send.js # send, reply, forward (with attachment support)
203
+ │ ├── drafts.js # Draft management, reply drafts
204
+ │ ├── attachments.js # List, download attachments
205
+ │ └── labels.js # Label management
206
+ ├── credentials.json # OAuth credentials (gitignored)
207
+ └── token.json # Auth token (gitignored)
208
+ ```
209
+
210
+ ## Required Scopes
211
+
212
+ - `gmail.modify` - Read, send, delete, manage labels
213
+ - `gmail.compose` - Create drafts and send
214
+ - `gmail.send` - Send emails
package/c4ai.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "gmail",
3
+ "version": "1.0.0",
4
+ "description": "Gmail CLI tool for messages, threads, and drafts",
5
+ "author": "cliforai",
6
+ "license": "MIT",
7
+ "entry": "run.ts",
8
+ "runtime": "bun",
9
+ "keywords": ["gmail", "email", "google", "mail"],
10
+ "commands": {
11
+ "inbox": { "description": "Recent inbox messages", "args": [{ "name": "limit", "required": false }] },
12
+ "unread": { "description": "Unread messages only", "args": [{ "name": "limit", "required": false }] },
13
+ "search": { "description": "Search with Gmail syntax", "args": [{ "name": "query", "required": true }, { "name": "limit", "required": false }] },
14
+ "read": { "description": "Read full message", "args": [{ "name": "id", "required": true }] },
15
+ "archive": { "description": "Archive message", "args": [{ "name": "id", "required": true }] },
16
+ "trash": { "description": "Move to trash", "args": [{ "name": "id", "required": true }] },
17
+ "untrash": { "description": "Remove from trash", "args": [{ "name": "id", "required": true }] },
18
+ "star": { "description": "Star message", "args": [{ "name": "id", "required": true }] },
19
+ "unstar": { "description": "Unstar message", "args": [{ "name": "id", "required": true }] },
20
+ "markread": { "description": "Mark as read", "args": [{ "name": "id", "required": true }] },
21
+ "markunread": { "description": "Mark as unread", "args": [{ "name": "id", "required": true }] },
22
+ "thread": { "description": "Full conversation thread", "args": [{ "name": "id", "required": true }] },
23
+ "threads": { "description": "List recent threads", "args": [{ "name": "limit", "required": false }] },
24
+ "send": { "description": "Send new email", "args": [{ "name": "to", "required": true }, { "name": "subject", "required": true }, { "name": "body", "required": true }] },
25
+ "reply": { "description": "Reply to message", "args": [{ "name": "id", "required": true }, { "name": "body", "required": true }] },
26
+ "replyall": { "description": "Reply all", "args": [{ "name": "id", "required": true }, { "name": "body", "required": true }] },
27
+ "forward": { "description": "Forward message", "args": [{ "name": "id", "required": true }, { "name": "to", "required": true }] },
28
+ "draft": { "description": "Create draft", "args": [{ "name": "to", "required": true }, { "name": "subject", "required": true }, { "name": "body", "required": true }] },
29
+ "labels": { "description": "List all labels" },
30
+ "label": { "description": "Add label to message", "args": [{ "name": "id", "required": true }, { "name": "label", "required": true }] },
31
+ "unlabel": { "description": "Remove label from message", "args": [{ "name": "id", "required": true }, { "name": "label", "required": true }] },
32
+ "attachments": { "description": "List attachments in message", "args": [{ "name": "id", "required": true }] },
33
+ "download": { "description": "Download attachment", "args": [{ "name": "id", "required": true }] },
34
+ "drafts": { "description": "List all drafts" },
35
+ "draft-send": { "description": "Send draft", "args": [{ "name": "id", "required": true }] }
36
+ },
37
+ "dependencies": {
38
+ "googleapis": "^144.0.0",
39
+ "google-auth-library": "^9.0.0",
40
+ "commander": "^14.0.0"
41
+ },
42
+ "mcp": {
43
+ "enabled": true,
44
+ "transport": "stdio"
45
+ }
46
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@cli4ai/gmail",
3
+ "version": "1.0.0",
4
+ "description": "Gmail CLI tool for messages, threads, and drafts",
5
+ "author": "cliforai",
6
+ "license": "MIT",
7
+ "main": "run.ts",
8
+ "bin": {
9
+ "gmail": "./run.ts"
10
+ },
11
+ "type": "module",
12
+ "keywords": [
13
+ "c4ai",
14
+ "cli",
15
+ "ai-tools",
16
+ "gmail",
17
+ "email",
18
+ "google",
19
+ "mail"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/cli4ai/packages",
24
+ "directory": "packages/gmail"
25
+ },
26
+ "homepage": "https://github.com/cli4ai/packages/tree/main/packages/gmail",
27
+ "bugs": {
28
+ "url": "https://github.com/cli4ai/packages/issues"
29
+ },
30
+ "files": [
31
+ "run.ts",
32
+ "c4ai.json",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "test": "bun test"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ }
42
+ }
package/run.ts ADDED
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env bun
2
+ // Gmail CLI tool
3
+
4
+ import { cli, withErrorHandling } from '../lib/cli.ts';
5
+
6
+ const messages = require('./lib/messages');
7
+ const threads = require('./lib/threads');
8
+ const send = require('./lib/send');
9
+ const labels = require('./lib/labels');
10
+ const attachments = require('./lib/attachments');
11
+ const drafts = require('./lib/drafts');
12
+
13
+ interface Flags {
14
+ raw?: boolean;
15
+ compact?: boolean;
16
+ body?: boolean;
17
+ fullBody?: boolean;
18
+ limit?: number;
19
+ cc?: string;
20
+ bcc?: string;
21
+ attach?: string[];
22
+ }
23
+
24
+ const program = cli('gmail', '1.0.0', 'Gmail CLI tool');
25
+
26
+ // Global options
27
+ program
28
+ .option('--raw, -r', 'Full JSON output')
29
+ .option('--compact, -c', 'Compact one-line output')
30
+ .option('--body, -b', 'Include body in search results')
31
+ .option('--full, -f', 'Full body (no truncation)')
32
+ .option('--limit <n>', 'Override default limit', parseInt)
33
+ .option('--cc <email>', 'Add CC recipient (send/draft)')
34
+ .option('--bcc <email>', 'Add BCC recipient (send/draft)')
35
+ .option('--attach <path>', 'Add attachment (repeatable)', (val: string, prev: string[] | undefined) => {
36
+ const list = prev || [];
37
+ list.push(val);
38
+ return list;
39
+ });
40
+
41
+ // ═══════════════════════════════════════════════════════════════════════════
42
+ // MESSAGE COMMANDS
43
+ // ═══════════════════════════════════════════════════════════════════════════
44
+
45
+ program
46
+ .command('inbox')
47
+ .description('Recent inbox messages')
48
+ .argument('[limit]', 'Number of messages', '20')
49
+ .action(withErrorHandling(async (limit: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
50
+ const flags = { ...cmd.parent.opts(), limit: parseInt(limit) };
51
+ await messages.inbox(flags);
52
+ }));
53
+
54
+ program
55
+ .command('unread')
56
+ .description('Unread messages only')
57
+ .argument('[limit]', 'Number of messages', '20')
58
+ .action(withErrorHandling(async (limit: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
59
+ const flags = { ...cmd.parent.opts(), limit: parseInt(limit) };
60
+ await messages.unread(flags);
61
+ }));
62
+
63
+ program
64
+ .command('search <query>')
65
+ .description('Search with Gmail syntax')
66
+ .argument('[limit]', 'Number of results', '20')
67
+ .action(withErrorHandling(async (query: string, limit: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
68
+ const flags = { ...cmd.parent.opts(), limit: parseInt(limit) };
69
+ await messages.search(query, flags);
70
+ }));
71
+
72
+ program
73
+ .command('read <id>')
74
+ .description('Read full message')
75
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
76
+ await messages.read(id, cmd.parent.opts());
77
+ }));
78
+
79
+ program
80
+ .command('archive <id>')
81
+ .description('Archive message (remove from inbox)')
82
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
83
+ await messages.archive(id, cmd.parent.opts());
84
+ }));
85
+
86
+ program
87
+ .command('trash <id>')
88
+ .description('Move to trash')
89
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
90
+ await messages.trash(id, cmd.parent.opts());
91
+ }));
92
+
93
+ program
94
+ .command('untrash <id>')
95
+ .description('Remove from trash')
96
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
97
+ await messages.untrash(id, cmd.parent.opts());
98
+ }));
99
+
100
+ program
101
+ .command('star <id>')
102
+ .description('Star message')
103
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
104
+ await messages.star(id, cmd.parent.opts());
105
+ }));
106
+
107
+ program
108
+ .command('unstar <id>')
109
+ .description('Unstar message')
110
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
111
+ await messages.unstar(id, cmd.parent.opts());
112
+ }));
113
+
114
+ program
115
+ .command('markread <id>')
116
+ .description('Mark as read')
117
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
118
+ await messages.markRead(id, cmd.parent.opts());
119
+ }));
120
+
121
+ program
122
+ .command('markunread <id>')
123
+ .description('Mark as unread')
124
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
125
+ await messages.markUnread(id, cmd.parent.opts());
126
+ }));
127
+
128
+ // ═══════════════════════════════════════════════════════════════════════════
129
+ // THREAD COMMANDS
130
+ // ═══════════════════════════════════════════════════════════════════════════
131
+
132
+ program
133
+ .command('thread <id>')
134
+ .description('Full conversation thread')
135
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
136
+ await threads.get(id, cmd.parent.opts());
137
+ }));
138
+
139
+ program
140
+ .command('threads')
141
+ .description('List recent threads')
142
+ .argument('[limit]', 'Number of threads', '20')
143
+ .argument('[query]', 'Search query')
144
+ .action(withErrorHandling(async (limit: string, query: string | undefined, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
145
+ const flags = { ...cmd.parent.opts(), limit: parseInt(limit), query };
146
+ await threads.list(flags);
147
+ }));
148
+
149
+ // ═══════════════════════════════════════════════════════════════════════════
150
+ // SEND COMMANDS
151
+ // ═══════════════════════════════════════════════════════════════════════════
152
+
153
+ program
154
+ .command('send <to> <subject> <body>')
155
+ .description('Send new email')
156
+ .action(withErrorHandling(async (to: string, subject: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
157
+ await send.send(to, subject, body, cmd.parent.opts());
158
+ }));
159
+
160
+ program
161
+ .command('reply <id> <body>')
162
+ .description('Reply to message')
163
+ .action(withErrorHandling(async (id: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
164
+ await send.reply(id, body, cmd.parent.opts());
165
+ }));
166
+
167
+ program
168
+ .command('replyall <id> <body>')
169
+ .description('Reply all')
170
+ .action(withErrorHandling(async (id: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
171
+ await send.replyAll(id, body, cmd.parent.opts());
172
+ }));
173
+
174
+ program
175
+ .command('forward <id> <to>')
176
+ .description('Forward message')
177
+ .argument('[body]', 'Additional message')
178
+ .action(withErrorHandling(async (id: string, to: string, body: string | undefined, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
179
+ await send.forward(id, to, body, cmd.parent.opts());
180
+ }));
181
+
182
+ program
183
+ .command('draft <to> <subject> <body>')
184
+ .description('Create draft')
185
+ .action(withErrorHandling(async (to: string, subject: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
186
+ await send.draft(to, subject, body, cmd.parent.opts());
187
+ }));
188
+
189
+ // ═══════════════════════════════════════════════════════════════════════════
190
+ // LABEL COMMANDS
191
+ // ═══════════════════════════════════════════════════════════════════════════
192
+
193
+ program
194
+ .command('labels')
195
+ .description('List all labels')
196
+ .action(withErrorHandling(async (options: Flags, cmd: { parent: { opts: () => Flags } }) => {
197
+ await labels.list(cmd.parent.opts());
198
+ }));
199
+
200
+ program
201
+ .command('label <id> <label>')
202
+ .description('Add label to message')
203
+ .action(withErrorHandling(async (id: string, label: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
204
+ await labels.addToMessage(id, label, cmd.parent.opts());
205
+ }));
206
+
207
+ program
208
+ .command('unlabel <id> <label>')
209
+ .description('Remove label from message')
210
+ .action(withErrorHandling(async (id: string, label: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
211
+ await labels.removeFromMessage(id, label, cmd.parent.opts());
212
+ }));
213
+
214
+ program
215
+ .command('label-info <label>')
216
+ .description('Get label details with counts')
217
+ .action(withErrorHandling(async (label: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
218
+ await labels.get(label, cmd.parent.opts());
219
+ }));
220
+
221
+ program
222
+ .command('label-create <name>')
223
+ .description('Create new label')
224
+ .action(withErrorHandling(async (name: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
225
+ await labels.create(name, cmd.parent.opts());
226
+ }));
227
+
228
+ program
229
+ .command('label-delete <name>')
230
+ .description('Delete label')
231
+ .action(withErrorHandling(async (name: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
232
+ await labels.remove(name, cmd.parent.opts());
233
+ }));
234
+
235
+ // ═══════════════════════════════════════════════════════════════════════════
236
+ // ATTACHMENT COMMANDS
237
+ // ═══════════════════════════════════════════════════════════════════════════
238
+
239
+ program
240
+ .command('attachments <id>')
241
+ .description('List attachments in message')
242
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
243
+ await attachments.list(id, cmd.parent.opts());
244
+ }));
245
+
246
+ program
247
+ .command('download <id>')
248
+ .description('Download attachment')
249
+ .argument('[filename]', 'Specific attachment filename')
250
+ .argument('[out]', 'Output directory')
251
+ .action(withErrorHandling(async (id: string, filename: string | undefined, out: string | undefined, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
252
+ await attachments.download(id, filename, out, cmd.parent.opts());
253
+ }));
254
+
255
+ program
256
+ .command('download-all <id>')
257
+ .description('Download all attachments')
258
+ .argument('[dir]', 'Output directory')
259
+ .action(withErrorHandling(async (id: string, dir: string | undefined, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
260
+ await attachments.downloadAll(id, dir, cmd.parent.opts());
261
+ }));
262
+
263
+ // ═══════════════════════════════════════════════════════════════════════════
264
+ // DRAFT COMMANDS
265
+ // ═══════════════════════════════════════════════════════════════════════════
266
+
267
+ program
268
+ .command('drafts')
269
+ .description('List all drafts')
270
+ .action(withErrorHandling(async (options: Flags, cmd: { parent: { opts: () => Flags } }) => {
271
+ await drafts.list(cmd.parent.opts());
272
+ }));
273
+
274
+ program
275
+ .command('draft-get <id>')
276
+ .description('Get draft content')
277
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
278
+ await drafts.get(id, cmd.parent.opts());
279
+ }));
280
+
281
+ program
282
+ .command('draft-create <to> <subject> <body>')
283
+ .description('Create new draft')
284
+ .action(withErrorHandling(async (to: string, subject: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
285
+ await drafts.create(to, subject, body, cmd.parent.opts());
286
+ }));
287
+
288
+ program
289
+ .command('draft-reply <msgId> <body>')
290
+ .description('Create draft reply to message')
291
+ .action(withErrorHandling(async (msgId: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
292
+ await drafts.createReply(msgId, body, cmd.parent.opts());
293
+ }));
294
+
295
+ program
296
+ .command('draft-update <id> <to> <subject> <body>')
297
+ .description('Update existing draft')
298
+ .action(withErrorHandling(async (id: string, to: string, subject: string, body: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
299
+ await drafts.update(id, to, subject, body, cmd.parent.opts());
300
+ }));
301
+
302
+ program
303
+ .command('draft-delete <id>')
304
+ .description('Delete draft')
305
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
306
+ await drafts.remove(id, cmd.parent.opts());
307
+ }));
308
+
309
+ program
310
+ .command('draft-send <id>')
311
+ .description('Send draft')
312
+ .action(withErrorHandling(async (id: string, options: Flags, cmd: { parent: { opts: () => Flags } }) => {
313
+ await drafts.send(id, cmd.parent.opts());
314
+ }));
315
+
316
+ program.parse();