fluxmail 0.20.0 → 0.21.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.
- package/dist/accounts/oauthCallback.d.ts +6 -3
- package/dist/accounts/oauthCallback.d.ts.map +1 -1
- package/dist/accounts/oauthCallback.js +8 -6
- package/dist/accounts/oauthCallback.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +93 -10
- package/dist/cli.js.map +1 -1
- package/dist/cliCloudAuth.d.ts +48 -0
- package/dist/cliCloudAuth.d.ts.map +1 -0
- package/dist/cliCloudAuth.js +254 -0
- package/dist/cliCloudAuth.js.map +1 -0
- package/dist/cliCloudClient.d.ts +29 -0
- package/dist/cliCloudClient.d.ts.map +1 -0
- package/dist/cliCloudClient.js +154 -0
- package/dist/cliCloudClient.js.map +1 -0
- package/dist/cliInstances.d.ts +39 -4
- package/dist/cliInstances.d.ts.map +1 -1
- package/dist/cliInstances.js +76 -8
- package/dist/cliInstances.js.map +1 -1
- package/dist/cliMail.d.ts.map +1 -1
- package/dist/cliMail.js +54 -143
- package/dist/cliMail.js.map +1 -1
- package/dist/cliMailBackend.d.ts +125 -0
- package/dist/cliMailBackend.d.ts.map +1 -0
- package/dist/cliMailBackend.js +354 -0
- package/dist/cliMailBackend.js.map +1 -0
- package/dist/cliOutput.d.ts.map +1 -1
- package/dist/cliOutput.js +19 -2
- package/dist/cliOutput.js.map +1 -1
- package/dist/feedback.d.ts +13 -29
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +2 -1
- package/dist/feedback.js.map +1 -1
- package/dist/http/admin.d.ts.map +1 -1
- package/dist/http/admin.js +4 -2
- package/dist/http/admin.js.map +1 -1
- package/dist/http/rest.d.ts.map +1 -1
- package/dist/http/rest.js +13 -6
- package/dist/http/rest.js.map +1 -1
- package/dist/mcp/attachmentContent.d.ts +1 -1
- package/dist/mcp/attachmentContent.d.ts.map +1 -1
- package/dist/mcp/buildServer.d.ts.map +1 -1
- package/dist/mcp/buildServer.js +37 -9
- package/dist/mcp/buildServer.js.map +1 -1
- package/dist/mcp/outputSchemas.d.ts +189 -3100
- package/dist/mcp/outputSchemas.d.ts.map +1 -1
- package/dist/sendAt.d.ts +4 -0
- package/dist/sendAt.d.ts.map +1 -0
- package/dist/sendAt.js +10 -0
- package/dist/sendAt.js.map +1 -0
- package/dist/service/emailService.d.ts.map +1 -1
- package/dist/service/emailService.js +20 -1
- package/dist/service/emailService.js.map +1 -1
- package/dist/storage/fileLock.d.ts +2 -0
- package/dist/storage/fileLock.d.ts.map +1 -1
- package/dist/storage/fileLock.js +25 -4
- package/dist/storage/fileLock.js.map +1 -1
- package/dist/telemetry.d.ts +5 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +17 -2
- package/dist/telemetry.js.map +1 -1
- package/package.json +8 -9
|
@@ -25,8 +25,9 @@ export interface LoopbackFlowOptions {
|
|
|
25
25
|
onCallback?: (source: OAuthCallbackSource) => void;
|
|
26
26
|
}
|
|
27
27
|
export declare const DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS: number;
|
|
28
|
+
type OAuthCallbackProvider = 'gmail' | 'outlook' | 'cloud';
|
|
28
29
|
interface CallbackFlowParams<T> {
|
|
29
|
-
provider:
|
|
30
|
+
provider: OAuthCallbackProvider;
|
|
30
31
|
redirectUri: string;
|
|
31
32
|
host: string;
|
|
32
33
|
port: number;
|
|
@@ -34,14 +35,16 @@ interface CallbackFlowParams<T> {
|
|
|
34
35
|
authUrl: string;
|
|
35
36
|
onAuthUrl: (url: string, context: OAuthAuthUrlContext) => void;
|
|
36
37
|
/** Exchanges the code and stores the account. Its errors end the flow. */
|
|
37
|
-
complete: (code: string) => Promise<{
|
|
38
|
+
complete: (code: string, callback: URL) => Promise<{
|
|
38
39
|
email: string;
|
|
39
40
|
value: T;
|
|
40
41
|
}>;
|
|
42
|
+
/** The browser page's heading after `complete` succeeds. */
|
|
43
|
+
successTitle?: (email: string) => string;
|
|
41
44
|
options?: LoopbackFlowOptions;
|
|
42
45
|
}
|
|
43
46
|
/** Explains a busy callback port, including the Docker Compose case where the container owns it. */
|
|
44
|
-
export declare function callbackPortInUseError(error: Error, port: number, provider:
|
|
47
|
+
export declare function callbackPortInUseError(error: Error, port: number, provider: OAuthCallbackProvider): Error;
|
|
45
48
|
/**
|
|
46
49
|
* Waits for the OAuth redirect on the loopback listener and, when a terminal
|
|
47
50
|
* is available, for the same callback URL pasted into it. The first callback
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthCallback.d.ts","sourceRoot":"","sources":["../../src/accounts/oauthCallback.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,kFAAkF;AAClF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,CAAC;IAChB,qEAAqE;IACrE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACpD;AAED,eAAO,MAAM,iCAAiC,QAAiB,CAAC;AAEhE,UAAU,kBAAkB,CAAC,CAAC;IAC5B,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"oauthCallback.d.ts","sourceRoot":"","sources":["../../src/accounts/oauthCallback.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,kFAAkF;AAClF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,CAAC;IAChB,qEAAqE;IACrE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACpD;AAED,eAAO,MAAM,iCAAiC,QAAiB,CAAC;AAEhE,KAAK,qBAAqB,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3D,UAAU,kBAAkB,CAAC,CAAC;IAC5B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC/D,0EAA0E;IAC1E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAChF,4DAA4D;IAC5D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAwED,oGAAoG;AACpG,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,KAAK,CAWzG;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA2LjF"}
|
|
@@ -3,7 +3,7 @@ import { createInterface } from 'node:readline';
|
|
|
3
3
|
import { EmailError } from '@fluxmail/core';
|
|
4
4
|
export const DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
5
5
|
function providerName(provider) {
|
|
6
|
-
return
|
|
6
|
+
return { gmail: 'Google', outlook: 'Microsoft', cloud: 'Fluxmail Cloud' }[provider];
|
|
7
7
|
}
|
|
8
8
|
function checkCallback(url, params, callbackPath) {
|
|
9
9
|
if (url.pathname !== callbackPath)
|
|
@@ -62,6 +62,8 @@ function timeoutError(params, timeoutMs) {
|
|
|
62
62
|
export function callbackPortInUseError(error, port, provider) {
|
|
63
63
|
if (error.code !== 'EADDRINUSE')
|
|
64
64
|
return error;
|
|
65
|
+
if (provider === 'cloud')
|
|
66
|
+
return new Error(`OAuth callback port ${port} is already in use. Try again.`, { cause: error });
|
|
65
67
|
return new Error(`OAuth callback port ${port} is already in use.\n\n` +
|
|
66
68
|
'If Fluxmail is running with Docker Compose, connect the account inside the container:\n\n' +
|
|
67
69
|
` docker compose exec fluxmail fluxmail accounts add ${provider}\n\n` +
|
|
@@ -125,11 +127,11 @@ export function runOAuthCallbackFlow(params) {
|
|
|
125
127
|
return claimed || settled;
|
|
126
128
|
}
|
|
127
129
|
/** Exchange a claimed code, then report the outcome to whichever path supplied it. */
|
|
128
|
-
async function exchange(source, code) {
|
|
130
|
+
async function exchange(source, code, callback) {
|
|
129
131
|
claimed = true;
|
|
130
132
|
params.options?.onCallback?.(source);
|
|
131
133
|
try {
|
|
132
|
-
const { email, value } = await params.complete(code);
|
|
134
|
+
const { email, value } = await params.complete(code, callback);
|
|
133
135
|
settle(() => resolve(value));
|
|
134
136
|
return { email };
|
|
135
137
|
}
|
|
@@ -169,9 +171,9 @@ export function runOAuthCallbackFlow(params) {
|
|
|
169
171
|
respond(response, 400, `${check.message} You can close this tab.`);
|
|
170
172
|
return;
|
|
171
173
|
}
|
|
172
|
-
const outcome = await exchange('listener', check.code);
|
|
174
|
+
const outcome = await exchange('listener', check.code, url);
|
|
173
175
|
if (outcome.email !== undefined) {
|
|
174
|
-
respond(response, 200, callbackPage(`${outcome.email} is connected to Fluxmail`, 'The account is ready to use.'), true);
|
|
176
|
+
respond(response, 200, callbackPage(params.successTitle?.(outcome.email) ?? `${outcome.email} is connected to Fluxmail`, 'The account is ready to use.'), true);
|
|
175
177
|
return;
|
|
176
178
|
}
|
|
177
179
|
const failure = failureMessage(outcome.error);
|
|
@@ -205,7 +207,7 @@ export function runOAuthCallbackFlow(params) {
|
|
|
205
207
|
settle(() => reject(check.error));
|
|
206
208
|
return;
|
|
207
209
|
}
|
|
208
|
-
await exchange('pasted', check.code);
|
|
210
|
+
await exchange('pasted', check.code, url);
|
|
209
211
|
}
|
|
210
212
|
lines?.on('line', (line) => void handlePastedLine(line));
|
|
211
213
|
lines?.on('close', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthCallback.js","sourceRoot":"","sources":["../../src/accounts/oauthCallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA+B5C,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"oauthCallback.js","sourceRoot":"","sources":["../../src/accounts/oauthCallback.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AA8B1C,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAgBpE,OAAO,EASL,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAQL,KAAK,SAAS,EAEf,MAAM,gBAAgB,CAAC;AAuCxB,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAC;AA8C7B,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAcD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,iBAAiB,EAAE,gBAAgB,UAAQ,GAAG,gBAAgB,CAuB/G;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,GAC9C,gBAAgB,CAQlB;AA0LD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,qBAAqB,CAAC,EAAE,wBAAwB,CAAC;IACjD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD;AAyJD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAatF;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CACnD;AAUD,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAQjE;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAExE;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CA+jEzE;AAED,wBAAsB,MAAM,CAAC,IAAI,GAAE,SAAS,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlF"}
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,7 @@ import { Command } from 'commander';
|
|
|
10
10
|
import { serve } from '@hono/node-server';
|
|
11
11
|
import { serveStdio, StdioServerTransport } from '@modelcontextprotocol/server/stdio';
|
|
12
12
|
import { EmailError, isEmailError } from '@fluxmail/core';
|
|
13
|
+
import { PERMISSION_PRESET_NAMES } from '@fluxmail/core/mcp';
|
|
13
14
|
import { createContext } from './context.js';
|
|
14
15
|
import { RuntimeLifecycle } from './lifecycle.js';
|
|
15
16
|
import { configTomlPath, createConfigurationService, deploymentToml, readLoggingSettings, resolveDataDir, resolveStoreLocation, writeDeploymentConfig, } from './config.js';
|
|
@@ -29,7 +30,9 @@ import { VERSION } from './version.js';
|
|
|
29
30
|
import { inspectStoreCompatibility, MIN_SUPPORTED_STORE_FORMAT, openDb, openReadonlyDb, } from './storage/db.js';
|
|
30
31
|
import { customPermissionPolicy, ADMIN_CAPABILITIES, DEFAULT_PERMISSION_POLICY, DEFAULT_PERMISSION_PROFILE, isNamedPermissionProfile, MCP_CAPABILITIES, NAMED_PERMISSION_PROFILES, permissionPolicyForProfile, } from './permissions.js';
|
|
31
32
|
import { captureOperation, getTelemetry, installTelemetryStreamEndHandler, isTelemetryEnabled, setTelemetryEnabled, shutdownTelemetry, telemetryDisabledInAnyEnvironment, } from './telemetry.js';
|
|
32
|
-
import { apiErrorCode, CliCanceledError, apiRequestId, clearSessionToken, instanceClient, loadInstanceConfig, removeInstance, resolveInstance, resolveStdioInstance, saveLocalInstance, saveRemoteInstance, saveSessionToken, setRequestDeadlineMs, useInstance, } from './cliInstances.js';
|
|
33
|
+
import { cloudManagementError, apiErrorCode, CliCanceledError, apiRequestId, clearSessionToken, instanceClient, loadInstanceConfig, removeInstance, resolveInstance, resolveStdioInstance, saveLocalInstance, saveRemoteInstance, saveSessionToken, setRequestDeadlineMs, useInstance, validateRemoteServerUrl, } from './cliInstances.js';
|
|
34
|
+
import { DEFAULT_CLOUD_ORIGIN, loginToCloud, logoutOfCloud, openInBrowser, replaceCloudSession, } from './cliCloudAuth.js';
|
|
35
|
+
import { CloudMailBackend, mailBackend } from './cliMailBackend.js';
|
|
33
36
|
import { cliExitCode, parseOutputFormat, printOutput } from './cliOutput.js';
|
|
34
37
|
import { CliStartupError, cliStartupDiagnostics } from './cliStartupDiagnostics.js';
|
|
35
38
|
import { authenticateBearer, isBootstrapComplete, normalizeAndValidatePassword, recoverAdminPassword, setupInitialAdmin, } from './auth.js';
|
|
@@ -407,7 +410,7 @@ export function createCliProgram(options = {}) {
|
|
|
407
410
|
program
|
|
408
411
|
.name('fluxmail')
|
|
409
412
|
.description('Fluxmail, a self-hosted email API with MCP, REST, and CLI access')
|
|
410
|
-
.option('--instance <name>', 'Use a named local or
|
|
413
|
+
.option('--instance <name>', 'Use a named local, remote, or Fluxmail Cloud instance')
|
|
411
414
|
.option('-a, --mail-account <id-or-email>', 'Use an email account by ID or address')
|
|
412
415
|
.option('--format <format>', 'Output format: json, table, or ndjson', 'json')
|
|
413
416
|
.option('--timeout <seconds>', 'Request deadline in seconds (1 to 300)', '30')
|
|
@@ -511,6 +514,17 @@ export function createCliProgram(options = {}) {
|
|
|
511
514
|
initialExitCode: process.exitCode,
|
|
512
515
|
logger: getLogger(dataDir, mode, logging),
|
|
513
516
|
});
|
|
517
|
+
if (mode === 'cli') {
|
|
518
|
+
try {
|
|
519
|
+
const config = loadInstanceConfig();
|
|
520
|
+
const kind = config.instances[selectedInstance() ?? config.active ?? '']?.kind;
|
|
521
|
+
if (kind === 'cloud')
|
|
522
|
+
recordCliOperationProperties(program, { instance_kind: kind });
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
// The command action reports an unreadable profile file.
|
|
526
|
+
}
|
|
527
|
+
}
|
|
514
528
|
const [group, action] = command.split(' ');
|
|
515
529
|
const alreadyStructured = ['folders', 'labels', 'emails', 'threads', 'drafts', 'scheduled', 'attachments'].includes(group ?? '') ||
|
|
516
530
|
command === 'accounts list' ||
|
|
@@ -573,6 +587,52 @@ export function createCliProgram(options = {}) {
|
|
|
573
587
|
}
|
|
574
588
|
}
|
|
575
589
|
});
|
|
590
|
+
async function cloudLogin(name, existing, opts) {
|
|
591
|
+
recordCliOperationProperties(program, { instance_kind: 'cloud' });
|
|
592
|
+
if (existing && existing.kind !== 'cloud') {
|
|
593
|
+
throw new EmailError('invalid_request', `Instance "${name}" is not a Fluxmail Cloud profile. Choose another name.`);
|
|
594
|
+
}
|
|
595
|
+
if (opts.email || opts.enroll || opts.reset) {
|
|
596
|
+
throw new EmailError('invalid_request', '--email, --enroll, and --reset do not apply to Fluxmail Cloud.');
|
|
597
|
+
}
|
|
598
|
+
if (opts.apiKey && opts.profile) {
|
|
599
|
+
throw new EmailError('invalid_request', 'An API key has its own permissions, so --profile does not apply.');
|
|
600
|
+
}
|
|
601
|
+
const preset = opts.profile ?? 'full';
|
|
602
|
+
if (!PERMISSION_PRESET_NAMES.includes(preset)) {
|
|
603
|
+
throw new EmailError('invalid_request', '--profile must be read-only, read-write, or full.');
|
|
604
|
+
}
|
|
605
|
+
const serverUrl = validateRemoteServerUrl(opts.server ?? existing?.serverUrl ?? DEFAULT_CLOUD_ORIGIN);
|
|
606
|
+
const profile = { kind: 'cloud', serverUrl };
|
|
607
|
+
if (opts.apiKey) {
|
|
608
|
+
const key = (process.env.FLUXMAIL_CLOUD_API_KEY ?? (await hiddenPrompt('Cloud API key'))).trim();
|
|
609
|
+
if (!key.startsWith('fm_'))
|
|
610
|
+
throw new EmailError('invalid_request', 'Fluxmail Cloud API keys start with fm_.');
|
|
611
|
+
// Check the key before it replaces a working session.
|
|
612
|
+
await new CloudMailBackend(name, profile, key).status();
|
|
613
|
+
await replaceCloudSession(name, { kind: 'key', key, serverUrl });
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
await loginToCloud({
|
|
617
|
+
instance: name,
|
|
618
|
+
serverUrl,
|
|
619
|
+
preset: preset,
|
|
620
|
+
flow: process.stdin.isTTY
|
|
621
|
+
? { paste: { input: process.stdin, write: (message) => console.error(message) } }
|
|
622
|
+
: undefined,
|
|
623
|
+
onAuthUrl: (url, { pasteEnabled }) => {
|
|
624
|
+
console.error(`Sign in to Fluxmail Cloud and approve access:\n\n ${url}\n`);
|
|
625
|
+
if (pasteEnabled) {
|
|
626
|
+
console.error('If your browser runs on another computer, paste the URL it lands on here.');
|
|
627
|
+
}
|
|
628
|
+
if (process.stdout.isTTY)
|
|
629
|
+
openInBrowser(url);
|
|
630
|
+
},
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
useInstance(name);
|
|
634
|
+
console.log(`Logged in to ${name}.`);
|
|
635
|
+
}
|
|
576
636
|
program
|
|
577
637
|
.command('setup')
|
|
578
638
|
.description('Create the first local administrator or claim a migrated administrator')
|
|
@@ -615,11 +675,14 @@ export function createCliProgram(options = {}) {
|
|
|
615
675
|
});
|
|
616
676
|
program
|
|
617
677
|
.command('login')
|
|
618
|
-
.description('Log in to a local or remote instance')
|
|
678
|
+
.description('Log in to a local or remote instance, or to Fluxmail Cloud')
|
|
619
679
|
.option('--server <url>', 'Add or update a remote instance')
|
|
620
680
|
.option('--email <email>', 'Member email')
|
|
621
681
|
.option('--enroll', 'Use a one-time enrollment code')
|
|
622
682
|
.option('--reset', 'Use a one-time password reset code')
|
|
683
|
+
.option('--cloud', 'Log in to Fluxmail Cloud in a browser')
|
|
684
|
+
.option('--api-key', 'With --cloud, use a Cloud API key instead of a browser')
|
|
685
|
+
.option('--profile <profile>', 'With --cloud, the permissions to request: read-only, read-write, or full')
|
|
623
686
|
.action(async (opts) => {
|
|
624
687
|
try {
|
|
625
688
|
if (opts.enroll && opts.reset) {
|
|
@@ -627,6 +690,18 @@ export function createCliProgram(options = {}) {
|
|
|
627
690
|
}
|
|
628
691
|
const requestedInstance = selectedInstance();
|
|
629
692
|
const instanceConfig = loadInstanceConfig();
|
|
693
|
+
const namedProfile = instanceConfig.instances[requestedInstance ?? instanceConfig.active ?? ''];
|
|
694
|
+
if (opts.cloud || (namedProfile?.kind === 'cloud' && !opts.server)) {
|
|
695
|
+
const name = requestedInstance ?? (namedProfile?.kind === 'cloud' ? instanceConfig.active : 'cloud');
|
|
696
|
+
await cloudLogin(name, instanceConfig.instances[name], opts);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
if (opts.apiKey || opts.profile) {
|
|
700
|
+
throw new EmailError('invalid_request', '--api-key and --profile require --cloud.');
|
|
701
|
+
}
|
|
702
|
+
if (opts.server && requestedInstance && namedProfile?.kind === 'cloud') {
|
|
703
|
+
throw new EmailError('invalid_request', `Instance "${requestedInstance}" is a Fluxmail Cloud profile.`);
|
|
704
|
+
}
|
|
630
705
|
if (!opts.server &&
|
|
631
706
|
!instanceConfig.instances.local &&
|
|
632
707
|
(requestedInstance === 'local' || (!requestedInstance && Object.keys(instanceConfig.instances).length === 0))) {
|
|
@@ -670,6 +745,13 @@ export function createCliProgram(options = {}) {
|
|
|
670
745
|
.action(async () => {
|
|
671
746
|
try {
|
|
672
747
|
const selected = resolveInstance(selectedInstance());
|
|
748
|
+
if (selected.profile.kind === 'cloud') {
|
|
749
|
+
const { revoked } = await logoutOfCloud(selected.name);
|
|
750
|
+
console.log(revoked
|
|
751
|
+
? `Logged out of ${selected.name}.`
|
|
752
|
+
: `Removed the credentials for ${selected.name}. To end access, revoke it at ${selected.profile.serverUrl}.`);
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
673
755
|
const response = await instanceClient(selected.name).request('/api/v1/auth/logout', { method: 'POST' });
|
|
674
756
|
if (!response.ok && response.status !== 401) {
|
|
675
757
|
throw new EmailError('invalid_request', `Logout failed with HTTP ${response.status}.`);
|
|
@@ -691,7 +773,7 @@ export function createCliProgram(options = {}) {
|
|
|
691
773
|
name,
|
|
692
774
|
active: config.active === name ? '*' : '',
|
|
693
775
|
kind: profile.kind,
|
|
694
|
-
url: profile.kind === '
|
|
776
|
+
url: profile.kind === 'local' ? '' : profile.serverUrl,
|
|
695
777
|
}));
|
|
696
778
|
const width = (values) => Math.max(...values.map((value) => value.length));
|
|
697
779
|
const nameWidth = width(['NAME', ...rows.map((row) => row.name)]);
|
|
@@ -951,8 +1033,7 @@ export function createCliProgram(options = {}) {
|
|
|
951
1033
|
.description('List available sender addresses')
|
|
952
1034
|
.action(async (accountId) => {
|
|
953
1035
|
try {
|
|
954
|
-
|
|
955
|
-
console.log(JSON.stringify(identities, null, 2));
|
|
1036
|
+
console.log(JSON.stringify(await mailBackend(selectedInstance()).listSendAs(accountId), null, 2));
|
|
956
1037
|
}
|
|
957
1038
|
catch (err) {
|
|
958
1039
|
failCliOperation(program, err);
|
|
@@ -1043,6 +1124,10 @@ export function createCliProgram(options = {}) {
|
|
|
1043
1124
|
return;
|
|
1044
1125
|
}
|
|
1045
1126
|
const selected = resolveInstance(selectedInstance());
|
|
1127
|
+
if (selected.profile.kind === 'cloud') {
|
|
1128
|
+
failCliOperation(program, cloudManagementError(selected.profile, '/mailboxes'));
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1046
1131
|
// A remote instance reconnects an IMAP mailbox that matches the address,
|
|
1047
1132
|
// so without --reauthorize only the server knows which one this is.
|
|
1048
1133
|
const reauthorize = opts.reauthorize !== undefined
|
|
@@ -1375,8 +1460,7 @@ export function createCliProgram(options = {}) {
|
|
|
1375
1460
|
.description('List connected accounts')
|
|
1376
1461
|
.action(async () => {
|
|
1377
1462
|
try {
|
|
1378
|
-
|
|
1379
|
-
printOutput({ data: all }, selectedFormat());
|
|
1463
|
+
printOutput({ data: await mailBackend(selectedInstance()).listAccounts() }, selectedFormat());
|
|
1380
1464
|
}
|
|
1381
1465
|
catch (err) {
|
|
1382
1466
|
failCliOperation(program, err);
|
|
@@ -2147,8 +2231,7 @@ export function createCliProgram(options = {}) {
|
|
|
2147
2231
|
.description('Show mailbox and provider status for the selected instance')
|
|
2148
2232
|
.action(async () => {
|
|
2149
2233
|
try {
|
|
2150
|
-
|
|
2151
|
-
printOutput({ data: status }, selectedFormat());
|
|
2234
|
+
printOutput({ data: await mailBackend(selectedInstance()).status() }, selectedFormat());
|
|
2152
2235
|
}
|
|
2153
2236
|
catch (err) {
|
|
2154
2237
|
failCliOperation(program, err);
|