@marlinjai/email-mcp 1.4.0 → 1.4.2

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.
@@ -4,7 +4,107 @@
4
4
  // src/setup/wizard.ts
5
5
  import crypto3 from "node:crypto";
6
6
  import { exec } from "node:child_process";
7
- import inquirer from "inquirer";
7
+
8
+ // src/setup/prompts.ts
9
+ import readline from "node:readline/promises";
10
+ import { stdin as input, stdout as output } from "node:process";
11
+ var CTRL_C = "";
12
+ var CTRL_D = "";
13
+ var BACKSPACE = "\x7F";
14
+ var sharedInterface = null;
15
+ function getInterface() {
16
+ if (!sharedInterface) {
17
+ sharedInterface = readline.createInterface({ input, output });
18
+ }
19
+ return sharedInterface;
20
+ }
21
+ function closePrompts() {
22
+ sharedInterface?.close();
23
+ sharedInterface = null;
24
+ }
25
+ async function askText(message, defaultValue) {
26
+ const rl = getInterface();
27
+ const suffix = defaultValue ? ` (${defaultValue})` : "";
28
+ const answer = await rl.question(`${message}${suffix} `);
29
+ const trimmed = answer.trim();
30
+ return trimmed.length > 0 ? trimmed : defaultValue ?? "";
31
+ }
32
+ async function askValidated(message, defaultValue, validate) {
33
+ for (; ; ) {
34
+ const value = await askText(message, defaultValue);
35
+ const result = validate(value);
36
+ if (result === true) return value;
37
+ console.log(` ${result}`);
38
+ }
39
+ }
40
+ async function askConfirm(message, defaultValue = false) {
41
+ const suffix = defaultValue ? "Y/n" : "y/N";
42
+ const answer = await askText(`${message} (${suffix})`);
43
+ if (!answer) return defaultValue;
44
+ return /^y/i.test(answer);
45
+ }
46
+ async function askChoice(message, choices) {
47
+ console.log(message);
48
+ choices.forEach((c, i) => console.log(` ${i + 1}) ${c.name}`));
49
+ for (; ; ) {
50
+ const answer = await askText("Enter a number:");
51
+ const idx = parseInt(answer, 10) - 1;
52
+ if (idx >= 0 && idx < choices.length) return choices[idx].value;
53
+ console.log(` Please enter a number between 1 and ${choices.length}.`);
54
+ }
55
+ }
56
+ function askPassword(message) {
57
+ return new Promise((resolve) => {
58
+ output.write(`${message} `);
59
+ closePrompts();
60
+ let rawModeOk = true;
61
+ try {
62
+ input.setRawMode(true);
63
+ } catch {
64
+ rawModeOk = false;
65
+ }
66
+ if (!rawModeOk) {
67
+ const rl = getInterface();
68
+ rl.question("").then(resolve);
69
+ return;
70
+ }
71
+ let value = "";
72
+ input.resume();
73
+ input.setEncoding("utf8");
74
+ const cleanup = () => {
75
+ input.setRawMode(false);
76
+ input.pause();
77
+ input.removeListener("data", onData);
78
+ };
79
+ const onData = (char) => {
80
+ switch (char) {
81
+ case "\n":
82
+ case "\r":
83
+ case CTRL_D:
84
+ cleanup();
85
+ output.write("\n");
86
+ resolve(value);
87
+ break;
88
+ case CTRL_C:
89
+ cleanup();
90
+ output.write("\n");
91
+ process.exit(130);
92
+ break;
93
+ case BACKSPACE:
94
+ case "\b":
95
+ if (value.length > 0) {
96
+ value = value.slice(0, -1);
97
+ output.write("\b \b");
98
+ }
99
+ break;
100
+ default:
101
+ value += char;
102
+ output.write("*");
103
+ }
104
+ };
105
+ input.on("data", onData);
106
+ });
107
+ }
8
108
 
9
109
  // src/auth/credential-store.ts
10
110
  import crypto from "node:crypto";
@@ -2527,15 +2627,7 @@ async function testAndSave(creds) {
2527
2627
  }
2528
2628
  }
2529
2629
  async function promptAccountName(defaultName) {
2530
- const { name } = await inquirer.prompt([
2531
- {
2532
- type: "input",
2533
- name: "name",
2534
- message: "Account name:",
2535
- default: defaultName
2536
- }
2537
- ]);
2538
- return name;
2630
+ return askText("Account name:", defaultName);
2539
2631
  }
