package-installer-cli 1.3.3 → 1.4.1

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/dist/commands/email.js +1150 -0
  3. data/dist/email-templates/bugReport.js +108 -0
  4. data/dist/email-templates/collectors/bugReport.js +41 -0
  5. data/dist/email-templates/collectors/common.js +56 -0
  6. data/dist/email-templates/collectors/customMessage.js +48 -0
  7. data/dist/email-templates/collectors/docs.js +41 -0
  8. data/dist/email-templates/collectors/featureRequest.js +47 -0
  9. data/dist/email-templates/collectors/improvement.js +52 -0
  10. data/dist/email-templates/collectors/index.js +9 -0
  11. data/dist/email-templates/collectors/question.js +31 -0
  12. data/dist/email-templates/collectors/templateRequest.js +53 -0
  13. data/dist/email-templates/customMessage.js +135 -0
  14. data/dist/email-templates/docs.js +111 -0
  15. data/dist/email-templates/featureRequest.js +111 -0
  16. data/dist/email-templates/generator.js +67 -0
  17. data/dist/email-templates/improvement.js +121 -0
  18. data/dist/email-templates/index.js +15 -0
  19. data/dist/email-templates/question.js +101 -0
  20. data/dist/email-templates/styles.js +168 -0
  21. data/dist/email-templates/templateRequest.js +120 -0
  22. data/dist/email-templates/testEmail.js +56 -0
  23. data/dist/email-templates/types.js +1 -0
  24. data/dist/index.js +29 -1
  25. data/dist/utils/featureInstaller.js +4 -11
  26. data/features/ai/ai.json +547 -0
  27. data/features/analytics/analytics.json +4 -0
  28. data/features/auth/auth.json +473 -0
  29. data/features/auth/auth0/django/backend/apiexample/urls.py +10 -0
  30. data/features/auth/auth0/django/backend/apiexample/validator.py +21 -0
  31. data/features/auth/auth0/django/backend/apiexample/views.py +30 -0
  32. data/features/auth/auth0/django/backend/requirements.txt +4 -0
  33. data/features/auth/auth0/django/web-app/requirements.txt +4 -0
  34. data/features/auth/auth0/django/web-app/webappexample/settings.py +28 -0
  35. data/features/auth/auth0/django/web-app/webappexample/templates/index.html +16 -0
  36. data/features/auth/auth0/django/web-app/webappexample/urls.py +10 -0
  37. data/features/auth/auth0/django/web-app/webappexample/views.py +52 -0
  38. data/features/auth/auth0/go/backend/go.mod +8 -0
  39. data/features/auth/auth0/go/backend/main.go +60 -0
  40. data/features/auth/auth0/go/backend/middleware/jwt.go +81 -0
  41. data/features/auth/auth0/go/web-app/auth.go +56 -0
  42. data/features/auth/auth0/go/web-app/callback.go +52 -0
  43. data/features/auth/auth0/go/web-app/go.mod +11 -0
  44. data/features/auth/auth0/go/web-app/isAuthenticated.go +20 -0
  45. data/features/auth/auth0/go/web-app/login.go +47 -0
  46. data/features/auth/auth0/go/web-app/logout.go +38 -0
  47. data/features/auth/auth0/go/web-app/main.go +31 -0
  48. data/features/auth/auth0/go/web-app/router.go +44 -0
  49. data/features/auth/auth0/go/web-app/user.go +18 -0
  50. data/features/auth/auth0/ruby-on-rails/backend/Gemfile +1 -0
  51. data/features/auth/auth0/ruby-on-rails/backend/app/controllers/application_controller.rb +5 -0
  52. data/features/auth/auth0/ruby-on-rails/backend/app/controllers/concern/secured.rb +60 -0
  53. data/features/auth/auth0/ruby-on-rails/backend/app/controllers/private_controller.rb +6 -0
  54. data/features/auth/auth0/ruby-on-rails/backend/app/controllers/public-controller.rb +6 -0
  55. data/features/auth/auth0/ruby-on-rails/backend/app/lib/auth0_client.rb +59 -0
  56. data/features/auth/auth0/ruby-on-rails/web-app/Gemfile +2 -0
  57. data/features/auth/auth0/ruby-on-rails/web-app/auth0_controller.rb +41 -0
  58. data/features/auth/auth0/ruby-on-rails/web-app/config/auth0.yml +4 -0
  59. data/features/auth/auth0/ruby-on-rails/web-app/config/initializers/auth0.rb +14 -0
  60. data/features/auth/auth0/ruby-on-rails/web-app/config/routes.rb +6 -0
  61. data/features/auth/auth0/ruby-on-rails/web-app/config/secured.rb +11 -0
  62. data/features/auth/clerk/go/clerk_client.go +28 -0
  63. data/features/auth/clerk/go/go.mod +5 -0
  64. data/features/auth/clerk/go/main.go +82 -0
  65. data/features/auth/clerk/nextjs/typescript/app/layout.tsx +2 -2
  66. data/features/auth/clerk/ruby-on-rails/Gemfile +1 -0
  67. data/features/auth/clerk/ruby-on-rails/app.rb +50 -0
  68. data/features/auth/clerk/ruby-on-rails/config/initializers/clerk.rb +4 -0
  69. data/features/aws/aws.json +5207 -0
  70. data/features/database/database.json +246 -0
  71. data/features/docker/docker.json +108 -0
  72. data/features/features.json +44 -7321
  73. data/features/gitignore/gitignore.json +61 -0
  74. data/features/monitoring/monitoring.json +5 -0
  75. data/features/payment/payment.json +347 -0
  76. data/features/storage/storage.json +371 -0
  77. data/features/testing/jest/angularjs/typescript/tests/angularjs.test.ts +12 -0
  78. data/features/testing/jest/expressjs/javascript/tests/expressjs.test.js +10 -0
  79. data/features/testing/jest/expressjs/typescript/tests/expressjs.test.ts +10 -0
  80. data/features/testing/jest/nestjs/typescript/tests/nestjs.test.ts +10 -0
  81. data/features/testing/jest/nextjs/javascript/tests/nextjs.test.js +10 -0
  82. data/features/testing/jest/nextjs/typescript/tests/nextjs.test.ts +10 -0
  83. data/features/testing/jest/nuxtjs/typescript/tests/nuxtjs.test.ts +9 -0
  84. data/features/testing/jest/reactjs/javascript/tests/reactjs.test.js +10 -0
  85. data/features/testing/jest/reactjs/typescript/tests/reactjs.test.ts +10 -0
  86. data/features/testing/jest/reactjs-expressjs-shadcn/javascript/tests/reactjs.expressjs.shadcn.test.js +16 -0
  87. data/features/testing/jest/reactjs-expressjs-shadcn/typescript/tests/reactjs.expressjs.shadcn.test.ts +16 -0
  88. data/features/testing/jest/reactjs-nestjs-shadcn/typescript/tests/reactjs.nestjs.shadcn.test.ts +14 -0
  89. data/features/testing/jest/remixjs/typescript/tests/remixjs.test.ts +9 -0
  90. data/features/testing/jest/vuejs/javascript/tests/vuejs.test.ts +9 -0
  91. data/features/testing/jest/vuejs/typescript/tests/vuejs.test.ts +9 -0
  92. data/features/testing/testing.json +102 -0
  93. data/features/ui/ui.json +91 -0
  94. metadata +90 -8
  95. data/features/testing/jest/angularjs/tests/angularjs.test.js +0 -12
  96. data/features/testing/jest/expressjs/tests/javascript/expressjs.test.js +0 -12
  97. data/features/testing/jest/expressjs/tests/typescript/expressjs.test.ts +0 -12
  98. data/features/testing/jest/go/tests/go.test.js +0 -12
  99. data/features/testing/jest/nextjs/tests/javascript/nextjs.test.js +0 -12
  100. data/features/testing/jest/nextjs/tests/typescript/nextjs.test.ts +0 -12
