@bobfrankston/mailx 1.0.12 → 1.0.13
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/bin/mailx.js +47 -29
- package/client/app.js +93 -13
- package/client/components/folder-tree.js +84 -3
- package/client/components/message-list.js +134 -8
- package/client/components/message-viewer.js +130 -13
- package/client/compose/compose.html +4 -4
- package/client/compose/compose.js +53 -34
- package/client/index.html +33 -9
- package/client/lib/api-client.js +102 -30
- package/client/lib/mailxapi.js +123 -0
- package/client/package.json +1 -1
- package/client/styles/components.css +188 -15
- package/client/styles/layout.css +2 -1
- package/killmail.cmd +6 -0
- package/launch.ps1 +47 -5
- package/launcher/bin/mailx-app.exe +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Breadcrumbs +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Crashpad/metadata +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Crashpad/settings.dat +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Crashpad/throttle_store.dat +1 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/CrashpadMetrics-active.pma +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/BrowsingTopicsSiteData +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Cache/No_Vary_Search/journal.baj +1 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/DIPS +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/DashTrackerDatabase +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/EdgeJourneys/EdgeJourneys.db +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Rules/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Rules/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Rules/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Scripts/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Scripts/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Scripts/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension State/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension State/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension State/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/ExtensionActivityComp +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/ExtensionActivityEdge +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Favicons +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/History +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/History-journal +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/IndexedDB/devtools_devtools_0.indexeddb.leveldb/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/IndexedDB/devtools_devtools_0.indexeddb.leveldb/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/IndexedDB/devtools_devtools_0.indexeddb.leveldb/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Local Storage/leveldb/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Login Data +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Login Data For Account +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network/Cookies +0 -0
- NEL +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network/Trust Tokens +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network Action Predictor +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Preferences +1 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/ServerCertificate +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Session Storage/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Session Storage/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Session Storage/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Shared Dictionary/db +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/SharedStorage +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Shortcuts +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Site Characteristics Database/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Top Sites +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Vpn Tokens +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Web Data +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Web Data-journal +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager-journal +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/heavy_ad_intervention_opt_out.db +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOCK +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOG +3 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/MANIFEST-000001 +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/DeferredBrowserMetrics/BrowserMetrics-69CAD063-BE24.pma +0 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Local State +1 -0
- package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Variations +1 -0
- package/launcher/bin/mailx-app.old.exe +0 -0
- package/package.json +1 -1
- package/packages/mailx-api/index.js +79 -26
- package/packages/mailx-core/index.d.ts +129 -0
- package/packages/mailx-core/index.js +323 -0
- package/packages/mailx-core/ipc.d.ts +13 -0
- package/packages/mailx-core/ipc.js +56 -0
- package/packages/mailx-core/package.json +18 -0
- package/packages/mailx-imap/index.d.ts +5 -1
- package/packages/mailx-imap/index.js +76 -14
- package/packages/mailx-server/index.js +42 -31
- package/packages/mailx-server/package.json +1 -2
- package/packages/mailx-settings/index.d.ts +1 -1
- package/packages/mailx-settings/index.js +21 -12
- package/packages/mailx-store/db.d.ts +5 -1
- package/packages/mailx-store/db.js +64 -12
- package/packages/mailx-store/file-store.d.ts +2 -8
- package/packages/mailx-store/file-store.js +7 -31
- package/packages/mailx-types/index.d.ts +3 -1
- package/.tswalk.json +0 -7396
- package/launcher/release.cmd +0 -4
- package/mailx.json +0 -9
- package/packages/mailx-api/node_modules/nodemailer/.ncurc.js +0 -9
- package/packages/mailx-api/node_modules/nodemailer/.prettierignore +0 -8
- package/packages/mailx-api/node_modules/nodemailer/.prettierrc +0 -12
- package/packages/mailx-api/node_modules/nodemailer/.prettierrc.js +0 -10
- package/packages/mailx-api/node_modules/nodemailer/.release-please-config.json +0 -9
- package/packages/mailx-api/node_modules/nodemailer/LICENSE +0 -16
- package/packages/mailx-api/node_modules/nodemailer/README.md +0 -86
- package/packages/mailx-api/node_modules/nodemailer/SECURITY.txt +0 -22
- package/packages/mailx-api/node_modules/nodemailer/eslint.config.js +0 -88
- package/packages/mailx-api/node_modules/nodemailer/lib/addressparser/index.js +0 -383
- package/packages/mailx-api/node_modules/nodemailer/lib/base64/index.js +0 -139
- package/packages/mailx-api/node_modules/nodemailer/lib/dkim/index.js +0 -253
- package/packages/mailx-api/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
- package/packages/mailx-api/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
- package/packages/mailx-api/node_modules/nodemailer/lib/dkim/sign.js +0 -117
- package/packages/mailx-api/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
- package/packages/mailx-api/node_modules/nodemailer/lib/fetch/index.js +0 -280
- package/packages/mailx-api/node_modules/nodemailer/lib/json-transport/index.js +0 -82
- package/packages/mailx-api/node_modules/nodemailer/lib/mail-composer/index.js +0 -629
- package/packages/mailx-api/node_modules/nodemailer/lib/mailer/index.js +0 -441
- package/packages/mailx-api/node_modules/nodemailer/lib/mailer/mail-message.js +0 -316
- package/packages/mailx-api/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
- package/packages/mailx-api/node_modules/nodemailer/lib/mime-funcs/mime-types.js +0 -2113
- package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/index.js +0 -1316
- package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/last-newline.js +0 -33
- package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/le-unix.js +0 -43
- package/packages/mailx-api/node_modules/nodemailer/lib/mime-node/le-windows.js +0 -52
- package/packages/mailx-api/node_modules/nodemailer/lib/nodemailer.js +0 -157
- package/packages/mailx-api/node_modules/nodemailer/lib/punycode/index.js +0 -460
- package/packages/mailx-api/node_modules/nodemailer/lib/qp/index.js +0 -227
- package/packages/mailx-api/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
- package/packages/mailx-api/node_modules/nodemailer/lib/ses-transport/index.js +0 -234
- package/packages/mailx-api/node_modules/nodemailer/lib/shared/index.js +0 -754
- package/packages/mailx-api/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
- package/packages/mailx-api/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
- package/packages/mailx-api/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1870
- package/packages/mailx-api/node_modules/nodemailer/lib/smtp-pool/index.js +0 -652
- package/packages/mailx-api/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +0 -259
- package/packages/mailx-api/node_modules/nodemailer/lib/smtp-transport/index.js +0 -421
- package/packages/mailx-api/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
- package/packages/mailx-api/node_modules/nodemailer/lib/well-known/index.js +0 -47
- package/packages/mailx-api/node_modules/nodemailer/lib/well-known/services.json +0 -611
- package/packages/mailx-api/node_modules/nodemailer/lib/xoauth2/index.js +0 -427
- package/packages/mailx-api/node_modules/nodemailer/package.json +0 -47
- package/packages/mailx-imap/node_modules/nodemailer/.ncurc.js +0 -9
- package/packages/mailx-imap/node_modules/nodemailer/.prettierignore +0 -8
- package/packages/mailx-imap/node_modules/nodemailer/.prettierrc +0 -12
- package/packages/mailx-imap/node_modules/nodemailer/.prettierrc.js +0 -10
- package/packages/mailx-imap/node_modules/nodemailer/.release-please-config.json +0 -9
- package/packages/mailx-imap/node_modules/nodemailer/LICENSE +0 -16
- package/packages/mailx-imap/node_modules/nodemailer/README.md +0 -86
- package/packages/mailx-imap/node_modules/nodemailer/SECURITY.txt +0 -22
- package/packages/mailx-imap/node_modules/nodemailer/eslint.config.js +0 -88
- package/packages/mailx-imap/node_modules/nodemailer/lib/addressparser/index.js +0 -383
- package/packages/mailx-imap/node_modules/nodemailer/lib/base64/index.js +0 -139
- package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/index.js +0 -253
- package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
- package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
- package/packages/mailx-imap/node_modules/nodemailer/lib/dkim/sign.js +0 -117
- package/packages/mailx-imap/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
- package/packages/mailx-imap/node_modules/nodemailer/lib/fetch/index.js +0 -280
- package/packages/mailx-imap/node_modules/nodemailer/lib/json-transport/index.js +0 -82
- package/packages/mailx-imap/node_modules/nodemailer/lib/mail-composer/index.js +0 -629
- package/packages/mailx-imap/node_modules/nodemailer/lib/mailer/index.js +0 -441
- package/packages/mailx-imap/node_modules/nodemailer/lib/mailer/mail-message.js +0 -316
- package/packages/mailx-imap/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
- package/packages/mailx-imap/node_modules/nodemailer/lib/mime-funcs/mime-types.js +0 -2113
- package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/index.js +0 -1316
- package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/last-newline.js +0 -33
- package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/le-unix.js +0 -43
- package/packages/mailx-imap/node_modules/nodemailer/lib/mime-node/le-windows.js +0 -52
- package/packages/mailx-imap/node_modules/nodemailer/lib/nodemailer.js +0 -157
- package/packages/mailx-imap/node_modules/nodemailer/lib/punycode/index.js +0 -460
- package/packages/mailx-imap/node_modules/nodemailer/lib/qp/index.js +0 -227
- package/packages/mailx-imap/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
- package/packages/mailx-imap/node_modules/nodemailer/lib/ses-transport/index.js +0 -234
- package/packages/mailx-imap/node_modules/nodemailer/lib/shared/index.js +0 -754
- package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
- package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
- package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1870
- package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-pool/index.js +0 -652
- package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +0 -259
- package/packages/mailx-imap/node_modules/nodemailer/lib/smtp-transport/index.js +0 -421
- package/packages/mailx-imap/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
- package/packages/mailx-imap/node_modules/nodemailer/lib/well-known/index.js +0 -47
- package/packages/mailx-imap/node_modules/nodemailer/lib/well-known/services.json +0 -611
- package/packages/mailx-imap/node_modules/nodemailer/lib/xoauth2/index.js +0 -427
- package/packages/mailx-imap/node_modules/nodemailer/package.json +0 -47
- package/packages/mailx-send/node_modules/nodemailer/.ncurc.js +0 -9
- package/packages/mailx-send/node_modules/nodemailer/.prettierignore +0 -8
- package/packages/mailx-send/node_modules/nodemailer/.prettierrc +0 -12
- package/packages/mailx-send/node_modules/nodemailer/.prettierrc.js +0 -10
- package/packages/mailx-send/node_modules/nodemailer/.release-please-config.json +0 -9
- package/packages/mailx-send/node_modules/nodemailer/LICENSE +0 -16
- package/packages/mailx-send/node_modules/nodemailer/README.md +0 -86
- package/packages/mailx-send/node_modules/nodemailer/SECURITY.txt +0 -22
- package/packages/mailx-send/node_modules/nodemailer/eslint.config.js +0 -88
- package/packages/mailx-send/node_modules/nodemailer/lib/addressparser/index.js +0 -383
- package/packages/mailx-send/node_modules/nodemailer/lib/base64/index.js +0 -139
- package/packages/mailx-send/node_modules/nodemailer/lib/dkim/index.js +0 -253
- package/packages/mailx-send/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
- package/packages/mailx-send/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
- package/packages/mailx-send/node_modules/nodemailer/lib/dkim/sign.js +0 -117
- package/packages/mailx-send/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
- package/packages/mailx-send/node_modules/nodemailer/lib/fetch/index.js +0 -280
- package/packages/mailx-send/node_modules/nodemailer/lib/json-transport/index.js +0 -82
- package/packages/mailx-send/node_modules/nodemailer/lib/mail-composer/index.js +0 -629
- package/packages/mailx-send/node_modules/nodemailer/lib/mailer/index.js +0 -441
- package/packages/mailx-send/node_modules/nodemailer/lib/mailer/mail-message.js +0 -316
- package/packages/mailx-send/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
- package/packages/mailx-send/node_modules/nodemailer/lib/mime-funcs/mime-types.js +0 -2113
- package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/index.js +0 -1316
- package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/last-newline.js +0 -33
- package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/le-unix.js +0 -43
- package/packages/mailx-send/node_modules/nodemailer/lib/mime-node/le-windows.js +0 -52
- package/packages/mailx-send/node_modules/nodemailer/lib/nodemailer.js +0 -157
- package/packages/mailx-send/node_modules/nodemailer/lib/punycode/index.js +0 -460
- package/packages/mailx-send/node_modules/nodemailer/lib/qp/index.js +0 -227
- package/packages/mailx-send/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
- package/packages/mailx-send/node_modules/nodemailer/lib/ses-transport/index.js +0 -234
- package/packages/mailx-send/node_modules/nodemailer/lib/shared/index.js +0 -754
- package/packages/mailx-send/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
- package/packages/mailx-send/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
- package/packages/mailx-send/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1870
- package/packages/mailx-send/node_modules/nodemailer/lib/smtp-pool/index.js +0 -652
- package/packages/mailx-send/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +0 -259
- package/packages/mailx-send/node_modules/nodemailer/lib/smtp-transport/index.js +0 -421
- package/packages/mailx-send/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
- package/packages/mailx-send/node_modules/nodemailer/lib/well-known/index.js +0 -47
- package/packages/mailx-send/node_modules/nodemailer/lib/well-known/services.json +0 -611
- package/packages/mailx-send/node_modules/nodemailer/lib/xoauth2/index.js +0 -427
- package/packages/mailx-send/node_modules/nodemailer/package.json +0 -47
|
@@ -11,10 +11,10 @@ import { ImapManager } from "@bobfrankston/mailx-imap";
|
|
|
11
11
|
import { createApiRouter } from "@bobfrankston/mailx-api";
|
|
12
12
|
import { loadSettings, getConfigDir, initLocalConfig } from "@bobfrankston/mailx-settings";
|
|
13
13
|
import { ports } from "@bobfrankston/miscinfo";
|
|
14
|
-
import {
|
|
14
|
+
import { createServer } from "node:http";
|
|
15
15
|
const PORT = ports.mailx;
|
|
16
16
|
// ── File logging ──
|
|
17
|
-
const logDir = path.join(process.env.USERPROFILE || process.env.HOME || ".", ".mailx");
|
|
17
|
+
const logDir = path.join(process.env.USERPROFILE || process.env.HOME || ".", ".mailx", "logs");
|
|
18
18
|
fs.mkdirSync(logDir, { recursive: true });
|
|
19
19
|
// Rotate: delete logs older than 7 days
|
|
20
20
|
try {
|
|
@@ -53,7 +53,19 @@ const db = new MailxDB(dbDir);
|
|
|
53
53
|
const imapManager = new ImapManager(db);
|
|
54
54
|
// ── Express App ──
|
|
55
55
|
const app = express();
|
|
56
|
-
app.use(express.json());
|
|
56
|
+
app.use(express.json({ limit: "Infinity" }));
|
|
57
|
+
// Request logging
|
|
58
|
+
app.use((req, res, next) => {
|
|
59
|
+
const start = Date.now();
|
|
60
|
+
res.on("finish", () => {
|
|
61
|
+
const ms = Date.now() - start;
|
|
62
|
+
// Skip noisy polling endpoints
|
|
63
|
+
if (req.path === "/api/sync/pending")
|
|
64
|
+
return;
|
|
65
|
+
console.log(` ${req.method} ${req.path} ${res.statusCode} ${ms}ms`);
|
|
66
|
+
});
|
|
67
|
+
next();
|
|
68
|
+
});
|
|
57
69
|
// Serve client static files
|
|
58
70
|
const clientDir = path.join(import.meta.dirname, "..", "..", "client");
|
|
59
71
|
const rootDir = path.join(import.meta.dirname, "..", "..");
|
|
@@ -97,15 +109,14 @@ ${accountInfo.map((a) => `<tr><td>${a.name}</td><td>${a.folders}</td><td>${a.inb
|
|
|
97
109
|
<p style="margin-top:2rem;font-size:0.8rem"><a href="/">Open mailx</a> | Auto-refreshes every 10s</p>
|
|
98
110
|
</body></html>`);
|
|
99
111
|
});
|
|
100
|
-
//
|
|
112
|
+
// Restart server + reload clients
|
|
101
113
|
app.post("/api/restart", (req, res) => {
|
|
102
114
|
res.json({ ok: true });
|
|
103
115
|
broadcast({ type: "reload" });
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
fs.utimesSync(serverFile, now, now);
|
|
116
|
+
// Graceful shutdown — node --watch will auto-restart
|
|
117
|
+
setTimeout(async () => {
|
|
118
|
+
console.log(" Restart requested via API");
|
|
119
|
+
await shutdown();
|
|
109
120
|
}, 500);
|
|
110
121
|
});
|
|
111
122
|
// SPA fallback
|
|
@@ -113,8 +124,13 @@ app.get("*", (req, res) => {
|
|
|
113
124
|
if (!req.path.startsWith("/api"))
|
|
114
125
|
res.sendFile(path.join(clientDir, "index.html"));
|
|
115
126
|
});
|
|
116
|
-
//
|
|
117
|
-
|
|
127
|
+
// JSON error handler — all errors return JSON, never HTML
|
|
128
|
+
app.use((err, _req, res, _next) => {
|
|
129
|
+
console.error(`ERROR ${err.message}`);
|
|
130
|
+
const status = err.status || err.statusCode || 500;
|
|
131
|
+
res.status(status).json({ error: err.message || "Internal server error" });
|
|
132
|
+
});
|
|
133
|
+
// ── HTTP Server ──
|
|
118
134
|
let server;
|
|
119
135
|
let wss;
|
|
120
136
|
const clients = new Set();
|
|
@@ -147,19 +163,19 @@ async function start() {
|
|
|
147
163
|
const seeded = db.seedContactsFromMessages();
|
|
148
164
|
if (seeded > 0)
|
|
149
165
|
console.log(` Seeded ${seeded} contacts`);
|
|
150
|
-
// Search index —
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
166
|
+
// Search index — rebuild in background after server starts (non-blocking)
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
let ftsCount = 0;
|
|
169
|
+
try {
|
|
170
|
+
ftsCount = db.db.prepare("SELECT COUNT(*) as cnt FROM messages_fts").get()?.cnt || 0;
|
|
171
|
+
}
|
|
172
|
+
catch { /* */ }
|
|
173
|
+
if (ftsCount === 0) {
|
|
154
174
|
const indexed = db.rebuildSearchIndex();
|
|
155
|
-
|
|
175
|
+
if (indexed > 0)
|
|
176
|
+
console.log(` Search index: ${indexed} messages`);
|
|
156
177
|
}
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
// FTS table might not exist yet
|
|
160
|
-
const indexed = db.rebuildSearchIndex();
|
|
161
|
-
console.log(` Search index built: ${indexed} messages`);
|
|
162
|
-
}
|
|
178
|
+
}, 5000);
|
|
163
179
|
// Add configured accounts
|
|
164
180
|
for (const account of settings.accounts) {
|
|
165
181
|
if (!account.enabled)
|
|
@@ -191,17 +207,12 @@ async function start() {
|
|
|
191
207
|
imapManager.startOutboxWorker();
|
|
192
208
|
// Start server — localhost only by default, --external for network access
|
|
193
209
|
const externalAccess = process.argv.includes("--external");
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
hostname: externalAccess ? undefined : "127.0.0.1",
|
|
197
|
-
app,
|
|
198
|
-
certspath,
|
|
199
|
-
msger: (msg) => console.log(` [cert] ${msg}`),
|
|
200
|
-
});
|
|
201
|
-
server = await InitServerAsync(opts);
|
|
210
|
+
const hostname = externalAccess ? "0.0.0.0" : "127.0.0.1";
|
|
211
|
+
server = createServer(app);
|
|
202
212
|
wss = new WebSocketServer({ server });
|
|
203
213
|
wireWebSocket();
|
|
204
|
-
|
|
214
|
+
await new Promise((resolve) => server.listen(PORT, hostname, resolve));
|
|
215
|
+
console.log(`mailx server running on http://${hostname}:${PORT}`);
|
|
205
216
|
}
|
|
206
217
|
// ── Graceful Shutdown ──
|
|
207
218
|
async function shutdown() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"@bobfrankston/mailx-imap": "file:../mailx-imap",
|
|
15
15
|
"@bobfrankston/mailx-api": "file:../mailx-api",
|
|
16
16
|
"@bobfrankston/mailx-settings": "file:../mailx-settings",
|
|
17
|
-
"@bobfrankston/certsupport": "file:../../../../projects/nodejs/certsupport",
|
|
18
17
|
"express": "^4.21.0",
|
|
19
18
|
"ws": "^8.18.0"
|
|
20
19
|
},
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* allowlist.jsonc — remote content allow-list
|
|
9
9
|
*
|
|
10
10
|
* Local overrides (~/.mailx/):
|
|
11
|
-
* config.
|
|
11
|
+
* config.jsonc — pointer to shared dir + local-only settings (storePath, historyDays)
|
|
12
12
|
* accounts.jsonc — cached copy, fallback when shared unavailable
|
|
13
13
|
* preferences.jsonc — local overrides merged on top of shared
|
|
14
14
|
* allowlist.jsonc — cached copy
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* allowlist.jsonc — remote content allow-list
|
|
9
9
|
*
|
|
10
10
|
* Local overrides (~/.mailx/):
|
|
11
|
-
* config.
|
|
11
|
+
* config.jsonc — pointer to shared dir + local-only settings (storePath, historyDays)
|
|
12
12
|
* accounts.jsonc — cached copy, fallback when shared unavailable
|
|
13
13
|
* preferences.jsonc — local overrides merged on top of shared
|
|
14
14
|
* allowlist.jsonc — cached copy
|
|
@@ -20,17 +20,17 @@ import * as path from "node:path";
|
|
|
20
20
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
21
21
|
// ── Paths ──
|
|
22
22
|
const LOCAL_DIR = path.join(process.env.USERPROFILE || process.env.HOME || ".", ".mailx");
|
|
23
|
-
const LOCAL_CONFIG_PATH = path.join(LOCAL_DIR, "config.
|
|
23
|
+
const LOCAL_CONFIG_PATH = path.join(LOCAL_DIR, "config.jsonc");
|
|
24
|
+
const LEGACY_CONFIG_PATH = path.join(LOCAL_DIR, "config.json");
|
|
24
25
|
const DEFAULT_STORE_PATH = path.join(LOCAL_DIR, "mailxstore");
|
|
25
26
|
function readLocalConfig() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return JSON.parse(fs.readFileSync(LOCAL_CONFIG_PATH, "utf-8"));
|
|
27
|
+
// Migrate config.json → config.jsonc
|
|
28
|
+
if (!fs.existsSync(LOCAL_CONFIG_PATH) && fs.existsSync(LEGACY_CONFIG_PATH)) {
|
|
29
|
+
fs.renameSync(LEGACY_CONFIG_PATH, LOCAL_CONFIG_PATH);
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
if (!fs.existsSync(LOCAL_CONFIG_PATH))
|
|
32
32
|
return {};
|
|
33
|
-
}
|
|
33
|
+
return readJsonc(LOCAL_CONFIG_PATH) || {};
|
|
34
34
|
}
|
|
35
35
|
function getSharedDir() {
|
|
36
36
|
const config = readLocalConfig();
|
|
@@ -42,14 +42,23 @@ function getSharedDir() {
|
|
|
42
42
|
return LOCAL_DIR;
|
|
43
43
|
}
|
|
44
44
|
// ── File helpers ──
|
|
45
|
+
/** Read JSON or JSONC file. If exact path not found, tries .json/.jsonc variant. */
|
|
45
46
|
function readJsonc(filePath) {
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
let actual = filePath;
|
|
48
|
+
if (!fs.existsSync(actual)) {
|
|
49
|
+
// Try alternate extension
|
|
50
|
+
if (actual.endsWith(".jsonc"))
|
|
51
|
+
actual = actual.replace(/\.jsonc$/, ".json");
|
|
52
|
+
else if (actual.endsWith(".json"))
|
|
53
|
+
actual = actual.replace(/\.json$/, ".jsonc");
|
|
54
|
+
if (!fs.existsSync(actual))
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
48
57
|
try {
|
|
49
|
-
return parseJsonc(fs.readFileSync(
|
|
58
|
+
return parseJsonc(fs.readFileSync(actual, "utf-8"));
|
|
50
59
|
}
|
|
51
60
|
catch (e) {
|
|
52
|
-
console.error(`Failed to read ${
|
|
61
|
+
console.error(`Failed to read ${actual}: ${e.message}`);
|
|
53
62
|
return null;
|
|
54
63
|
}
|
|
55
64
|
}
|
|
@@ -44,7 +44,9 @@ export declare class MailxDB {
|
|
|
44
44
|
bodyPath: string;
|
|
45
45
|
}): number;
|
|
46
46
|
getMessages(query: MessageQuery): PagedResult<MessageEnvelope>;
|
|
47
|
-
|
|
47
|
+
/** Unified inbox: all inbox folders across accounts, sorted by date, paginated in SQL */
|
|
48
|
+
getUnifiedInbox(page?: number, pageSize?: number): PagedResult<MessageEnvelope>;
|
|
49
|
+
getMessageByUid(accountId: string, uid: number, folderId?: number): MessageEnvelope;
|
|
48
50
|
getMessageBodyPath(accountId: string, uid: number): string;
|
|
49
51
|
updateMessageFlags(accountId: string, uid: number, flags: string[]): void;
|
|
50
52
|
getHighestUid(accountId: string, folderId: number): number;
|
|
@@ -52,6 +54,8 @@ export declare class MailxDB {
|
|
|
52
54
|
getUidsForFolder(accountId: string, folderId: number): number[];
|
|
53
55
|
/** Delete a message by account + UID */
|
|
54
56
|
deleteMessage(accountId: string, uid: number): void;
|
|
57
|
+
/** Recalculate folder total/unread counts from actual messages */
|
|
58
|
+
recalcFolderCounts(folderId: number): void;
|
|
55
59
|
/** Bulk insert within a transaction for sync performance */
|
|
56
60
|
beginTransaction(): void;
|
|
57
61
|
commitTransaction(): void;
|
|
@@ -241,8 +241,43 @@ export class MailxDB {
|
|
|
241
241
|
}));
|
|
242
242
|
return { items, total, page, pageSize };
|
|
243
243
|
}
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
/** Unified inbox: all inbox folders across accounts, sorted by date, paginated in SQL */
|
|
245
|
+
getUnifiedInbox(page = 1, pageSize = 50) {
|
|
246
|
+
const offset = (page - 1) * pageSize;
|
|
247
|
+
// Find all inbox folder IDs
|
|
248
|
+
const inboxRows = this.db.prepare("SELECT id FROM folders WHERE special_use = 'inbox'").all();
|
|
249
|
+
if (inboxRows.length === 0)
|
|
250
|
+
return { items: [], total: 0, page, pageSize };
|
|
251
|
+
const placeholders = inboxRows.map(() => "?").join(",");
|
|
252
|
+
const folderIds = inboxRows.map((r) => r.id);
|
|
253
|
+
const total = this.db.prepare(`SELECT COUNT(*) as cnt FROM messages WHERE folder_id IN (${placeholders})`).get(...folderIds).cnt;
|
|
254
|
+
const rows = this.db.prepare(`SELECT * FROM messages WHERE folder_id IN (${placeholders}) ORDER BY date DESC LIMIT ? OFFSET ?`).all(...folderIds, pageSize, offset);
|
|
255
|
+
const items = rows.map(r => ({
|
|
256
|
+
id: r.id,
|
|
257
|
+
accountId: r.account_id,
|
|
258
|
+
folderId: r.folder_id,
|
|
259
|
+
uid: r.uid,
|
|
260
|
+
messageId: r.message_id || "",
|
|
261
|
+
inReplyTo: r.in_reply_to || "",
|
|
262
|
+
references: JSON.parse(r.refs || "[]"),
|
|
263
|
+
date: r.date,
|
|
264
|
+
subject: r.subject,
|
|
265
|
+
from: { name: r.from_name, address: r.from_address },
|
|
266
|
+
to: JSON.parse(r.to_json),
|
|
267
|
+
cc: JSON.parse(r.cc_json),
|
|
268
|
+
flags: JSON.parse(r.flags_json),
|
|
269
|
+
size: r.size,
|
|
270
|
+
hasAttachments: !!r.has_attachments,
|
|
271
|
+
preview: r.preview
|
|
272
|
+
}));
|
|
273
|
+
return { items, total, page, pageSize };
|
|
274
|
+
}
|
|
275
|
+
getMessageByUid(accountId, uid, folderId) {
|
|
276
|
+
const sql = folderId != null
|
|
277
|
+
? "SELECT * FROM messages WHERE account_id = ? AND uid = ? AND folder_id = ?"
|
|
278
|
+
: "SELECT * FROM messages WHERE account_id = ? AND uid = ?";
|
|
279
|
+
const params = folderId != null ? [accountId, uid, folderId] : [accountId, uid];
|
|
280
|
+
const r = this.db.prepare(sql).get(...params);
|
|
246
281
|
if (!r)
|
|
247
282
|
return null;
|
|
248
283
|
return {
|
|
@@ -282,7 +317,19 @@ export class MailxDB {
|
|
|
282
317
|
}
|
|
283
318
|
/** Delete a message by account + UID */
|
|
284
319
|
deleteMessage(accountId, uid) {
|
|
320
|
+
// Get folderId before deleting so we can update counts
|
|
321
|
+
const msg = this.db.prepare("SELECT folder_id FROM messages WHERE account_id = ? AND uid = ?").get(accountId, uid);
|
|
285
322
|
this.db.prepare("DELETE FROM messages WHERE account_id = ? AND uid = ?").run(accountId, uid);
|
|
323
|
+
// Refresh folder counts
|
|
324
|
+
if (msg)
|
|
325
|
+
this.recalcFolderCounts(msg.folder_id);
|
|
326
|
+
}
|
|
327
|
+
/** Recalculate folder total/unread counts from actual messages */
|
|
328
|
+
recalcFolderCounts(folderId) {
|
|
329
|
+
const counts = this.db.prepare(`SELECT COUNT(*) as total,
|
|
330
|
+
SUM(CASE WHEN flags_json NOT LIKE '%\\\\Seen%' THEN 1 ELSE 0 END) as unread
|
|
331
|
+
FROM messages WHERE folder_id = ?`).get(folderId);
|
|
332
|
+
this.updateFolderCounts(folderId, counts?.total || 0, counts?.unread || 0);
|
|
286
333
|
}
|
|
287
334
|
/** Bulk insert within a transaction for sync performance */
|
|
288
335
|
beginTransaction() { this.db.exec("BEGIN"); }
|
|
@@ -401,19 +448,24 @@ export class MailxDB {
|
|
|
401
448
|
subject, from_name, from_address, to_text, cc_text, body_text,
|
|
402
449
|
content=messages, content_rowid=id
|
|
403
450
|
)`);
|
|
451
|
+
// Use a single transaction + prepared statement for speed (~50x faster than individual inserts)
|
|
452
|
+
const insert = this.db.prepare("INSERT INTO messages_fts (rowid, subject, from_name, from_address, to_text, cc_text, body_text) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
404
453
|
const rows = this.db.prepare("SELECT id, subject, from_name, from_address, to_json, cc_json, preview FROM messages").all();
|
|
405
454
|
let count = 0;
|
|
406
|
-
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
455
|
+
const batchInsert = this.db.transaction(() => {
|
|
456
|
+
for (const r of rows) {
|
|
457
|
+
const to = JSON.parse(r.to_json || "[]");
|
|
458
|
+
const cc = JSON.parse(r.cc_json || "[]");
|
|
459
|
+
const toText = to.map((a) => `${a.name} ${a.address}`).join(" ");
|
|
460
|
+
const ccText = cc.map((a) => `${a.name} ${a.address}`).join(" ");
|
|
461
|
+
try {
|
|
462
|
+
insert.run(r.id, r.subject, r.from_name, r.from_address, toText, ccText, r.preview);
|
|
463
|
+
count++;
|
|
464
|
+
}
|
|
465
|
+
catch { /* skip duplicates */ }
|
|
414
466
|
}
|
|
415
|
-
|
|
416
|
-
|
|
467
|
+
});
|
|
468
|
+
batchInsert();
|
|
417
469
|
return count;
|
|
418
470
|
}
|
|
419
471
|
// ── Sync Actions ──
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* File-per-message body storage backend.
|
|
3
|
-
* Messages stored as: {basePath}/{accountId}/{
|
|
4
|
-
*
|
|
3
|
+
* Messages stored as: {basePath}/{accountId}/{folderId}/{uid}.eml
|
|
4
|
+
* Folder IDs are numeric (from SQLite), not names.
|
|
5
5
|
*/
|
|
6
6
|
import type { MessageStore } from "@bobfrankston/mailx-types";
|
|
7
7
|
export declare class FileMessageStore implements MessageStore {
|
|
8
8
|
private basePath;
|
|
9
|
-
private folderNames;
|
|
10
9
|
constructor(basePath: string);
|
|
11
|
-
/** Register folder ID → path mapping for human-readable directory names */
|
|
12
|
-
registerFolder(folderId: number, folderPath: string): void;
|
|
13
|
-
private folderDir;
|
|
14
10
|
private messagePath;
|
|
15
|
-
/** Check legacy path (numeric folder ID) */
|
|
16
|
-
private legacyPath;
|
|
17
11
|
putMessage(accountId: string, folderId: number, uid: number, raw: Buffer): Promise<string>;
|
|
18
12
|
getMessage(accountId: string, folderId: number, uid: number): Promise<Buffer>;
|
|
19
13
|
deleteMessage(accountId: string, folderId: number, uid: number): Promise<void>;
|
|
@@ -1,34 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* File-per-message body storage backend.
|
|
3
|
-
* Messages stored as: {basePath}/{accountId}/{
|
|
4
|
-
*
|
|
3
|
+
* Messages stored as: {basePath}/{accountId}/{folderId}/{uid}.eml
|
|
4
|
+
* Folder IDs are numeric (from SQLite), not names.
|
|
5
5
|
*/
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as path from "node:path";
|
|
8
|
-
/** Sanitize folder path for use as directory name — replace delimiters with _ */
|
|
9
|
-
function sanitizeFolderName(folderPath) {
|
|
10
|
-
return folderPath.replace(/[\/\\.:]/g, "_");
|
|
11
|
-
}
|
|
12
8
|
export class FileMessageStore {
|
|
13
9
|
basePath;
|
|
14
|
-
folderNames = new Map();
|
|
15
10
|
constructor(basePath) {
|
|
16
11
|
this.basePath = basePath;
|
|
17
12
|
fs.mkdirSync(basePath, { recursive: true });
|
|
18
13
|
}
|
|
19
|
-
/** Register folder ID → path mapping for human-readable directory names */
|
|
20
|
-
registerFolder(folderId, folderPath) {
|
|
21
|
-
this.folderNames.set(folderId, sanitizeFolderName(folderPath));
|
|
22
|
-
}
|
|
23
|
-
folderDir(accountId, folderId) {
|
|
24
|
-
const name = this.folderNames.get(folderId) || String(folderId);
|
|
25
|
-
return path.join(this.basePath, accountId, name);
|
|
26
|
-
}
|
|
27
14
|
messagePath(accountId, folderId, uid) {
|
|
28
|
-
return path.join(this.folderDir(accountId, folderId), `${uid}.eml`);
|
|
29
|
-
}
|
|
30
|
-
/** Check legacy path (numeric folder ID) */
|
|
31
|
-
legacyPath(accountId, folderId, uid) {
|
|
32
15
|
return path.join(this.basePath, accountId, String(folderId), `${uid}.eml`);
|
|
33
16
|
}
|
|
34
17
|
async putMessage(accountId, folderId, uid, raw) {
|
|
@@ -38,22 +21,15 @@ export class FileMessageStore {
|
|
|
38
21
|
return filePath;
|
|
39
22
|
}
|
|
40
23
|
async getMessage(accountId, folderId, uid) {
|
|
41
|
-
|
|
42
|
-
if (fs.existsSync(filePath))
|
|
43
|
-
return fs.readFileSync(filePath);
|
|
44
|
-
// Fallback to legacy path
|
|
45
|
-
const legacy = this.legacyPath(accountId, folderId, uid);
|
|
46
|
-
return fs.readFileSync(legacy);
|
|
24
|
+
return fs.readFileSync(this.messagePath(accountId, folderId, uid));
|
|
47
25
|
}
|
|
48
26
|
async deleteMessage(accountId, folderId, uid) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
27
|
+
const filePath = this.messagePath(accountId, folderId, uid);
|
|
28
|
+
if (fs.existsSync(filePath))
|
|
29
|
+
fs.unlinkSync(filePath);
|
|
53
30
|
}
|
|
54
31
|
async hasMessage(accountId, folderId, uid) {
|
|
55
|
-
return fs.existsSync(this.messagePath(accountId, folderId, uid))
|
|
56
|
-
fs.existsSync(this.legacyPath(accountId, folderId, uid));
|
|
32
|
+
return fs.existsSync(this.messagePath(accountId, folderId, uid));
|
|
57
33
|
}
|
|
58
34
|
}
|
|
59
35
|
//# sourceMappingURL=file-store.js.map
|
|
@@ -8,7 +8,8 @@ export type AuthMethod = "password" | "oauth2";
|
|
|
8
8
|
/** Mail account configuration */
|
|
9
9
|
export interface AccountConfig {
|
|
10
10
|
id: string; /** Unique account identifier (e.g., "iecc", "gmail-bob") */
|
|
11
|
-
name: string; /**
|
|
11
|
+
name: string; /** Sender name for From header (e.g., "Bob Frankston") */
|
|
12
|
+
label?: string; /** UI label for account list (e.g., "Gmail"). Falls back to name if not set */
|
|
12
13
|
email: string; /** Email address */
|
|
13
14
|
imap: {
|
|
14
15
|
host: string;
|
|
@@ -28,6 +29,7 @@ export interface AccountConfig {
|
|
|
28
29
|
password?: string;
|
|
29
30
|
};
|
|
30
31
|
enabled: boolean;
|
|
32
|
+
defaultSend?: boolean; /** Use this account's SMTP when From doesn't match any account */
|
|
31
33
|
}
|
|
32
34
|
/** Standard IMAP special-use folder types */
|
|
33
35
|
export type SpecialUse = "inbox" | "sent" | "drafts" | "trash" | "junk" | "archive" | "all";
|