@marlinjai/email-mcp 1.7.0 → 1.7.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.
- package/README.md +2 -0
- package/dist/index.js +34 -17
- package/dist/index.js.map +3 -3
- package/dist/setup/wizard.js +32 -15
- package/dist/setup/wizard.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -7710,15 +7710,17 @@ var init_auth = __esm({
|
|
|
7710
7710
|
getAuthUrl(redirectUri, scopeMode) {
|
|
7711
7711
|
const codeVerifier = crypto2.randomBytes(32).toString("base64url");
|
|
7712
7712
|
const codeChallenge = crypto2.createHash("sha256").update(codeVerifier).digest("base64url");
|
|
7713
|
+
const state = crypto2.randomBytes(16).toString("base64url");
|
|
7713
7714
|
this.oauth2Client = new OAuth2Client2(this.clientId, this.clientSecret, redirectUri);
|
|
7714
7715
|
const url2 = this.oauth2Client.generateAuthUrl({
|
|
7715
7716
|
access_type: "offline",
|
|
7716
7717
|
scope: GMAIL_SCOPES[resolveScopeMode(scopeMode)],
|
|
7717
7718
|
prompt: "consent",
|
|
7718
7719
|
code_challenge: codeChallenge,
|
|
7719
|
-
code_challenge_method: "S256"
|
|
7720
|
+
code_challenge_method: "S256",
|
|
7721
|
+
state
|
|
7720
7722
|
});
|
|
7721
|
-
return { url: url2, codeVerifier };
|
|
7723
|
+
return { url: url2, codeVerifier, state };
|
|
7722
7724
|
}
|
|
7723
7725
|
async exchangeCode(code, codeVerifier) {
|
|
7724
7726
|
const { tokens } = await this.oauth2Client.getToken({ code, codeVerifier });
|
|
@@ -8369,6 +8371,7 @@ var init_adapter2 = __esm({
|
|
|
8369
8371
|
});
|
|
8370
8372
|
|
|
8371
8373
|
// src/providers/outlook/auth.ts
|
|
8374
|
+
import crypto3 from "node:crypto";
|
|
8372
8375
|
import fs2 from "node:fs";
|
|
8373
8376
|
import path2 from "node:path";
|
|
8374
8377
|
import os2 from "node:os";
|
|
@@ -8423,13 +8426,15 @@ var init_auth2 = __esm({
|
|
|
8423
8426
|
}
|
|
8424
8427
|
async getAuthUrl(redirectUri) {
|
|
8425
8428
|
const { verifier, challenge } = await this.cryptoProvider.generatePkceCodes();
|
|
8429
|
+
const state = crypto3.randomBytes(16).toString("base64url");
|
|
8426
8430
|
const url2 = await this.pca.getAuthCodeUrl({
|
|
8427
8431
|
scopes: _OutlookAuth.SCOPES,
|
|
8428
8432
|
redirectUri,
|
|
8429
8433
|
codeChallenge: challenge,
|
|
8430
|
-
codeChallengeMethod: "S256"
|
|
8434
|
+
codeChallengeMethod: "S256",
|
|
8435
|
+
state
|
|
8431
8436
|
});
|
|
8432
|
-
return { url: url2, codeVerifier: verifier };
|
|
8437
|
+
return { url: url2, codeVerifier: verifier, state };
|
|
8433
8438
|
}
|
|
8434
8439
|
async exchangeCode(code, codeVerifier, redirectUri) {
|
|
8435
8440
|
const result = await this.pca.acquireTokenByCode({
|
|
@@ -9660,6 +9665,7 @@ var init_oauth_server = __esm({
|
|
|
9660
9665
|
rejectCode = null;
|
|
9661
9666
|
timeoutMs;
|
|
9662
9667
|
timeoutHandle = null;
|
|
9668
|
+
expectedState = null;
|
|
9663
9669
|
constructor(timeoutMs = 12e4) {
|
|
9664
9670
|
this.timeoutMs = timeoutMs;
|
|
9665
9671
|
}
|
|
@@ -9670,7 +9676,12 @@ var init_oauth_server = __esm({
|
|
|
9670
9676
|
if (url2.pathname === "/callback" || url2.pathname === "/") {
|
|
9671
9677
|
const code = url2.searchParams.get("code");
|
|
9672
9678
|
const error48 = url2.searchParams.get("error");
|
|
9673
|
-
|
|
9679
|
+
const state = url2.searchParams.get("state");
|
|
9680
|
+
if (code && this.expectedState !== null && state !== this.expectedState) {
|
|
9681
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
9682
|
+
res.end(ERROR_HTML);
|
|
9683
|
+
this.rejectCode?.(new Error("OAuth error: state mismatch, callback did not come from the authorization request we started"));
|
|
9684
|
+
} else if (code) {
|
|
9674
9685
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
9675
9686
|
res.end(SUCCESS_HTML);
|
|
9676
9687
|
this.resolveCode?.(code);
|
|
@@ -9695,7 +9706,13 @@ var init_oauth_server = __esm({
|
|
|
9695
9706
|
this.server.on("error", reject);
|
|
9696
9707
|
});
|
|
9697
9708
|
}
|
|
9698
|
-
|
|
9709
|
+
/**
|
|
9710
|
+
* Resolve with the authorization code once the browser is redirected back.
|
|
9711
|
+
* Pass the `state` that was put into the authorization URL: callbacks whose
|
|
9712
|
+
* state does not match are rejected instead of resolved (CSRF protection).
|
|
9713
|
+
*/
|
|
9714
|
+
waitForCode(expectedState) {
|
|
9715
|
+
this.expectedState = expectedState ?? null;
|
|
9699
9716
|
return new Promise((resolve, reject) => {
|
|
9700
9717
|
this.resolveCode = (code) => {
|
|
9701
9718
|
if (this.timeoutHandle) clearTimeout(this.timeoutHandle);
|
|
@@ -9727,7 +9744,7 @@ var init_oauth_server = __esm({
|
|
|
9727
9744
|
|
|
9728
9745
|
// src/setup/wizard.ts
|
|
9729
9746
|
var wizard_exports = {};
|
|
9730
|
-
import
|
|
9747
|
+
import crypto5 from "node:crypto";
|
|
9731
9748
|
import { exec } from "node:child_process";
|
|
9732
9749
|
function openBrowser(url2) {
|
|
9733
9750
|
const platform = process.platform;
|
|
@@ -9794,7 +9811,7 @@ async function setupGmail(scopeModeFlag) {
|
|
|
9794
9811
|
const port = await server.start();
|
|
9795
9812
|
const redirectUri = `http://localhost:${port}/callback`;
|
|
9796
9813
|
const gmailAuth = new GmailAuth(GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, redirectUri);
|
|
9797
|
-
const { url: url2, codeVerifier } = gmailAuth.getAuthUrl(redirectUri, scopeMode);
|
|
9814
|
+
const { url: url2, codeVerifier, state } = gmailAuth.getAuthUrl(redirectUri, scopeMode);
|
|
9798
9815
|
console.log("\nOpening browser for Google authorization...");
|
|
9799
9816
|
console.log(`If the browser does not open, visit:
|
|
9800
9817
|
${url2}
|
|
@@ -9802,7 +9819,7 @@ ${url2}
|
|
|
9802
9819
|
openBrowser(url2);
|
|
9803
9820
|
let code;
|
|
9804
9821
|
try {
|
|
9805
|
-
code = await server.waitForCode();
|
|
9822
|
+
code = await server.waitForCode(state);
|
|
9806
9823
|
} catch (err) {
|
|
9807
9824
|
server.shutdown();
|
|
9808
9825
|
throw new Error(`OAuth flow failed: ${err.message}`);
|
|
@@ -9818,7 +9835,7 @@ ${url2}
|
|
|
9818
9835
|
if (!email3) throw new Error("Could not retrieve Gmail address from profile");
|
|
9819
9836
|
console.log(`Authenticated as ${email3}`);
|
|
9820
9837
|
const name = await promptAccountName("Gmail");
|
|
9821
|
-
const id =
|
|
9838
|
+
const id = crypto5.randomUUID();
|
|
9822
9839
|
const creds = {
|
|
9823
9840
|
id,
|
|
9824
9841
|
name,
|
|
@@ -9835,7 +9852,7 @@ async function setupOutlook() {
|
|
|
9835
9852
|
const port = await server.start();
|
|
9836
9853
|
const redirectUri = `http://localhost:${port}`;
|
|
9837
9854
|
const outlookAuth = new OutlookAuth(OUTLOOK_CLIENT_ID);
|
|
9838
|
-
const { url: url2, codeVerifier } = await outlookAuth.getAuthUrl(redirectUri);
|
|
9855
|
+
const { url: url2, codeVerifier, state } = await outlookAuth.getAuthUrl(redirectUri);
|
|
9839
9856
|
console.log("\nOpening browser for Microsoft authorization...");
|
|
9840
9857
|
console.log(`If the browser does not open, visit:
|
|
9841
9858
|
${url2}
|
|
@@ -9843,7 +9860,7 @@ ${url2}
|
|
|
9843
9860
|
openBrowser(url2);
|
|
9844
9861
|
let code;
|
|
9845
9862
|
try {
|
|
9846
|
-
code = await server.waitForCode();
|
|
9863
|
+
code = await server.waitForCode(state);
|
|
9847
9864
|
} catch (err) {
|
|
9848
9865
|
server.shutdown();
|
|
9849
9866
|
throw new Error(`OAuth flow failed: ${err.message}`);
|
|
@@ -9856,7 +9873,7 @@ ${url2}
|
|
|
9856
9873
|
if (!email3) throw new Error("Could not retrieve email from Microsoft account");
|
|
9857
9874
|
console.log(`Authenticated as ${email3}`);
|
|
9858
9875
|
const name = await promptAccountName("Outlook");
|
|
9859
|
-
const id =
|
|
9876
|
+
const id = crypto5.randomUUID();
|
|
9860
9877
|
const creds = {
|
|
9861
9878
|
id,
|
|
9862
9879
|
name,
|
|
@@ -9888,7 +9905,7 @@ async function setupICloud() {
|
|
|
9888
9905
|
password = await askPassword("App-specific password:");
|
|
9889
9906
|
}
|
|
9890
9907
|
const name = await promptAccountName("iCloud");
|
|
9891
|
-
const id =
|
|
9908
|
+
const id = crypto5.randomUUID();
|
|
9892
9909
|
const creds = {
|
|
9893
9910
|
id,
|
|
9894
9911
|
name,
|
|
@@ -9929,7 +9946,7 @@ async function setupIMAP() {
|
|
|
9929
9946
|
smtpPort = parseInt(smtpPortStr, 10);
|
|
9930
9947
|
}
|
|
9931
9948
|
const name = await promptAccountName("IMAP");
|
|
9932
|
-
const id =
|
|
9949
|
+
const id = crypto5.randomUUID();
|
|
9933
9950
|
const creds = {
|
|
9934
9951
|
id,
|
|
9935
9952
|
name,
|
|
@@ -33215,7 +33232,7 @@ var StdioServerTransport = class {
|
|
|
33215
33232
|
init_account_manager();
|
|
33216
33233
|
|
|
33217
33234
|
// src/tools/accounts.ts
|
|
33218
|
-
import
|
|
33235
|
+
import crypto4 from "node:crypto";
|
|
33219
33236
|
function jsonResult(data) {
|
|
33220
33237
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
33221
33238
|
}
|
|
@@ -33270,7 +33287,7 @@ function registerAccountTools(server, accountManager) {
|
|
|
33270
33287
|
error: "IMAP host and port are required for non-iCloud providers"
|
|
33271
33288
|
});
|
|
33272
33289
|
}
|
|
33273
|
-
const accountId =
|
|
33290
|
+
const accountId = crypto4.randomUUID();
|
|
33274
33291
|
const creds = {
|
|
33275
33292
|
id: accountId,
|
|
33276
33293
|
name: args.name,
|