@@ -0,0 +1,1150 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+ import boxen from 'boxen';
4
+ import { execSync } from 'child_process';
5
+ import os from 'os';
6
+ import path from 'path';
7
+ import fs from 'fs-extra';
8
+ import { createStandardHelp } from '../utils/helpFormatter.js';
9
+ import { displayCommandBanner } from '../utils/banner.js';
10
+ import { generateEmailTemplate, generateTestEmailTemplate, collectBugReportData, collectFeatureRequestData, collectTemplateRequestData, collectQuestionData, collectImprovementData, collectDocsData, collectCustomMessageData, collectContactInfo, collectQuickFeedback } from '../email-templates/index.js';
11
+ const EMAIL_CATEGORIES = [
12
+ {
13
+ name: 'šŸ› Bug Report',
14
+ value: 'bug',
15
+ description: 'Report a bug or issue with the CLI',
16
+ emoji: 'šŸ›',
17
+ template: 'bug-report'
18
+ },
19
+ {
20
+ name: 'šŸ’” Feature Request',
21
+ value: 'feature',
22
+ description: 'Suggest a new feature or enhancement',
23
+ emoji: 'šŸ’”',
24
+ template: 'feature-request'
25
+ },
26
+ {
27
+ name: 'šŸ“‹ Template Request',
28
+ value: 'template',
29
+ description: 'Request a new project template',
30
+ emoji: 'šŸ“‹',
31
+ template: 'template-request'
32
+ },
33
+ {
34
+ name: 'ā“ General Question',
35
+ value: 'question',
36
+ description: 'Ask a general question about the CLI',
37
+ emoji: 'ā“',
38
+ template: 'question'
39
+ },
40
+ {
41
+ name: 'šŸš€ Improvement Suggestion',
42
+ value: 'improvement',
43
+ description: 'Suggest improvements to existing features',
44
+ emoji: 'šŸš€',
45
+ template: 'improvement'
46
+ },
47
+ {
48
+ name: 'šŸ“– Documentation Issue',
49
+ value: 'docs',
50
+ description: 'Report issues with documentation',
51
+ emoji: 'šŸ“–',
52
+ template: 'docs-issue'
53
+ },
54
+ {
55
+ name: 'āœ‰ļø Custom Message',
56
+ value: 'custom',
57
+ description: 'Send a custom formatted message',
58
+ emoji: 'āœ‰ļø',
59
+ template: 'custom-message'
60
+ }
61
+ ];
62
+ /**
63
+ * Check if Email MCP CLI is available and get version info
64
+ */
65
+ async function checkEmailMcpAvailability() {
66
+ try {
67
+ // First try the global npm package
68
+ try {
69
+ const output = execSync('npx @0xshariq/email-mcp-server --version', {
70
+ stdio: 'pipe',
71
+ encoding: 'utf8',
72
+ timeout: 10000
73
+ });
74
+ const versionMatch = output.match(/Version: ([\d.]+)/);
75
+ const isConfigured = !output.includes('Environment not configured');
76
+ return {
77
+ available: true,
78
+ version: versionMatch ? versionMatch[1] : 'unknown',
79
+ path: 'npx @0xshariq/email-mcp-server',
80
+ configured: isConfigured,
81
+ installationType: 'npx'
82
+ };
83
+ }
84
+ catch (npxError) {
85
+ // Fallback to direct email-cli command if globally installed
86
+ try {
87
+ const output = execSync('email-cli --version', {
88
+ stdio: 'pipe',
89
+ encoding: 'utf8',
90
+ timeout: 10000
91
+ });
92
+ const versionMatch = output.match(/Version: ([\d.]+)/);
93
+ const isConfigured = !output.includes('Environment not configured');
94
+ return {
95
+ available: true,
96
+ version: versionMatch ? versionMatch[1] : 'unknown',
97
+ path: 'email-cli',
98
+ configured: isConfigured,
99
+ installationType: 'global'
100
+ };
101
+ }
102
+ catch (globalError) {
103
+ // Last fallback to local development path
104
+ const emailMcpPath = path.join(os.homedir(), 'desktop', 'shariq-mcp-servers', 'email-mcp-server');
105
+ const emailCliPath = path.join(emailMcpPath, 'email-cli.js');
106
+ if (await fs.pathExists(emailCliPath)) {
107
+ try {
108
+ const output = execSync(`node "${emailCliPath}" --version`, {
109
+ stdio: 'pipe',
110
+ encoding: 'utf8',
111
+ cwd: emailMcpPath,
112
+ timeout: 10000
113
+ });
114
+ const versionMatch = output.match(/Version: ([\d.]+)/);
115
+ const isConfigured = !output.includes('Environment not configured');
116
+ return {
117
+ available: true,
118
+ version: versionMatch ? versionMatch[1] : 'unknown',
119
+ path: emailCliPath,
120
+ configured: isConfigured,
121
+ installationType: 'local'
122
+ };
123
+ }
124
+ catch (localError) {
125
+ // Local version exists but has issues (like missing dependencies)
126
+ return {
127
+ available: true,
128
+ version: 'unknown',
129
+ path: emailCliPath,
130
+ configured: false,
131
+ installationType: 'local'
132
+ };
133
+ }
134
+ }
135
+ }
136
+ }
137
+ return { available: false };
138
+ }
139
+ catch (error) {
140
+ return { available: false };
141
+ }
142
+ }
143
+ /**
144
+ * Get system information for bug reports
145
+ */
146
+ function getSystemInfo() {
147
+ try {
148
+ const nodeVersion = process.version;
149
+ const platform = `${os.platform()} ${os.release()}`;
150
+ const arch = os.arch();
151
+ const cliVersion = process.env.CLI_VERSION || 'unknown';
152
+ const timestamp = new Date().toLocaleString();
153
+ return {
154
+ platform,
155
+ arch,
156
+ nodeVersion,
157
+ cliVersion,
158
+ workingDirectory: process.cwd(),
159
+ timestamp
160
+ };
161
+ }
162
+ catch (error) {
163
+ return {
164
+ platform: 'unknown',
165
+ arch: 'unknown',
166
+ nodeVersion: 'unknown',
167
+ cliVersion: 'unknown',
168
+ workingDirectory: 'unknown',
169
+ timestamp: new Date().toLocaleString()
170
+ };
171
+ }
172
+ }
173
+ /**
174
+ * Configure Email MCP Server with user's email credentials
175
+ */
176
+ async function configureEmailMcp() {
177
+ try {
178
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ”§ Email Configuration Setup') + '\n\n' +
179
+ chalk.white('To send emails, we need to configure your email credentials.') + '\n' +
180
+ chalk.hex('#95afc0')('Your credentials will be stored securely and used only for sending feedback emails.') + '\n\n' +
181
+ chalk.hex('#ffa502')('Supported Email Providers:') + '\n' +
182
+ chalk.hex('#95afc0')('• Gmail (recommended)') + '\n' +
183
+ chalk.hex('#95afc0')('• Outlook/Hotmail') + '\n' +
184
+ chalk.hex('#95afc0')('• Yahoo') + '\n' +
185
+ chalk.hex('#95afc0')('• Custom SMTP servers'), {
186
+ padding: 1,
187
+ margin: 1,
188
+ borderStyle: 'round',
189
+ borderColor: 'cyan'
190
+ }));
191
+ // Collect email configuration
192
+ const emailConfig = await inquirer.prompt([
193
+ {
194
+ type: 'list',
195
+ name: 'provider',
196
+ message: 'Select your email provider:',
197
+ choices: [
198
+ { name: 'šŸ“§ Gmail', value: 'gmail' },
199
+ { name: 'šŸ”· Outlook/Hotmail', value: 'outlook' },
200
+ { name: '🟔 Yahoo', value: 'yahoo' },
201
+ { name: 'āš™ļø Custom SMTP', value: 'custom' }
202
+ ]
203
+ },
204
+ {
205
+ type: 'input',
206
+ name: 'email',
207
+ message: 'Enter your email address:',
208
+ validate: (input) => {
209
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
210
+ return emailRegex.test(input) || 'Please enter a valid email address';
211
+ }
212
+ },
213
+ {
214
+ type: 'password',
215
+ name: 'password',
216
+ message: (answers) => {
217
+ if (answers.provider === 'gmail') {
218
+ return 'Enter your Gmail App Password (not regular password):';
219
+ }
220
+ return 'Enter your email password or app password:';
221
+ },
222
+ validate: (input) => input.length > 0 || 'Password is required'
223
+ }
224
+ ]);
225
+ // Add custom SMTP settings if needed
226
+ let smtpConfig = {};
227
+ if (emailConfig.provider === 'custom') {
228
+ smtpConfig = await inquirer.prompt([
229
+ {
230
+ type: 'input',
231
+ name: 'host',
232
+ message: 'SMTP Host (e.g., smtp.gmail.com):',
233
+ validate: (input) => input.length > 0 || 'SMTP host is required'
234
+ },
235
+ {
236
+ type: 'input',
237
+ name: 'port',
238
+ message: 'SMTP Port (e.g., 587):',
239
+ default: '587',
240
+ validate: (input) => {
241
+ const port = parseInt(input);
242
+ return (port > 0 && port <= 65535) || 'Please enter a valid port number';
243
+ }
244
+ }
245
+ ]);
246
+ }
247
+ // Set provider-specific SMTP settings
248
+ let host, port;
249
+ switch (emailConfig.provider) {
250
+ case 'gmail':
251
+ host = 'smtp.gmail.com';
252
+ port = '587';
253
+ break;
254
+ case 'outlook':
255
+ host = 'smtp.live.com';
256
+ port = '587';
257
+ break;
258
+ case 'yahoo':
259
+ host = 'smtp.mail.yahoo.com';
260
+ port = '587';
261
+ break;
262
+ case 'custom':
263
+ host = smtpConfig.host;
264
+ port = smtpConfig.port;
265
+ break;
266
+ default:
267
+ host = 'smtp.gmail.com';
268
+ port = '587';
269
+ }
270
+ // Show provider-specific setup instructions
271
+ if (emailConfig.provider === 'gmail') {
272
+ console.log(boxen(chalk.hex('#ffa502')('šŸ“§ Gmail Setup Instructions') + '\n\n' +
273
+ chalk.hex('#95afc0')('For Gmail, you need to use an App Password:') + '\n' +
274
+ chalk.hex('#95afc0')('1. Enable 2-Factor Authentication in your Google Account') + '\n' +
275
+ chalk.hex('#95afc0')('2. Go to Google Account Settings > Security') + '\n' +
276
+ chalk.hex('#95afc0')('3. Under "2-Step Verification", click "App passwords"') + '\n' +
277
+ chalk.hex('#95afc0')('4. Generate a new app password for "Mail"') + '\n' +
278
+ chalk.hex('#95afc0')('5. Use that 16-character password above') + '\n\n' +
279
+ chalk.hex('#00d2d3')('šŸ’” Regular Gmail passwords will NOT work!'), {
280
+ padding: 1,
281
+ margin: 1,
282
+ borderStyle: 'round',
283
+ borderColor: 'yellow'
284
+ }));
285
+ }
286
+ // Create .env content
287
+ const envContent = `# Email MCP Server Configuration
288
+ # Generated by Package Installer CLI
289
+ EMAIL_HOST=${host}
290
+ EMAIL_PORT=${port}
291
+ EMAIL_USER=${emailConfig.email}
292
+ EMAIL_PASS=${emailConfig.password}
293
+ EMAIL_SECURE=false
294
+ EMAIL_TLS=true
295
+ `;
296
+ // Find Email MCP Server directory and create .env file
297
+ const mcpInfo = await checkEmailMcpAvailability();
298
+ let envFilePath;
299
+ if (mcpInfo.installationType === 'local' && mcpInfo.path) {
300
+ // Local installation - create .env in the project directory
301
+ const projectDir = path.dirname(mcpInfo.path);
302
+ envFilePath = path.join(projectDir, '.env');
303
+ }
304
+ else {
305
+ // Global or npx installation - create .env in home directory
306
+ const configDir = path.join(os.homedir(), '.email-mcp-server');
307
+ await fs.ensureDir(configDir);
308
+ envFilePath = path.join(configDir, '.env');
309
+ }
310
+ // Write .env file
311
+ await fs.writeFile(envFilePath, envContent, 'utf8');
312
+ console.log(boxen(chalk.green('āœ… Email Configuration Saved!') + '\n\n' +
313
+ chalk.white('Email credentials have been configured successfully.') + '\n' +
314
+ chalk.hex('#95afc0')(`Configuration saved to: ${chalk.cyan(envFilePath)}`) + '\n\n' +
315
+ chalk.hex('#00d2d3')('You can now send feedback emails using the CLI!') + '\n' +
316
+ chalk.hex('#95afc0')('Test the setup with: ') + chalk.cyan('pi email --test'), {
317
+ padding: 1,
318
+ margin: 1,
319
+ borderStyle: 'round',
320
+ borderColor: 'green'
321
+ }));
322
+ return true;
323
+ }
324
+ catch (error) {
325
+ console.error(chalk.red(`āŒ Failed to configure email: ${error.message}`));
326
+ return false;
327
+ }
328
+ }
329
+ /**
330
+ * Check if email is configured and prompt for setup if needed
331
+ */
332
+ async function ensureEmailConfigured() {
333
+ const mcpInfo = await checkEmailMcpAvailability();
334
+ if (!mcpInfo.available) {
335
+ console.log(chalk.yellow('āš ļø Email MCP Server not installed. Please install it first:'));
336
+ console.log(chalk.cyan('npm install -g @0xshariq/email-mcp-server'));
337
+ return false;
338
+ }
339
+ if (!mcpInfo.configured) {
340
+ console.log(chalk.yellow('āš ļø Email not configured. Setting up email configuration...'));
341
+ return await configureEmailMcp();
342
+ }
343
+ return true;
344
+ }
345
+ /**
346
+ * Get the configured email from .env file
347
+ */
348
+ async function getConfiguredEmail() {
349
+ try {
350
+ const mcpInfo = await checkEmailMcpAvailability();
351
+ let envFilePath;
352
+ if (mcpInfo.installationType === 'local' && mcpInfo.path) {
353
+ const projectDir = path.dirname(mcpInfo.path);
354
+ envFilePath = path.join(projectDir, '.env');
355
+ }
356
+ else {
357
+ const configDir = path.join(os.homedir(), '.email-mcp-server');
358
+ envFilePath = path.join(configDir, '.env');
359
+ }
360
+ if (await fs.pathExists(envFilePath)) {
361
+ const envContent = await fs.readFile(envFilePath, 'utf8');
362
+ const emailMatch = envContent.match(/EMAIL_USER=(.+)/);
363
+ return emailMatch ? emailMatch[1].trim() : null;
364
+ }
365
+ return null;
366
+ }
367
+ catch (error) {
368
+ return null;
369
+ }
370
+ }
371
+ /**
372
+ * Collect sender email option from user
373
+ */
374
+ async function collectSenderEmailOption() {
375
+ const configuredEmail = await getConfiguredEmail();
376
+ if (!configuredEmail) {
377
+ // No configured email, must use custom
378
+ console.log(chalk.yellow('āš ļø No configured email found. Please provide your email credentials:'));
379
+ const customCredentials = await inquirer.prompt([
380
+ {
381
+ type: 'input',
382
+ name: 'email',
383
+ message: 'Enter your email address:',
384
+ validate: (input) => {
385
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
386
+ return emailRegex.test(input) || 'Please enter a valid email address';
387
+ }
388
+ },
389
+ {
390
+ type: 'password',
391
+ name: 'password',
392
+ message: 'Enter your email password or app password:',
393
+ validate: (input) => input.length > 0 || 'Password is required'
394
+ }
395
+ ]);
396
+ return {
397
+ useConfigured: false,
398
+ customEmail: customCredentials.email,
399
+ customPassword: customCredentials.password
400
+ };
401
+ }
402
+ // Show options for configured vs custom email
403
+ const { emailOption } = await inquirer.prompt([
404
+ {
405
+ type: 'list',
406
+ name: 'emailOption',
407
+ message: 'Which email would you like to use for sending?',
408
+ choices: [
409
+ {
410
+ name: `šŸ“§ Use configured email: ${chalk.cyan(configuredEmail)}`,
411
+ value: 'configured'
412
+ },
413
+ {
414
+ name: 'āœ‰ļø Use a different email (temporary)',
415
+ value: 'custom'
416
+ }
417
+ ]
418
+ }
419
+ ]);
420
+ if (emailOption === 'configured') {
421
+ return { useConfigured: true };
422
+ }
423
+ // Collect custom email credentials
424
+ const customCredentials = await inquirer.prompt([
425
+ {
426
+ type: 'input',
427
+ name: 'email',
428
+ message: 'Enter your email address:',
429
+ validate: (input) => {
430
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
431
+ return emailRegex.test(input) || 'Please enter a valid email address';
432
+ }
433
+ },
434
+ {
435
+ type: 'password',
436
+ name: 'password',
437
+ message: 'Enter your email password or app password:',
438
+ validate: (input) => input.length > 0 || 'Password is required'
439
+ },
440
+ {
441
+ type: 'list',
442
+ name: 'provider',
443
+ message: 'Select your email provider:',
444
+ choices: [
445
+ { name: 'šŸ“§ Gmail', value: 'gmail' },
446
+ { name: 'šŸ”· Outlook/Hotmail', value: 'outlook' },
447
+ { name: '🟔 Yahoo', value: 'yahoo' },
448
+ { name: 'āš™ļø Custom SMTP', value: 'custom' }
449
+ ]
450
+ }
451
+ ]);
452
+ return {
453
+ useConfigured: false,
454
+ customEmail: customCredentials.email,
455
+ customPassword: customCredentials.password,
456
+ customProvider: customCredentials.provider
457
+ };
458
+ }
459
+ /**
460
+ * Send email using Email MCP CLI with proper command structure
461
+ * Supports both plain text and HTML emails
462
+ * Uses user's configured or custom email to send to khanshariq92213@gmail.com
463
+ */
464
+ async function sendEmailViaMcp(subject, body, htmlBody, customCredentials) {
465
+ let tempEnvFile = '';
466
+ try {
467
+ const mcpInfo = await checkEmailMcpAvailability();
468
+ if (!mcpInfo.available) {
469
+ throw new Error('Email MCP Server not available');
470
+ }
471
+ // Hardcoded recipient email
472
+ const to = 'khanshariq92213@gmail.com';
473
+ // Handle custom credentials if provided
474
+ if (customCredentials) {
475
+ // Create temporary .env file with custom credentials
476
+ const tempDir = os.tmpdir();
477
+ tempEnvFile = path.join(tempDir, `temp-email-config-${Date.now()}.env`);
478
+ // Determine SMTP settings based on provider
479
+ let host, port;
480
+ switch (customCredentials.provider) {
481
+ case 'gmail':
482
+ host = 'smtp.gmail.com';
483
+ port = '587';
484
+ break;
485
+ case 'outlook':
486
+ host = 'smtp.live.com';
487
+ port = '587';
488
+ break;
489
+ case 'yahoo':
490
+ host = 'smtp.mail.yahoo.com';
491
+ port = '587';
492
+ break;
493
+ default:
494
+ host = 'smtp.gmail.com'; // Default to Gmail
495
+ port = '587';
496
+ }
497
+ const tempEnvContent = `EMAIL_HOST=${host}
498
+ EMAIL_PORT=${port}
499
+ EMAIL_USER=${customCredentials.email}
500
+ EMAIL_PASS=${customCredentials.password}
501
+ EMAIL_SECURE=false
502
+ EMAIL_TLS=true
503
+ `;
504
+ await fs.writeFile(tempEnvFile, tempEnvContent);
505
+ // Set environment variable to use the temporary config
506
+ process.env.EMAIL_CONFIG_PATH = tempEnvFile;
507
+ }
508
+ // Create temporary files for HTML content if provided
509
+ let tempHtmlFile = '';
510
+ let command = '';
511
+ let options = {
512
+ stdio: 'pipe',
513
+ timeout: 45000,
514
+ encoding: 'utf8'
515
+ };
516
+ if (htmlBody) {
517
+ // Try HTML email with ehtml command (if supported) or fall back to esend
518
+ const tempDir = os.tmpdir();
519
+ tempHtmlFile = path.join(tempDir, `email-${Date.now()}.html`);
520
+ try {
521
+ await fs.writeFile(tempHtmlFile, htmlBody);
522
+ // Try HTML command first
523
+ const htmlArgs = [to, subject, tempHtmlFile];
524
+ const escapedHtmlArgs = htmlArgs.map(arg => `"${arg.replace(/"/g, '\\"')}"`).join(' ');
525
+ switch (mcpInfo.installationType) {
526
+ case 'npx':
527
+ command = `npx @0xshariq/email-mcp-server ehtml ${escapedHtmlArgs}`;
528
+ break;
529
+ case 'global':
530
+ command = `email-cli ehtml ${escapedHtmlArgs}`;
531
+ break;
532
+ case 'local':
533
+ command = `node "${mcpInfo.path}" ehtml ${escapedHtmlArgs}`;
534
+ options.cwd = path.dirname(mcpInfo.path);
535
+ break;
536
+ }
537
+ try {
538
+ const output = execSync(command, options);
539
+ return true;
540
+ }
541
+ catch (htmlError) {
542
+ // If HTML command fails, fall back to regular esend
543
+ console.log(chalk.yellow('ā„¹ļø HTML email not supported, sending as rich text...'));
544
+ }
545
+ }
546
+ catch (fileError) {
547
+ console.log(chalk.yellow('ā„¹ļø Could not create HTML file, sending as plain text...'));
548
+ }
549
+ finally {
550
+ // Clean up temp file
551
+ if (tempHtmlFile && await fs.pathExists(tempHtmlFile)) {
552
+ await fs.remove(tempHtmlFile);
553
+ }
554
+ }
555
+ }
556
+ // Fall back to regular text email
557
+ const args = [to, subject, body];
558
+ const escapedArgs = args.map(arg => `"${arg.replace(/"/g, '\\"')}"`).join(' ');
559
+ // Use the appropriate command based on installation type
560
+ switch (mcpInfo.installationType) {
561
+ case 'npx':
562
+ command = `npx @0xshariq/email-mcp-server esend ${escapedArgs}`;
563
+ break;
564
+ case 'global':
565
+ command = `email-cli esend ${escapedArgs}`;
566
+ break;
567
+ case 'local':
568
+ command = `node "${mcpInfo.path}" esend ${escapedArgs}`;
569
+ options.cwd = path.dirname(mcpInfo.path);
570
+ break;
571
+ default:
572
+ throw new Error('Unknown installation type');
573
+ }
574
+ const output = execSync(command, options);
575
+ return true;
576
+ }
577
+ catch (error) {
578
+ // Better error handling with specific error messages
579
+ if (error.message?.includes('timeout')) {
580
+ console.error(chalk.red('āŒ Email sending timed out. Check your internet connection.'));
581
+ }
582
+ else if (error.message?.includes('Environment not configured')) {
583
+ console.error(chalk.red('āŒ Email MCP Server not configured. Run: pi email --setup'));
584
+ }
585
+ else if (error.message?.includes('ERR_MODULE_NOT_FOUND')) {
586
+ console.error(chalk.red('āŒ Email MCP Server has missing dependencies.'));
587
+ console.error(chalk.yellow('šŸ’” Try: npm install -g @0xshariq/email-mcp-server (for global use)'));
588
+ }
589
+ else if (error.message?.includes('Cannot find module')) {
590
+ console.error(chalk.red('āŒ Email MCP Server dependencies missing.'));
591
+ if (error.message?.includes('local')) {
592
+ console.error(chalk.yellow('šŸ’” For local development: cd to email-mcp-server && npm install'));
593
+ }
594
+ else {
595
+ console.error(chalk.yellow('šŸ’” For global use: npm install -g @0xshariq/email-mcp-server'));
596
+ }
597
+ }
598
+ else {
599
+ console.error(chalk.red(`āŒ Failed to send email: ${error.message || error}`));
600
+ }
601
+ return false;
602
+ }
603
+ finally {
604
+ // Clean up temporary files
605
+ try {
606
+ if (tempEnvFile && await fs.pathExists(tempEnvFile)) {
607
+ await fs.remove(tempEnvFile);
608
+ }
609
+ if (process.env.EMAIL_CONFIG_PATH) {
610
+ delete process.env.EMAIL_CONFIG_PATH;
611
+ }
612
+ }
613
+ catch (cleanupError) {
614
+ // Ignore cleanup errors
615
+ }
616
+ }
617
+ }
618
+ /**
619
+ * Show available email categories
620
+ */
621
+ async function showEmailCategories() {
622
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ“‹ Available Email Categories') + '\n\n' +
623
+ EMAIL_CATEGORIES.map(cat => `${cat.emoji} ${chalk.bold.cyan(cat.value)} - ${chalk.white(cat.name.replace(cat.emoji + ' ', ''))}\n ${chalk.gray(cat.description)}`).join('\n\n') + '\n\n' +
624
+ chalk.hex('#95afc0')('Usage: ') + chalk.hex('#00d2d3')('pi email <category>') + '\n' +
625
+ chalk.hex('#95afc0')('Example: ') + chalk.hex('#00d2d3')('pi email bug'), {
626
+ padding: 1,
627
+ margin: 1,
628
+ borderStyle: 'round',
629
+ borderColor: 'cyan'
630
+ }));
631
+ }
632
+ /**
633
+ * Show installation instructions
634
+ */
635
+ async function showInstallInstructions() {
636
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ“¦ Email MCP Server Installation') + '\n\n' +
637
+ chalk.hex('#ffa502')('Option 1: Global Installation (Recommended)') + '\n' +
638
+ chalk.hex('#00d2d3')('npm install -g @0xshariq/email-mcp-server') + '\n\n' +
639
+ chalk.hex('#ffa502')('Option 2: One-time Usage') + '\n' +
640
+ chalk.hex('#00d2d3')('npx @0xshariq/email-mcp-server') + '\n\n' +
641
+ chalk.hex('#ffa502')('Option 3: Local Development') + '\n' +
642
+ chalk.hex('#00d2d3')('git clone <repo> && npm install') + '\n\n' +
643
+ chalk.hex('#95afc0')('After installation, configure your email credentials.') + '\n' +
644
+ chalk.hex('#95afc0')('Then use: ') + chalk.hex('#00d2d3')('pi email --setup'), {
645
+ padding: 1,
646
+ margin: 1,
647
+ borderStyle: 'round',
648
+ borderColor: 'blue'
649
+ }));
650
+ }
651
+ /**
652
+ * Show setup instructions for email configuration
653
+ */
654
+ async function showSetupInstructions() {
655
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ”§ Email Configuration Guide') + '\n\n' +
656
+ chalk.white('To send feedback emails, configure your email credentials using:') + '\n\n' +
657
+ chalk.hex('#ffa502')('Interactive Setup (Recommended):') + '\n' +
658
+ chalk.hex('#00d2d3')('pi email --setup') + '\n\n' +
659
+ chalk.hex('#95afc0')('This will guide you through:') + '\n' +
660
+ chalk.hex('#95afc0')('• Selecting your email provider (Gmail, Outlook, Yahoo, Custom)') + '\n' +
661
+ chalk.hex('#95afc0')('• Entering your email address') + '\n' +
662
+ chalk.hex('#95afc0')('• Setting up your app password') + '\n' +
663
+ chalk.hex('#95afc0')('• Automatically configuring SMTP settings') + '\n\n' +
664
+ chalk.hex('#ffa502')('Supported Providers:') + '\n' +
665
+ chalk.hex('#95afc0')('šŸ“§ Gmail (with App Password)') + '\n' +
666
+ chalk.hex('#95afc0')('šŸ”· Outlook/Hotmail') + '\n' +
667
+ chalk.hex('#95afc0')('🟔 Yahoo Mail') + '\n' +
668
+ chalk.hex('#95afc0')('āš™ļø Custom SMTP servers') + '\n\n' +
669
+ chalk.hex('#95afc0')('šŸ’” Your credentials are stored securely and used only for sending feedback'), {
670
+ padding: 1,
671
+ margin: 1,
672
+ borderStyle: 'round',
673
+ borderColor: 'yellow'
674
+ }));
675
+ }
676
+ /**
677
+ * Show email system status
678
+ */
679
+ async function showEmailStatus() {
680
+ console.log(chalk.hex('#00d2d3')('šŸ” Checking Email System Status...\n'));
681
+ const mcpInfo = await checkEmailMcpAvailability();
682
+ const statusColor = mcpInfo.available ? (mcpInfo.configured ? 'green' : 'yellow') : 'red';
683
+ const statusIcon = mcpInfo.available ? (mcpInfo.configured ? 'āœ…' : 'āš ļø') : 'āŒ';
684
+ const statusText = mcpInfo.available ?
685
+ (mcpInfo.configured ? 'Ready' : 'Available (Not Configured)') :
686
+ 'Not Found';
687
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ“Š Email System Status') + '\n\n' +
688
+ `${statusIcon} Email MCP Server: ${chalk[statusColor](statusText)}` + '\n' +
689
+ (mcpInfo.version ? `${chalk.blue('ā„¹ļø')} Version: ${chalk.cyan(mcpInfo.version)}` + '\n' : '') +
690
+ (mcpInfo.installationType ? `${chalk.blue('ā„¹ļø')} Type: ${chalk.cyan(mcpInfo.installationType)}` + '\n' : '') +
691
+ (mcpInfo.path ? `${chalk.blue('ā„¹ļø')} Path: ${chalk.gray(mcpInfo.path)}` + '\n' : '') +
692
+ `${chalk.blue('ā„¹ļø')} Configuration: ${mcpInfo.configured ? chalk.green('āœ… Configured') : chalk.yellow('āš ļø Not Configured')}` + '\n' +
693
+ `${chalk.blue('ā„¹ļø')} Target Email: ${chalk.cyan('khanshariq92213@gmail.com')}` + '\n' +
694
+ `${chalk.blue('ā„¹ļø')} Package: ${chalk.cyan('@0xshariq/email-mcp-server')}` + '\n\n' +
695
+ chalk.hex('#ffa502')('Available Commands:') + '\n' +
696
+ chalk.hex('#95afc0')('• esend - Send basic email (up to 3 recipients)') + '\n' +
697
+ chalk.hex('#95afc0')('• eattach - Send email with attachments') + '\n' +
698
+ chalk.hex('#95afc0')('• ebulk - Send bulk emails to many recipients') + '\n' +
699
+ chalk.hex('#95afc0')('• eread - Read recent emails') + '\n' +
700
+ chalk.hex('#95afc0')('• esearch - Search emails with filters') + '\n\n' +
701
+ (mcpInfo.available ?
702
+ (mcpInfo.configured ?
703
+ chalk.green('šŸŽ‰ Ready to send emails! Use: pi email <category>') :
704
+ chalk.yellow('āš ļø Configuration required: pi email --setup')) :
705
+ chalk.yellow('āš ļø Install required: npm install -g @0xshariq/email-mcp-server')) + '\n\n' +
706
+ (mcpInfo.installationType === 'local' && !mcpInfo.configured ?
707
+ chalk.hex('#ffa502')('šŸ’” Local Development Setup:') + '\n' +
708
+ chalk.hex('#95afc0')('• For testing: Use global install (npm install -g @0xshariq/email-mcp-server)') + '\n' +
709
+ chalk.hex('#95afc0')('• For development: Configure .env in email-mcp-server directory') + '\n' +
710
+ chalk.hex('#95afc0')('• See: pi email --setup for configuration details') : ''), {
711
+ padding: 1,
712
+ margin: 1,
713
+ borderStyle: 'round',
714
+ borderColor: statusColor
715
+ }));
716
+ }
717
+ /**
718
+ * Test email connection
719
+ */
720
+ async function testEmailConnection() {
721
+ console.log(chalk.hex('#00d2d3')('🧪 Testing Email Connection...\n'));
722
+ const mcpInfo = await checkEmailMcpAvailability();
723
+ if (!mcpInfo.available) {
724
+ console.log(boxen(chalk.red('āŒ Email MCP Server Not Available') + '\n\n' +
725
+ chalk.yellow('Cannot test connection without Email MCP Server.') + '\n' +
726
+ chalk.hex('#95afc0')('Install it first: npm install -g @0xshariq/email-mcp-server'), {
727
+ padding: 1,
728
+ margin: 1,
729
+ borderStyle: 'round',
730
+ borderColor: 'red'
731
+ }));
732
+ return;
733
+ }
734
+ // Collect sender email option for test
735
+ console.log(chalk.hex('#95afc0')('šŸ“§ Email sending configuration for test:'));
736
+ const senderOption = await collectSenderEmailOption();
737
+ console.log(chalk.hex('#9c88ff')('šŸ“§ Sending test email...'));
738
+ const systemInfo = getSystemInfo();
739
+ const testEmail = generateTestEmailTemplate(systemInfo);
740
+ let customCredentials;
741
+ if (!senderOption.useConfigured && senderOption.customEmail) {
742
+ customCredentials = {
743
+ email: senderOption.customEmail,
744
+ password: senderOption.customPassword,
745
+ provider: senderOption.customProvider || 'gmail'
746
+ };
747
+ }
748
+ const success = await sendEmailViaMcp(testEmail.subject, testEmail.plainBody, testEmail.htmlBody, customCredentials);
749
+ if (success) {
750
+ console.log(boxen(chalk.green('āœ… Test Email Sent Successfully!') + '\n\n' +
751
+ chalk.white('A test email has been sent to khanshariq92213@gmail.com') + '\n' +
752
+ chalk.hex('#95afc0')('The email functionality is working correctly.') + '\n\n' +
753
+ chalk.hex('#00d2d3')('You can now use: pi email <category> to send feedback'), {
754
+ padding: 1,
755
+ margin: 1,
756
+ borderStyle: 'round',
757
+ borderColor: 'green'
758
+ }));
759
+ }
760
+ else {
761
+ console.log(boxen(chalk.red('āŒ Test Email Failed') + '\n\n' +
762
+ chalk.yellow('There was an issue sending the test email.') + '\n' +
763
+ chalk.hex('#95afc0')('Check your email configuration and try again.') + '\n\n' +
764
+ chalk.cyan('Troubleshooting:') + '\n' +
765
+ chalk.hex('#95afc0')('• Run: pi email --setup (for configuration help)') + '\n' +
766
+ chalk.hex('#95afc0')('• Check email credentials and SMTP settings') + '\n' +
767
+ chalk.hex('#95afc0')('• Verify internet connection'), {
768
+ padding: 1,
769
+ margin: 1,
770
+ borderStyle: 'round',
771
+ borderColor: 'red'
772
+ }));
773
+ }
774
+ }
775
+ /**
776
+ * Show development information for local Email MCP Server
777
+ */
778
+ async function showDevelopmentInfo() {
779
+ const mcpInfo = await checkEmailMcpAvailability();
780
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ› ļø Email MCP Server Development Info') + '\n\n' +
781
+ chalk.hex('#ffa502')('Local Development Status:') + '\n' +
782
+ `${mcpInfo.available && mcpInfo.installationType === 'local' ? chalk.green('āœ…') : chalk.red('āŒ')} Local Email MCP Server: ${mcpInfo.available && mcpInfo.installationType === 'local' ? 'Found' : 'Not Found'}` + '\n' +
783
+ (mcpInfo.path && mcpInfo.installationType === 'local' ? `${chalk.blue('ā„¹ļø')} Path: ${chalk.gray(mcpInfo.path)}` + '\n' : '') +
784
+ `${chalk.blue('ā„¹ļø')} Configuration: ${mcpInfo.configured ? chalk.green('āœ… Configured') : chalk.yellow('āš ļø Not Configured')}` + '\n\n' +
785
+ chalk.hex('#ffa502')('Development Setup Options:') + '\n' +
786
+ chalk.hex('#95afc0')('1. Use Global Install (Recommended for testing):') + '\n' +
787
+ chalk.hex('#00d2d3')(' npm install -g @0xshariq/email-mcp-server') + '\n' +
788
+ chalk.hex('#95afc0')(' # Configure once globally, works everywhere') + '\n\n' +
789
+ chalk.hex('#95afc0')('2. Configure Local Development:') + '\n' +
790
+ chalk.hex('#00d2d3')(' cd ~/desktop/shariq-mcp-servers/email-mcp-server') + '\n' +
791
+ chalk.hex('#00d2d3')(' npm install # Install dependencies') + '\n' +
792
+ chalk.hex('#00d2d3')(' cp .env.example .env # Create .env file') + '\n' +
793
+ chalk.hex('#00d2d3')(' # Edit .env with your email settings') + '\n\n' +
794
+ chalk.hex('#95afc0')('3. One-time Usage (No setup needed):') + '\n' +
795
+ chalk.hex('#00d2d3')(' npx @0xshariq/email-mcp-server esend "email" "subject" "body"') + '\n\n' +
796
+ chalk.hex('#ffa502')('Environment Variables (.env):') + '\n' +
797
+ chalk.hex('#95afc0')('EMAIL_HOST=smtp.gmail.com') + '\n' +
798
+ chalk.hex('#95afc0')('EMAIL_PORT=587') + '\n' +
799
+ chalk.hex('#95afc0')('EMAIL_USER=your-email@gmail.com') + '\n' +
800
+ chalk.hex('#95afc0')('EMAIL_PASS=your-app-password') + '\n\n' +
801
+ chalk.hex('#ffa502')('Current Issue:') + '\n' +
802
+ (mcpInfo.installationType === 'local' && !mcpInfo.configured ?
803
+ chalk.yellow('āš ļø Local version found but not configured or has dependency issues') :
804
+ chalk.green('āœ… No issues detected')) + '\n\n' +
805
+ chalk.hex('#ffa502')('Recommended Action:') + '\n' +
806
+ (mcpInfo.installationType === 'local' && !mcpInfo.configured ?
807
+ chalk.hex('#00d2d3')('npm install -g @0xshariq/email-mcp-server # Use global version for testing') :
808
+ chalk.hex('#00d2d3')('pi email --status # Check current status')), {
809
+ padding: 1,
810
+ margin: 1,
811
+ borderStyle: 'round',
812
+ borderColor: 'blue'
813
+ }));
814
+ }
815
+ /**
816
+ * Show all available Email MCP Server commands
817
+ */
818
+ async function showEmailCommands() {
819
+ const mcpInfo = await checkEmailMcpAvailability();
820
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ“§ Email MCP Server Commands') + '\n\n' +
821
+ chalk.hex('#ffa502')('Basic Email Operations:') + '\n' +
822
+ chalk.hex('#95afc0')('• esend <to> <subject> <body> - Send email (max 3 recipients)') + '\n' +
823
+ chalk.hex('#95afc0')('• eread [count] - Read recent emails') + '\n' +
824
+ chalk.hex('#95afc0')('• eget <id> - Get specific email by ID') + '\n' +
825
+ chalk.hex('#95afc0')('• edelete <id> - Delete an email') + '\n' +
826
+ chalk.hex('#95afc0')('• emarkread <id> - Mark email as read/unread') + '\n\n' +
827
+ chalk.hex('#ffa502')('Advanced Email Operations:') + '\n' +
828
+ chalk.hex('#95afc0')('• eattach <to> <subject> <body> <file> - Send with attachment') + '\n' +
829
+ chalk.hex('#95afc0')('• esearch <query> - Search emails with filters') + '\n' +
830
+ chalk.hex('#95afc0')('• eforward <id> <to> - Forward an email') + '\n' +
831
+ chalk.hex('#95afc0')('• ereply <id> <body> - Reply to an email') + '\n' +
832
+ chalk.hex('#95afc0')('• estats - Get email statistics') + '\n' +
833
+ chalk.hex('#95afc0')('• edraft <to> <subject> <body> - Create email draft') + '\n' +
834
+ chalk.hex('#95afc0')('• eschedule <to> <subject> <body> <time> - Schedule email') + '\n' +
835
+ chalk.hex('#95afc0')('• ebulk <file> <subject> <body> - Send bulk emails') + '\n\n' +
836
+ chalk.hex('#ffa502')('Contact Management:') + '\n' +
837
+ chalk.hex('#95afc0')('• cadd <name> <email> - Add new contact') + '\n' +
838
+ chalk.hex('#95afc0')('• clist - List all contacts') + '\n' +
839
+ chalk.hex('#95afc0')('• csearch <query> - Search contacts') + '\n' +
840
+ chalk.hex('#95afc0')('• cgroup <group> - Get contacts by group') + '\n' +
841
+ chalk.hex('#95afc0')('• cupdate <id> <field> <value> - Update contact') + '\n' +
842
+ chalk.hex('#95afc0')('• cdelete <id> - Delete contact') + '\n\n' +
843
+ `${mcpInfo.available ? chalk.green('āœ…') : chalk.red('āŒ')} Status: ${mcpInfo.available ? 'Available' : 'Not Installed'}` + '\n' +
844
+ (mcpInfo.version ? `${chalk.blue('ā„¹ļø')} Version: ${mcpInfo.version}` + '\n' : '') +
845
+ `${chalk.blue('ā„¹ļø')} Package: @0xshariq/email-mcp-server` + '\n\n' +
846
+ chalk.hex('#00d2d3')('Usage Examples:') + '\n' +
847
+ chalk.gray('esend "user@example.com" "Hello" "Test message"') + '\n' +
848
+ chalk.gray('eattach "user@example.com" "Report" "See attached" "./file.pdf"') + '\n' +
849
+ chalk.gray('ebulk "recipients.txt" "Newsletter" "Monthly update"'), {
850
+ padding: 1,
851
+ margin: 1,
852
+ borderStyle: 'round',
853
+ borderColor: mcpInfo.available ? 'cyan' : 'yellow'
854
+ }));
855
+ }
856
+ /**
857
+ * Show help for email command
858
+ */
859
+ export async function showEmailHelp() {
860
+ const helpConfig = {
861
+ commandName: 'Email',
862
+ emoji: 'šŸ“§',
863
+ description: 'Contact the developer with feedback, bug reports, feature requests, and questions.\nDirect communication channel to improve Package Installer CLI.',
864
+ usage: [
865
+ 'email',
866
+ 'email [category]'
867
+ ],
868
+ options: [
869
+ { flag: '-h, --help', description: 'Show this help message' },
870
+ { flag: '-l, --list', description: 'List all available email categories' },
871
+ { flag: '--install', description: 'Show Email MCP Server installation instructions' },
872
+ { flag: '--setup', description: 'Configure your email credentials for sending feedback' },
873
+ { flag: '--status', description: 'Check email system status and availability' },
874
+ { flag: '--test', description: 'Send a test email to verify functionality' },
875
+ { flag: '--commands', description: 'Show all available Email MCP Server commands' },
876
+ { flag: '--dev', description: 'Show development setup information and troubleshooting' },
877
+ { flag: '--quick', description: 'Quick feedback mode (minimal prompts)' }
878
+ ],
879
+ examples: [
880
+ { command: 'email', description: 'Interactive feedback form with category selection' },
881
+ { command: 'email bug', description: 'Quick bug report form' },
882
+ { command: 'email feature', description: 'Feature request form' },
883
+ { command: 'email template', description: 'Request a new project template' },
884
+ { command: 'email --list', description: 'Show all available categories' },
885
+ { command: 'email --status', description: 'Check if email system is ready' },
886
+ { command: 'email --test', description: 'Send test email to verify setup' },
887
+ { command: 'email --install', description: 'Show installation instructions' },
888
+ { command: 'email --setup', description: 'Configure your email credentials interactively' },
889
+ { command: 'email --commands', description: 'Show all Email MCP Server commands' },
890
+ { command: 'email --dev', description: 'Development setup and troubleshooting' }
891
+ ],
892
+ additionalSections: [
893
+ {
894
+ title: 'Available Categories',
895
+ items: EMAIL_CATEGORIES.map(cat => `${cat.emoji} ${cat.value} - ${cat.description}`)
896
+ },
897
+ {
898
+ title: 'What You Can Contact About',
899
+ items: [
900
+ 'Bug reports with detailed reproduction steps',
901
+ 'Feature requests and enhancement ideas',
902
+ 'New project template suggestions',
903
+ 'Documentation improvements',
904
+ 'General questions about CLI usage',
905
+ 'Performance or usability improvements'
906
+ ]
907
+ },
908
+ {
909
+ title: 'Email Setup (Required for sending)',
910
+ items: [
911
+ 'Install: npm install -g @0xshariq/email-mcp-server',
912
+ 'Configure: pi email --setup (interactive setup)',
913
+ 'Supports Gmail, Outlook, Yahoo, and custom SMTP',
914
+ 'Your credentials are stored securely for sending feedback'
915
+ ]
916
+ }
917
+ ],
918
+ tips: [
919
+ 'Be specific and detailed in your reports',
920
+ 'Include system information for bug reports',
921
+ 'Provide use cases for feature requests',
922
+ 'Your contact info is optional but helpful for follow-up'
923
+ ]
924
+ };
925
+ createStandardHelp(helpConfig);
926
+ }
927
+ /**
928
+ * Main email command handler
929
+ */
930
+ export async function emailCommand(category, options = {}) {
931
+ try {
932
+ // Handle help flag
933
+ if (options.help) {
934
+ await showEmailHelp();
935
+ return;
936
+ }
937
+ // Handle list categories flag
938
+ if (options.list) {
939
+ await showEmailCategories();
940
+ return;
941
+ }
942
+ // Handle install flag
943
+ if (options.install) {
944
+ await showInstallInstructions();
945
+ return;
946
+ }
947
+ // Handle setup flag
948
+ if (options.setup) {
949
+ await configureEmailMcp();
950
+ return;
951
+ }
952
+ // Handle status flag
953
+ if (options.status) {
954
+ await showEmailStatus();
955
+ return;
956
+ }
957
+ // Handle test flag
958
+ if (options.test) {
959
+ const isConfigured = await ensureEmailConfigured();
960
+ if (isConfigured) {
961
+ await testEmailConnection();
962
+ }
963
+ return;
964
+ }
965
+ // Handle commands flag (show all available email commands)
966
+ if (options.commands) {
967
+ await showEmailCommands();
968
+ return;
969
+ }
970
+ // Handle dev flag (development mode info)
971
+ if (options.dev) {
972
+ await showDevelopmentInfo();
973
+ return;
974
+ }
975
+ // Display command banner
976
+ displayCommandBanner('Email', 'Contact the developer with feedback, suggestions, and questions');
977
+ // Ensure email is configured before proceeding
978
+ const isConfigured = await ensureEmailConfigured();
979
+ if (!isConfigured) {
980
+ console.log(boxen(chalk.yellow('āš ļø Email Configuration Required') + '\n\n' +
981
+ chalk.white('To send feedback emails, you need to configure your email credentials.') + '\n\n' +
982
+ chalk.cyan('šŸ“¦ Quick Setup Steps:') + '\n' +
983
+ chalk.hex('#95afc0')('1. Install: npm install -g @0xshariq/email-mcp-server') + '\n' +
984
+ chalk.hex('#95afc0')('2. Configure: pi email --setup') + '\n' +
985
+ chalk.hex('#95afc0')('3. Send feedback: pi email <category>') + '\n\n' +
986
+ chalk.cyan('šŸ“ž Alternative Contact Methods:') + '\n' +
987
+ chalk.hex('#95afc0')('šŸ“§ Direct Email: khanshariq92213@gmail.com') + '\n' +
988
+ chalk.hex('#95afc0')('šŸ™ GitHub Issues: Create an issue on the repository'), {
989
+ padding: 1,
990
+ margin: 1,
991
+ borderStyle: 'round',
992
+ borderColor: 'yellow'
993
+ }));
994
+ console.log('\n' + chalk.hex('#00d2d3')('šŸ’» Quick Setup Command:'));
995
+ console.log(chalk.gray('pi email --setup'));
996
+ return;
997
+ }
998
+ // Show welcome message
999
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ“§ Contact Developer') + '\n\n' +
1000
+ chalk.white('I appreciate your feedback and contributions to improve Package Installer CLI!') + '\n\n' +
1001
+ chalk.hex('#95afc0')('• Bug reports help fix issues quickly') + '\n' +
1002
+ chalk.hex('#95afc0')('• Feature requests shape future development') + '\n' +
1003
+ chalk.hex('#95afc0')('• Template requests expand project options') + '\n' +
1004
+ chalk.hex('#95afc0')('• Questions help improve documentation'), {
1005
+ padding: 1,
1006
+ margin: 1,
1007
+ borderStyle: 'round',
1008
+ borderColor: 'cyan'
1009
+ }));
1010
+ let selectedCategory = category;
1011
+ // If no category specified, show selection
1012
+ if (!selectedCategory) {
1013
+ const { category: chosenCategory } = await inquirer.prompt([
1014
+ {
1015
+ type: 'list',
1016
+ name: 'category',
1017
+ message: chalk.hex('#9c88ff')('What would you like to contact me about?'),
1018
+ choices: EMAIL_CATEGORIES.map(cat => ({
1019
+ name: `${cat.name} - ${chalk.gray(cat.description)}`,
1020
+ value: cat.value,
1021
+ short: cat.value
1022
+ })),
1023
+ pageSize: 10
1024
+ }
1025
+ ]);
1026
+ selectedCategory = chosenCategory;
1027
+ }
1028
+ // Validate category
1029
+ const categoryConfig = EMAIL_CATEGORIES.find(cat => cat.value === selectedCategory);
1030
+ if (!categoryConfig) {
1031
+ console.log(chalk.red(`āŒ Invalid category: ${selectedCategory}`));
1032
+ console.log(chalk.yellow(`šŸ’” Available categories: ${EMAIL_CATEGORIES.map(c => c.value).join(', ')}`));
1033
+ return;
1034
+ }
1035
+ console.log(`\n${categoryConfig.emoji} ${chalk.bold.cyan('Collecting information for:')} ${chalk.white(categoryConfig.name)}`);
1036
+ // Collect category-specific information
1037
+ let categoryData;
1038
+ if (options.quick) {
1039
+ // Quick mode - minimal prompts
1040
+ console.log(chalk.hex('#ffa502')('šŸš€ Quick Mode - Minimal prompts for fast feedback'));
1041
+ categoryData = await collectQuickFeedback(selectedCategory);
1042
+ }
1043
+ else {
1044
+ // Full mode - detailed prompts
1045
+ switch (selectedCategory) {
1046
+ case 'bug':
1047
+ categoryData = await collectBugReportData();
1048
+ break;
1049
+ case 'feature':
1050
+ categoryData = await collectFeatureRequestData();
1051
+ break;
1052
+ case 'template':
1053
+ categoryData = await collectTemplateRequestData();
1054
+ break;
1055
+ case 'question':
1056
+ categoryData = await collectQuestionData();
1057
+ break;
1058
+ case 'improvement':
1059
+ categoryData = await collectImprovementData();
1060
+ break;
1061
+ case 'docs':
1062
+ categoryData = await collectDocsData();
1063
+ break;
1064
+ case 'custom':
1065
+ categoryData = await collectCustomMessageData();
1066
+ break;
1067
+ default:
1068
+ categoryData = await collectQuestionData(); // Fallback
1069
+ }
1070
+ }
1071
+ // Collect optional contact information
1072
+ console.log(chalk.hex('#95afc0')('\nšŸ“ž Contact information (optional, for follow-up):'));
1073
+ const contactData = await collectContactInfo();
1074
+ // Collect sender email option
1075
+ console.log(chalk.hex('#95afc0')('\nšŸ“§ Email sending configuration:'));
1076
+ const senderOption = await collectSenderEmailOption();
1077
+ // Merge all data
1078
+ const allData = { ...categoryData, ...contactData };
1079
+ // Generate email content (both HTML and plain text)
1080
+ const systemInfo = getSystemInfo();
1081
+ const emailTemplate = generateEmailTemplate(selectedCategory, allData, systemInfo);
1082
+ const { subject, htmlBody, plainBody } = emailTemplate;
1083
+ // Show preview
1084
+ console.log(boxen(chalk.hex('#00d2d3')('šŸ“§ Email Preview') + '\n\n' +
1085
+ chalk.gray('To: khanshariq92213@gmail.com') + '\n' +
1086
+ chalk.gray(`Subject: ${subject}`) + '\n' +
1087
+ chalk.gray('Format: HTML + Plain Text Fallback') + '\n\n' +
1088
+ chalk.white(plainBody.substring(0, 300) + (plainBody.length > 300 ? '...' : '')), {
1089
+ padding: 1,
1090
+ margin: 1,
1091
+ borderStyle: 'round',
1092
+ borderColor: 'blue'
1093
+ }));
1094
+ // Confirm sending
1095
+ const { confirmSend } = await inquirer.prompt([
1096
+ {
1097
+ type: 'confirm',
1098
+ name: 'confirmSend',
1099
+ message: 'Send this beautifully formatted email?',
1100
+ default: true
1101
+ }
1102
+ ]);
1103
+ if (!confirmSend) {
1104
+ console.log(chalk.yellow('šŸ“§ Email cancelled. Your feedback is still valuable!'));
1105
+ return;
1106
+ }
1107
+ // Send email (try HTML first, fall back to plain text)
1108
+ console.log(chalk.hex('#9c88ff')('šŸ“§ Sending formatted email...'));
1109
+ let customCredentials;
1110
+ if (!senderOption.useConfigured && senderOption.customEmail) {
1111
+ customCredentials = {
1112
+ email: senderOption.customEmail,
1113
+ password: senderOption.customPassword,
1114
+ provider: senderOption.customProvider || 'gmail'
1115
+ };
1116
+ }
1117
+ const success = await sendEmailViaMcp(subject, plainBody, htmlBody, customCredentials);
1118
+ if (success) {
1119
+ console.log(boxen(chalk.green('āœ… Email sent successfully!') + '\n\n' +
1120
+ chalk.white('Thank you for your feedback!') + '\n' +
1121
+ chalk.hex('#95afc0')('I\'ll review your message and get back to you if needed.') + '\n\n' +
1122
+ chalk.hex('#00d2d3')('Your contribution helps make Package Installer CLI better! šŸš€'), {
1123
+ padding: 1,
1124
+ margin: 1,
1125
+ borderStyle: 'round',
1126
+ borderColor: 'green'
1127
+ }));
1128
+ }
1129
+ else {
1130
+ console.log(boxen(chalk.red('āŒ Failed to send email') + '\n\n' +
1131
+ chalk.yellow('Troubleshooting:') + '\n' +
1132
+ chalk.hex('#95afc0')('• Ensure @0xshariq/email-mcp-server is installed') + '\n' +
1133
+ chalk.hex('#95afc0')('• Check your email configuration') + '\n' +
1134
+ chalk.hex('#95afc0')('• Verify internet connection') + '\n\n' +
1135
+ chalk.yellow('Alternative contact methods:') + '\n' +
1136
+ chalk.hex('#95afc0')('šŸ“§ Direct email: khanshariq92213@gmail.com') + '\n' +
1137
+ chalk.hex('#95afc0')('šŸ™ GitHub: Create an issue on the repository') + '\n\n' +
1138
+ chalk.gray('Subject: ' + subject) + '\n' +
1139
+ chalk.gray('Please copy the message content for manual sending.'), {
1140
+ padding: 1,
1141
+ margin: 1,
1142
+ borderStyle: 'round',
1143
+ borderColor: 'red'
1144
+ }));
1145
+ }
1146
+ }
1147
+ catch (error) {
1148
+ console.error(chalk.red(`āŒ Error in email command: ${error.message}`));
1149
+ }
1150
+ }