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