@marlinjai/email-mcp 1.4.0 → 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.
@@ -4,7 +4,101 @@
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
+ if (!input.isTTY || typeof input.setRawMode !== "function") {
60
+ const rl = getInterface();
61
+ rl.question("").then(resolve);
62
+ return;
63
+ }
64
+ let value = "";
65
+ input.setRawMode(true);
66
+ input.resume();
67
+ input.setEncoding("utf8");
68
+ const cleanup = () => {
69
+ input.setRawMode(false);
70
+ input.pause();
71
+ input.removeListener("data", onData);
72
+ };
73
+ const onData = (char) => {
74
+ switch (char) {
75
+ case "\n":
76
+ case "\r":
77
+ case CTRL_D:
78
+ cleanup();
79
+ output.write("\n");
80
+ resolve(value);
81
+ break;
82
+ case CTRL_C:
83
+ cleanup();
84
+ output.write("\n");
85
+ process.exit(130);
86
+ break;
87
+ case BACKSPACE:
88
+ case "\b":
89
+ if (value.length > 0) {
90
+ value = value.slice(0, -1);
91
+ output.write("\b \b");
92
+ }
93
+ break;
94
+ default:
95
+ value += char;
96
+ output.write("*");
97
+ }
98
+ };
99
+ input.on("data", onData);
100
+ });
101
+ }
8
102
 
9
103
  // src/auth/credential-store.ts
10
104
  import crypto from "node:crypto";
@@ -2527,15 +2621,7 @@ async function testAndSave(creds) {
2527
2621
  }
2528
2622
  }
2529
2623
  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;
2624
+ return askText("Account name:", defaultName);
2539
2625
  }
2540
2626
  async function setupGmail() {
2541
2627
  console.log("\n--- Gmail Setup ---");
@@ -2627,30 +2713,25 @@ async function setupICloud() {
2627
2713
  console.log(
2628
2714
  "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
2715
  );
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
- ]);
2716
+ const email = await askValidated(
2717
+ "iCloud email address:",
2718
+ void 0,
2719
+ (v) => v.includes("@") || "Enter a valid email address"
2720
+ );
2721
+ let password = await askPassword("App-specific password:");
2722
+ while (password.trim().length === 0) {
2723
+ console.log(" Password is required");
2724
+ password = await askPassword("App-specific password:");
2725
+ }
2645
2726
  const name = await promptAccountName("iCloud");
2646
2727
  const id = crypto3.randomUUID();
2647
2728
  const creds = {
2648
2729
  id,
2649
2730
  name,
2650
2731
  provider: ProviderType.ICloud,
2651
- email: answers.email.trim(),
2732
+ email: email.trim(),
2652
2733
  password: {
2653
- password: answers.password,
2734
+ password,
2654
2735
  host: "imap.mail.me.com",
2655
2736
  port: 993,
2656
2737
  tls: true,
@@ -2662,72 +2743,26 @@ async function setupICloud() {
2662
2743
  }
2663
2744
  async function setupIMAP() {
2664
2745
  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
- ]);
2746
+ const portValidator = (v) => {
2747
+ const n = parseInt(v, 10);
2748
+ return n > 0 && n <= 65535 || "Enter a valid port number (1-65535)";
2749
+ };
2750
+ const email = await askValidated("Email address:", void 0, (v) => v.includes("@") || "Enter a valid email address");
2751
+ const host = await askValidated("IMAP host:", void 0, (v) => v.trim().length > 0 || "Host is required");
2752
+ const portStr = await askValidated("IMAP port:", "993", portValidator);
2753
+ const tls = await askConfirm("Use TLS?", true);
2754
+ let password = await askPassword("Password:");
2755
+ while (password.trim().length === 0) {
2756
+ console.log(" Password is required");
2757
+ password = await askPassword("Password:");
2758
+ }
2759
+ const configureSmtp = await askConfirm("Configure SMTP (for sending)?", false);
2708
2760
  let smtpHost;
2709
2761
  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);
2762
+ if (configureSmtp) {
2763
+ smtpHost = await askValidated("SMTP host:", void 0, (v) => v.trim().length > 0 || "SMTP host is required");
2764
+ const smtpPortStr = await askValidated("SMTP port:", "587", portValidator);
2765
+ smtpPort = parseInt(smtpPortStr, 10);
2731
2766
  }
2732
2767
  const name = await promptAccountName("IMAP");
2733
2768
  const id = crypto3.randomUUID();
@@ -2735,12 +2770,12 @@ async function setupIMAP() {
2735
2770
  id,
2736
2771
  name,
2737
2772
  provider: ProviderType.IMAP,
2738
- email: answers.email.trim(),
2773
+ email: email.trim(),
2739
2774
  password: {
2740
- password: answers.password,
2741
- host: answers.host.trim(),
2742
- port: parseInt(answers.port, 10),
2743
- tls: answers.tls,
2775
+ password,
2776
+ host: host.trim(),
2777
+ port: parseInt(portStr, 10),
2778
+ tls,
2744
2779
  smtpHost,
2745
2780
  smtpPort
2746
2781
  }
@@ -2770,14 +2805,7 @@ async function removeAccount(id) {
2770
2805
  console.error(`Account not found: ${id}`);
2771
2806
  process.exit(1);
2772
2807
  }
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
- ]);
2808
+ const confirm = await askConfirm(`Remove account "${acct.name}" (${acct.email})?`, false);
2781
2809
  if (confirm) {
2782
2810
  await store.remove(id);
2783
2811
  console.log(`Account "${acct.name}" removed.`);
@@ -2804,18 +2832,11 @@ async function main() {
2804
2832
  console.log("@marlinjai/email-mcp Account Setup\n");
2805
2833
  let addMore = true;
2806
2834
  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
- }
2835
+ const provider = await askChoice("Select provider:", [
2836
+ { name: "Gmail", value: "gmail" },
2837
+ { name: "Outlook", value: "outlook" },
2838
+ { name: "iCloud", value: "icloud" },
2839
+ { name: "Other IMAP", value: "imap" }
2819
2840
  ]);
2820
2841
  switch (provider) {
2821
2842
  case ProviderType.Gmail:
@@ -2834,15 +2855,7 @@ async function main() {
2834
2855
  console.error(`Unknown provider: ${provider}`);
2835
2856
  process.exit(1);
2836
2857
  }
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;
2858
+ addMore = await askConfirm("Would you like to add another email account?", false);
2846
2859
  }
2847
2860
  console.log("\nSetup complete! You can now use the email tools in Claude Code.");
2848
2861
  }
@@ -2850,5 +2863,5 @@ main().catch((err) => {
2850
2863
  console.error(`
2851
2864
  Setup failed: ${err.message}`);
2852
2865
  process.exit(1);
2853
- });
2866
+ }).finally(closePrompts);
2854
2867
  //# sourceMappingURL=wizard.js.map