2540
2632
  async function setupGmail() {
2541
2633
  console.log("\n--- Gmail Setup ---");
@@ -2627,30 +2719,25 @@ async function setupICloud() {
2627
2719
  console.log(
2628
2720
  "You need an app-specific password for iCloud Mail.\nGenerate one at https://appleid.apple.com/account/manage\n(Sign In & Security > App-Specific Passwords)\n"
2629
2721
  );
2630
- const answers = await inquirer.prompt([
2631
- {
2632
- type: "input",
2633
- name: "email",
2634
- message: "iCloud email address:",
2635
- validate: (v) => v.includes("@") || "Enter a valid email address"
2636
- },
2637
- {
2638
- type: "password",
2639
- name: "password",
2640
- message: "App-specific password:",
2641
- mask: "*",
2642
- validate: (v) => v.trim().length > 0 || "Password is required"
2643
- }
2644
- ]);
2722
+ const email = await askValidated(
2723
+ "iCloud email address:",
2724
+ void 0,
2725
+ (v) => v.includes("@") || "Enter a valid email address"
2726
+ );
2727
+ let password = await askPassword("App-specific password:");
2728
+ while (password.trim().length === 0) {
2729
+ console.log(" Password is required");
2730
+ password = await askPassword("App-specific password:");
2731
+ }
2645
2732
  const name = await promptAccountName("iCloud");
2646
2733
  const id = crypto3.randomUUID();
2647
2734
  const creds = {
2648
2735
  id,
2649
2736
  name,
2650
2737
  provider: ProviderType.ICloud,
2651
- email: answers.email.trim(),
2738
+ email: email.trim(),
2652
2739
  password: {
2653
- password: answers.password,
2740
+ password,
2654
2741
  host: "imap.mail.me.com",
2655
2742
  port: 993,
2656
2743
  tls: true,
@@ -2662,72 +2749,26 @@ async function setupICloud() {
2662
2749
  }
2663
2750
  async function setupIMAP() {
2664
2751
  console.log("\n--- Generic IMAP Setup ---\n");
2665
- const answers = await inquirer.prompt([
2666
- {
2667
- type: "input",
2668
- name: "email",
2669
- message: "Email address:",
2670
- validate: (v) => v.includes("@") || "Enter a valid email address"
2671
- },
2672
- {
2673
- type: "input",
2674
- name: "host",
2675
- message: "IMAP host:",
2676
- validate: (v) => v.trim().length > 0 || "Host is required"
2677
- },
2678
- {
2679
- type: "input",
2680
- name: "port",
2681
- message: "IMAP port:",
2682
- default: "993",
2683
- validate: (v) => {
2684
- const n = parseInt(v, 10);
2685
- return n > 0 && n <= 65535 || "Enter a valid port number (1-65535)";
2686
- }
2687
- },
2688
- {
2689
- type: "confirm",
2690
- name: "tls",
2691
- message: "Use TLS?",
2692
- default: true
2693
- },
2694
- {
2695
- type: "password",
2696
- name: "password",
2697
- message: "Password:",
2698
- mask: "*",
2699
- validate: (v) => v.trim().length > 0 || "Password is required"
2700
- },
2701
- {
2702
- type: "confirm",
2703
- name: "configureSmtp",
2704
- message: "Configure SMTP (for sending)?",
2705
- default: false
2706
- }
2707
- ]);
2752
+ const portValidator = (v) => {
2753
+ const n = parseInt(v, 10);
2754
+ return n > 0 && n <= 65535 || "Enter a valid port number (1-65535)";
2755
+ };
2756
+ const email = await askValidated("Email address:", void 0, (v) => v.includes("@") || "Enter a valid email address");
2757
+ const host = await askValidated("IMAP host:", void 0, (v) => v.trim().length > 0 || "Host is required");
2758
+ const portStr = await askValidated("IMAP port:", "993", portValidator);
2759
+ const tls = await askConfirm("Use TLS?", true);
2760
+ let password = await askPassword("Password:");
2761
+ while (password.trim().length === 0) {
2762
+ console.log(" Password is required");
2763
+ password = await askPassword("Password:");
2764
+ }
2765
+ const configureSmtp = await askConfirm("Configure SMTP (for sending)?", false);
2708
2766
  let smtpHost;
2709
2767
  let smtpPort;
2710
- if (answers.configureSmtp) {
2711
- const smtp = await inquirer.prompt([
2712
- {
2713
- type: "input",
2714
- name: "smtpHost",
2715
- message: "SMTP host:",
2716
- validate: (v) => v.trim().length > 0 || "SMTP host is required"
2717
- },
2718
- {
2719
- type: "input",
2720
- name: "smtpPort",
2721
- message: "SMTP port:",
2722
- default: "587",
2723
- validate: (v) => {
2724
- const n = parseInt(v, 10);
2725
- return n > 0 && n <= 65535 || "Enter a valid port number (1-65535)";
2726
- }
2727
- }
2728
- ]);
2729
- smtpHost = smtp.smtpHost.trim();
2730
- smtpPort = parseInt(smtp.smtpPort, 10);
2768
+ if (configureSmtp) {
2769
+ smtpHost = await askValidated("SMTP host:", void 0, (v) => v.trim().length > 0 || "SMTP host is required");
2770
+ const smtpPortStr = await askValidated("SMTP port:", "587", portValidator);
2771
+ smtpPort = parseInt(smtpPortStr, 10);
2731
2772
  }
2732
2773
  const name = await promptAccountName("IMAP");
2733
2774
  const id = crypto3.randomUUID();
@@ -2735,12 +2776,12 @@ async function setupIMAP() {
2735
2776
  id,
2736
2777
  name,
2737
2778
  provider: ProviderType.IMAP,
2738
- email: answers.email.trim(),
2779
+ email: email.trim(),
2739
2780
  password: {
2740
- password: answers.password,
2741
- host: answers.host.trim(),
2742
- port: parseInt(answers.port, 10),
2743
- tls: answers.tls,
2781
+ password,
2782
+ host: host.trim(),
2783
+ port: parseInt(portStr, 10),
2784
+ tls,
2744
2785
  smtpHost,
2745
2786
  smtpPort
2746
2787
  }
@@ -2770,14 +2811,7 @@ async function removeAccount(id) {
2770
2811
  console.error(`Account not found: ${id}`);
2771
2812
  process.exit(1);
2772
2813
  }
2773
- const { confirm } = await inquirer.prompt([
2774
- {
2775
- type: "confirm",
2776
- name: "confirm",
2777
- message: `Remove account "${acct.name}" (${acct.email})?`,
2778
- default: false
2779
- }
2780
- ]);
2814
+ const confirm = await askConfirm(`Remove account "${acct.name}" (${acct.email})?`, false);
2781
2815
  if (confirm) {
2782
2816
  await store.remove(id);
2783
2817
  console.log(`Account "${acct.name}" removed.`);
@@ -2804,18 +2838,11 @@ async function main() {
2804
2838
  console.log("@marlinjai/email-mcp Account Setup\n");
2805
2839
  let addMore = true;
2806
2840
  while (addMore) {
2807
- const { provider } = await inquirer.prompt([
2808
- {
2809
- type: "rawlist",
2810
- name: "provider",
2811
- message: "Select provider:",
2812
- choices: [
2813
- { name: "Gmail", value: "gmail" },
2814
- { name: "Outlook", value: "outlook" },
2815
- { name: "iCloud", value: "icloud" },
2816
- { name: "Other IMAP", value: "imap" }
2817
- ]
2818
- }
2841
+ const provider = await askChoice("Select provider:", [
2842
+ { name: "Gmail", value: "gmail" },
2843
+ { name: "Outlook", value: "outlook" },
2844
+ { name: "iCloud", value: "icloud" },
2845
+ { name: "Other IMAP", value: "imap" }
2819
2846
  ]);
2820
2847
  switch (provider) {
2821
2848
  case ProviderType.Gmail:
@@ -2834,15 +2861,7 @@ async function main() {
2834
2861
  console.error(`Unknown provider: ${provider}`);
2835
2862
  process.exit(1);
2836
2863
  }
2837
- const { another } = await inquirer.prompt([
2838
- {
2839
- type: "confirm",
2840
- name: "another",
2841
- message: "Would you like to add another email account?",
2842
- default: false
2843
- }
2844
- ]);
2845
- addMore = another;
2864
+ addMore = await askConfirm("Would you like to add another email account?", false);
2846
2865
  }
2847
2866
  console.log("\nSetup complete! You can now use the email tools in Claude Code.");
2848
2867
  }
@@ -2850,5 +2869,8 @@ main().catch((err) => {
2850
2869
  console.error(`
2851
2870
  Setup failed: ${err.message}`);
2852
2871
  process.exit(1);
2872
+ }).finally(() => {
2873
+ closePrompts();
2874
+ process.exit(0);
2853
2875
  });
2854
2876
  //# sourceMappingURL=wizard.js.map