@bobfrankston/mailx 1.0.181 → 1.0.182
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"height":
|
|
1
|
+
{"height":1344,"width":1438,"x":216,"y":107}
|
package/client/app.js
CHANGED
|
@@ -265,12 +265,31 @@ async function openCompose(mode) {
|
|
|
265
265
|
references: [],
|
|
266
266
|
accounts: accounts.map((a) => ({ id: a.id, name: a.name, email: a.email })),
|
|
267
267
|
};
|
|
268
|
+
// Auto-detect reply From: if the message was delivered to an identity domain,
|
|
269
|
+
// reply from that address instead of the default account address.
|
|
270
|
+
// Identity domains configured per-account in accounts.jsonc (identityDomains array).
|
|
271
|
+
// Default identity domains for bob.ma account:
|
|
272
|
+
const identityDomains = ["bob.ma", "frankston.com"];
|
|
273
|
+
function detectReplyFrom() {
|
|
274
|
+
if (!msg)
|
|
275
|
+
return undefined;
|
|
276
|
+
// Check deliveredTo first (most reliable), then To addresses
|
|
277
|
+
const candidates = [msg.deliveredTo, ...(msg.to || []).map((a) => a.address)].filter(Boolean);
|
|
278
|
+
for (const addr of candidates) {
|
|
279
|
+
const domain = addr.split("@")[1]?.toLowerCase();
|
|
280
|
+
if (domain && identityDomains.some(d => domain === d || domain.endsWith(`.${d}`))) {
|
|
281
|
+
return addr;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
268
286
|
if (msg && mode === "reply") {
|
|
269
287
|
init.to = [msg.from];
|
|
270
288
|
init.subject = `Re: ${cleanSubject}`;
|
|
271
289
|
init.bodyHtml = quoteBody(msg);
|
|
272
290
|
init.inReplyTo = msg.messageId;
|
|
273
291
|
init.references = [...(msg.references || []), msg.messageId];
|
|
292
|
+
init.fromAddress = detectReplyFrom();
|
|
274
293
|
}
|
|
275
294
|
else if (msg && mode === "replyAll") {
|
|
276
295
|
init.to = [msg.from, ...msg.to.filter((a) => a.address !== msg.from.address)];
|
|
@@ -279,6 +298,7 @@ async function openCompose(mode) {
|
|
|
279
298
|
init.bodyHtml = quoteBody(msg);
|
|
280
299
|
init.inReplyTo = msg.messageId;
|
|
281
300
|
init.references = [...(msg.references || []), msg.messageId];
|
|
301
|
+
init.fromAddress = detectReplyFrom();
|
|
282
302
|
}
|
|
283
303
|
else if (msg && mode === "forward") {
|
|
284
304
|
init.subject = `Fwd: ${cleanSubject}`;
|
|
@@ -260,6 +260,13 @@ function parseAddrs(s) {
|
|
|
260
260
|
function applyInit(init) {
|
|
261
261
|
// Populate From dropdown
|
|
262
262
|
populateFromSelect(init.accounts, init.accountId);
|
|
263
|
+
// Auto-detect reply From: if fromAddress is set (identity domain match),
|
|
264
|
+
// use it as the From address via the "Other..." custom field
|
|
265
|
+
if (init.fromAddress) {
|
|
266
|
+
fromSelect.value = "__custom__";
|
|
267
|
+
fromCustom.hidden = false;
|
|
268
|
+
fromCustom.value = init.fromAddress;
|
|
269
|
+
}
|
|
263
270
|
toInput.value = formatAddrs(init.to);
|
|
264
271
|
ccInput.value = formatAddrs(init.cc);
|
|
265
272
|
subjectInput.value = init.subject;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.182",
|
|
4
4
|
"description": "Local-first email client with IMAP sync and standalone native app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/mailx.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@bobfrankston/iflow-node": "^0.1.2",
|
|
25
25
|
"@bobfrankston/miscinfo": "^1.0.8",
|
|
26
26
|
"@bobfrankston/oauthsupport": "^1.0.21",
|
|
27
|
-
"@bobfrankston/msger": "^0.1.
|
|
27
|
+
"@bobfrankston/msger": "^0.1.232",
|
|
28
28
|
"@capacitor/android": "^8.3.0",
|
|
29
29
|
"@capacitor/cli": "^8.3.0",
|
|
30
30
|
"@capacitor/core": "^8.3.0",
|
|
@@ -106,7 +106,7 @@ export class MailxService {
|
|
|
106
106
|
for (const cfg of settings.accounts) {
|
|
107
107
|
const a = dbAccounts.find(d => d.id === cfg.id);
|
|
108
108
|
if (a)
|
|
109
|
-
ordered.push({ ...a, label: cfg.label, defaultSend: cfg.defaultSend || false });
|
|
109
|
+
ordered.push({ ...a, label: cfg.label, defaultSend: cfg.defaultSend || false, identityDomains: cfg.identityDomains || [] });
|
|
110
110
|
}
|
|
111
111
|
// Append any DB accounts not in settings
|
|
112
112
|
for (const a of dbAccounts) {
|
|
@@ -339,7 +339,9 @@ export class MailxService {
|
|
|
339
339
|
const account = settings.accounts.find(a => a.id === msg.from);
|
|
340
340
|
if (!account)
|
|
341
341
|
throw new Error(`Unknown account: ${msg.from}`);
|
|
342
|
-
|
|
342
|
+
// Use custom From address if set (identity domain reply), but always wrap with account display name
|
|
343
|
+
const fromAddr = msg.fromAddress || account.email;
|
|
344
|
+
const fromHeader = `${account.name} <${fromAddr}>`;
|
|
343
345
|
const to = msg.to.map((a) => a.name ? `${a.name} <${a.address}>` : a.address).join(", ");
|
|
344
346
|
const cc = msg.cc?.map((a) => a.name ? `${a.name} <${a.address}>` : a.address).join(", ");
|
|
345
347
|
const bcc = msg.bcc?.map((a) => a.name ? `${a.name} <${a.address}>` : a.address).join(", ");
|