@bobfrankston/mailx 1.0.13 → 1.0.14

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.
Files changed (84) hide show
  1. package/bin/mailx.js +8 -2
  2. package/client/app.js +20 -17
  3. package/client/components/message-list.js +30 -2
  4. package/client/index.html +20 -15
  5. package/client/lib/api-client.js +11 -2
  6. package/client/styles/components.css +18 -1
  7. package/launcher/bin/mailx-app-linux +0 -0
  8. package/launcher/bin/mailx-app.exe +0 -0
  9. package/launcher/builder/build-config.json +11 -0
  10. package/launcher/builder/postinstall.js +81 -0
  11. package/package.json +2 -4
  12. package/packages/mailx-api/index.js +46 -3
  13. package/packages/mailx-imap/index.d.ts +2 -0
  14. package/packages/mailx-imap/index.js +13 -0
  15. package/packages/mailx-store/db.d.ts +1 -1
  16. package/packages/mailx-store/db.js +14 -4
  17. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Breadcrumbs +0 -0
  18. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Crashpad/metadata +0 -0
  19. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Crashpad/settings.dat +0 -0
  20. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Crashpad/throttle_store.dat +0 -1
  21. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/CrashpadMetrics-active.pma +0 -0
  22. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/BrowsingTopicsSiteData +0 -0
  23. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Cache/No_Vary_Search/journal.baj +0 -1
  24. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/DIPS +0 -0
  25. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/DashTrackerDatabase +0 -0
  26. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/EdgeJourneys/EdgeJourneys.db +0 -0
  27. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Rules/LOCK +0 -0
  28. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Rules/LOG +0 -3
  29. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Rules/MANIFEST-000001 +0 -0
  30. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Scripts/LOCK +0 -0
  31. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Scripts/LOG +0 -3
  32. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension Scripts/MANIFEST-000001 +0 -0
  33. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension State/LOCK +0 -0
  34. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension State/LOG +0 -3
  35. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Extension State/MANIFEST-000001 +0 -0
  36. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/ExtensionActivityComp +0 -0
  37. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/ExtensionActivityEdge +0 -0
  38. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Favicons +0 -0
  39. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/History +0 -0
  40. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/History-journal +0 -0
  41. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/IndexedDB/devtools_devtools_0.indexeddb.leveldb/LOCK +0 -0
  42. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/IndexedDB/devtools_devtools_0.indexeddb.leveldb/LOG +0 -3
  43. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/IndexedDB/devtools_devtools_0.indexeddb.leveldb/MANIFEST-000001 +0 -0
  44. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOCK +0 -0
  45. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Local Storage/leveldb/LOG +0 -3
  46. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Local Storage/leveldb/MANIFEST-000001 +0 -0
  47. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Login Data +0 -0
  48. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Login Data For Account +0 -0
  49. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network/Cookies +0 -0
  50. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network/Reporting and NEL +0 -0
  51. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network/Trust Tokens +0 -0
  52. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Network Action Predictor +0 -0
  53. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Preferences +0 -1
  54. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Safe Browsing Network/Safe Browsing Cookies +0 -0
  55. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/ServerCertificate +0 -0
  56. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Session Storage/LOCK +0 -0
  57. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Session Storage/LOG +0 -3
  58. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Session Storage/MANIFEST-000001 +0 -0
  59. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Shared Dictionary/db +0 -0
  60. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/SharedStorage +0 -0
  61. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Shortcuts +0 -0
  62. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOCK +0 -0
  63. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Site Characteristics Database/LOG +0 -3
  64. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Site Characteristics Database/MANIFEST-000001 +0 -0
  65. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOCK +0 -0
  66. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/LOG +0 -3
  67. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Sync Data/LevelDB/MANIFEST-000001 +0 -0
  68. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Top Sites +0 -0
  69. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Vpn Tokens +0 -0
  70. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Web Data +0 -0
  71. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/Web Data-journal +0 -0
  72. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager +0 -0
  73. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/WebStorage/QuotaManager-journal +0 -0
  74. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/heavy_ad_intervention_opt_out.db +0 -0
  75. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/LOCK +0 -0
  76. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/LOG +0 -3
  77. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/MANIFEST-000001 +0 -0
  78. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOCK +0 -0
  79. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/LOG +0 -3
  80. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Default/shared_proto_db/metadata/MANIFEST-000001 +0 -0
  81. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/DeferredBrowserMetrics/BrowserMetrics-69CAD063-BE24.pma +0 -0
  82. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Local State +0 -1
  83. package/launcher/bin/mailx-app.exe.WebView2/EBWebView/Variations +0 -1
  84. package/launcher/bin/mailx-app.old.exe +0 -0
package/bin/mailx.js CHANGED
@@ -58,9 +58,15 @@ async function main() {
58
58
  }
59
59
  } else {
60
60
  // Default: launch native WebView app with IPC
61
+ // Platform-specific binary naming (matches msger pattern)
62
+ let binaryName;
63
+ if (process.platform === "win32") binaryName = "mailx-app.exe";
64
+ else if (process.platform === "darwin") binaryName = process.arch === "arm64" ? "mailx-app-arm64" : "mailx-app";
65
+ else binaryName = process.arch === "arm64" ? "mailx-app-linux-aarch64" : "mailx-app-linux";
66
+
61
67
  const launcherPaths = [
62
- path.join(import.meta.dirname, "..", "launcher", "bin", "mailx-app.exe"),
63
- path.join(import.meta.dirname, "..", "launcher", "target", "debug", "mailx-app.exe"),
68
+ path.join(import.meta.dirname, "..", "launcher", "bin", binaryName),
69
+ path.join(import.meta.dirname, "..", "launcher", "target", "release", binaryName),
64
70
  ];
65
71
 
66
72
  let launcherPath = launcherPaths.find(p => fs.existsSync(p));
package/client/app.js CHANGED
@@ -11,6 +11,8 @@ const folderTree = document.getElementById("folder-tree");
11
11
  let currentFolderSpecialUse = "";
12
12
  initFolderTree(folderTree, (accountId, folderId, folderName, specialUse) => {
13
13
  currentFolderSpecialUse = specialUse;
14
+ currentAccountId = accountId;
15
+ currentFolderId = folderId;
14
16
  loadMessages(accountId, folderId, 1, specialUse);
15
17
  document.title = `mailx - ${folderName}`;
16
18
  }, () => {
@@ -207,29 +209,30 @@ document.getElementById("btn-forward")?.addEventListener("click", () => openComp
207
209
  // ── Search ──
208
210
  let searchTimeout;
209
211
  const searchInput = document.getElementById("search-input");
212
+ const searchScope = document.getElementById("search-scope");
213
+ function doSearch() {
214
+ const query = searchInput.value.trim();
215
+ if (query.length < 2) {
216
+ if (query.length === 0)
217
+ reloadCurrentFolder();
218
+ return;
219
+ }
220
+ const scope = searchScope?.value || "all";
221
+ // For "current" and "server" scopes, pass the active folder context
222
+ loadSearchResults(query, scope, currentAccountId, currentFolderId);
223
+ document.title = `mailx - Search: ${query}`;
224
+ }
225
+ // Track current folder for scoped search
226
+ let currentAccountId = "";
227
+ let currentFolderId = 0;
210
228
  searchInput?.addEventListener("input", () => {
211
229
  clearTimeout(searchTimeout);
212
- searchTimeout = setTimeout(() => {
213
- const query = searchInput.value.trim();
214
- if (query.length >= 2) {
215
- loadSearchResults(query);
216
- document.title = `mailx - Search: ${query}`;
217
- }
218
- else if (query.length === 0) {
219
- // Clear search — reload current folder
220
- reloadCurrentFolder();
221
- }
222
- }, 400);
230
+ searchTimeout = setTimeout(doSearch, 400);
223
231
  });
224
- // Enter triggers immediate search
225
232
  searchInput?.addEventListener("keydown", (e) => {
226
233
  if (e.key === "Enter") {
227
234
  clearTimeout(searchTimeout);
228
- const query = searchInput.value.trim();
229
- if (query) {
230
- loadSearchResults(query);
231
- document.title = `mailx - Search: ${query}`;
232
- }
235
+ doSearch();
233
236
  }
234
237
  if (e.key === "Escape") {
235
238
  searchInput.value = "";
@@ -140,7 +140,7 @@ export async function loadUnifiedInbox() {
140
140
  }
141
141
  }
142
142
  /** Load search results */
143
- export async function loadSearchResults(query) {
143
+ export async function loadSearchResults(query, scope = "all", accountId = "", folderId = 0) {
144
144
  clearFilter();
145
145
  searchMode = true;
146
146
  unifiedMode = false;
@@ -152,7 +152,35 @@ export async function loadSearchResults(query) {
152
152
  return;
153
153
  body.innerHTML = `<div class="ml-empty">Searching...</div>`;
154
154
  try {
155
- const result = await searchMessages(query, 1);
155
+ // Regex search: filter client-side
156
+ if (query.startsWith("/") && query.endsWith("/") && query.length > 2) {
157
+ const pattern = query.slice(1, -1);
158
+ let regex;
159
+ try {
160
+ regex = new RegExp(pattern, "i");
161
+ }
162
+ catch {
163
+ body.innerHTML = `<div class="ml-empty">Invalid regex</div>`;
164
+ return;
165
+ }
166
+ // Get all messages from current context and filter
167
+ const source = scope === "current" && accountId
168
+ ? await getMessages(accountId, folderId, 1, 10000)
169
+ : await searchMessages("*", 1, 10000, "all");
170
+ const matches = source.items.filter((m) => regex.test(m.subject || "") || regex.test(m.from?.name || "") || regex.test(m.from?.address || "") || regex.test(m.preview || ""));
171
+ totalMessages = matches.length;
172
+ if (matches.length === 0) {
173
+ body.innerHTML = `<div class="ml-empty">No regex matches</div>`;
174
+ return;
175
+ }
176
+ body.innerHTML = "";
177
+ appendMessages(body, "", matches);
178
+ const firstRow = body.querySelector(".ml-row");
179
+ if (firstRow)
180
+ firstRow.click();
181
+ return;
182
+ }
183
+ const result = await searchMessages(query, 1, 50, scope, accountId, folderId);
156
184
  totalMessages = result.total;
157
185
  if (result.items.length === 0) {
158
186
  body.innerHTML = `<div class="ml-empty">No results for "${query}"</div>`;
package/client/index.html CHANGED
@@ -13,24 +13,24 @@
13
13
  <body>
14
14
  <header class="toolbar">
15
15
  <div class="toolbar-left">
16
- <button class="tb-btn" id="btn-compose" title="Compose">
17
- <span class="tb-icon">&#x270F;</span> Compose
16
+ <button class="tb-btn" id="btn-compose" title="Compose (Ctrl+N)">
17
+ <span class="tb-icon">✏</span> Compose
18
18
  </button>
19
- <button class="tb-btn" id="btn-reply" title="Reply" disabled>
20
- <span class="tb-icon">&#x21A9;</span>
19
+ <button class="tb-btn" id="btn-reply" title="Reply (Ctrl+R)" disabled>
20
+ <span class="tb-icon">↩</span>
21
21
  </button>
22
- <button class="tb-btn" id="btn-reply-all" title="Reply All" disabled>
23
- <span class="tb-icon">&#x21A9;&#x21A9;</span>
22
+ <button class="tb-btn" id="btn-reply-all" title="Reply All (Ctrl+Shift+R)" disabled>
23
+ <span class="tb-icon">↩↩</span>
24
24
  </button>
25
25
  <button class="tb-btn" id="btn-forward" title="Forward" disabled>
26
- <span class="tb-icon">&#x2192;</span>
26
+ <span class="tb-icon">→</span>
27
27
  </button>
28
28
  <span class="tb-sep"></span>
29
- <button class="tb-btn" id="btn-delete" title="Delete" disabled>
30
- <span class="tb-icon">&#x1F5D1;</span>
29
+ <button class="tb-btn" id="btn-delete" title="Delete (Del)" disabled>
30
+ <span class="tb-icon">🗑</span>
31
31
  </button>
32
32
  <button class="tb-btn" id="btn-flag" title="Flag" disabled>
33
- <span class="tb-icon">&#x2691;</span>
33
+ <span class="tb-icon">⚑</span>
34
34
  </button>
35
35
  </div>
36
36
  <div class="toolbar-center">
@@ -45,14 +45,19 @@
45
45
  <span id="app-version" class="app-version"></span>
46
46
  </div>
47
47
  <div class="toolbar-right">
48
- <search>
49
- <input type="search" id="search-input" placeholder="Search..." autocomplete="off">
48
+ <search class="search-bar">
49
+ <select id="search-scope" title="Search scope">
50
+ <option value="all">All folders</option>
51
+ <option value="current">This folder</option>
52
+ <option value="server">IMAP server</option>
53
+ </select>
54
+ <input type="search" id="search-input" placeholder="Search... (/regex/)" autocomplete="off" title="Search messages. /pattern/ for regex. Qualifiers: from: to: subject:">
50
55
  </search>
51
56
  <button class="tb-btn" id="btn-sync" title="Sync all folders (F5)">
52
- <span class="tb-icon">&#x21BB;</span> Sync
57
+ <span class="tb-icon">↻</span> Sync
53
58
  </button>
54
59
  <button class="tb-btn" id="btn-restart" title="Restart server and reload page">
55
- <span class="tb-icon">&#x26A1;</span> Restart
60
+ <span class="tb-icon">⚡</span> Restart
56
61
  </button>
57
62
  </div>
58
63
  </header>
@@ -92,7 +97,7 @@
92
97
  <div class="mv-to"></div>
93
98
  </div>
94
99
  <div class="mv-header-actions">
95
- <button class="mv-action mv-action-primary" id="mv-edit-draft" hidden>Edit &amp; Send</button>
100
+ <button class="mv-action mv-action-primary" id="mv-edit-draft" hidden>Edit & Send</button>
96
101
  <a class="mv-unsubscribe" id="mv-unsubscribe" hidden>Unsubscribe</a>
97
102
  <button class="mv-action" id="mv-view-source" title="View source (.eml)" hidden>Source</button>
98
103
  </div>
@@ -52,10 +52,19 @@ export function getUnifiedInbox(page = 1, pageSize = 50) {
52
52
  const signal = newMessageListSignal();
53
53
  return api(`/messages/unified/inbox?page=${page}&pageSize=${pageSize}`, { signal });
54
54
  }
55
- export function searchMessages(query, page = 1, pageSize = 50) {
55
+ export function searchMessages(query, page = 1, pageSize = 50, scope = "all", accountId = "", folderId = 0) {
56
56
  if (hasIPC)
57
57
  return mailxapi.searchMessages(query, page, pageSize);
58
- return api(`/search?q=${encodeURIComponent(query)}&page=${page}&pageSize=${pageSize}`);
58
+ const params = new URLSearchParams({ q: query, page: String(page), pageSize: String(pageSize), scope });
59
+ if (scope === "current" && accountId) {
60
+ params.set("accountId", accountId);
61
+ params.set("folderId", String(folderId));
62
+ }
63
+ if (scope === "server" && accountId) {
64
+ params.set("accountId", accountId);
65
+ params.set("folderId", String(folderId));
66
+ }
67
+ return api(`/search?${params}`);
59
68
  }
60
69
  export function getMessage(accountId, uid, allowRemote = false, folderId) {
61
70
  if (hasIPC)
@@ -68,10 +68,27 @@
68
68
  .tb-menu-item input[type="checkbox"] { accent-color: var(--color-accent); }
69
69
  .tb-sep { width: 1px; height: 1.2rem; background: var(--color-border); margin: 0 var(--gap-xs); }
70
70
 
71
+ .search-bar {
72
+ display: flex;
73
+ align-items: center;
74
+ gap: 0;
75
+ }
76
+
77
+ #search-scope {
78
+ padding: var(--gap-xs) var(--gap-xs);
79
+ border: 1px solid var(--color-border);
80
+ border-radius: var(--radius-md) 0 0 var(--radius-md);
81
+ background: var(--color-bg-surface);
82
+ color: var(--color-text);
83
+ font-size: var(--font-size-sm);
84
+ border-right: none;
85
+ cursor: pointer;
86
+ }
87
+
71
88
  #search-input {
72
89
  padding: var(--gap-xs) var(--gap-sm);
73
90
  border: 1px solid var(--color-border);
74
- border-radius: var(--radius-md);
91
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
75
92
  background: var(--color-bg-surface);
76
93
  color: var(--color-text);
77
94
  font-size: var(--font-size-sm);
Binary file
Binary file
@@ -0,0 +1,11 @@
1
+ {
2
+ "platforms": {
3
+ "windows": true,
4
+ "wsl": true,
5
+ "arm64": false
6
+ },
7
+ "options": {
8
+ "release": true,
9
+ "verbose": true
10
+ }
11
+ }
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script to set executable permissions on Linux/Mac binaries
4
+ * and check for required system dependencies (webkit2gtk on Linux).
5
+ */
6
+
7
+ import fs from "fs";
8
+ import path from "path";
9
+ import { execSync } from "child_process";
10
+
11
+ function detectDistro() {
12
+ if (!fs.existsSync("/etc/os-release")) return "unknown";
13
+ try {
14
+ const osRelease = fs.readFileSync("/etc/os-release", "utf8").toLowerCase();
15
+ if (osRelease.includes("ubuntu") || osRelease.includes("debian")) return "debian";
16
+ if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) return "fedora";
17
+ if (osRelease.includes("arch")) return "arch";
18
+ return "unknown";
19
+ } catch { return "unknown"; }
20
+ }
21
+
22
+ function showDependencyHelp(distro) {
23
+ console.warn("\n Missing system dependencies for mailx native launcher.");
24
+ console.warn(" Install required libraries:\n");
25
+ switch (distro) {
26
+ case "debian": console.warn(" sudo apt install libwebkit2gtk-4.1-0 libgtk-3-0\n"); break;
27
+ case "fedora": console.warn(" sudo dnf install webkit2gtk4.1 gtk3\n"); break;
28
+ case "arch": console.warn(" sudo pacman -S webkit2gtk-4.1 gtk3\n"); break;
29
+ default: console.warn(" Install webkit2gtk-4.1 and gtk3 for your distribution\n");
30
+ }
31
+ }
32
+
33
+ function main() {
34
+ if (process.platform === "win32") return;
35
+
36
+ const binDir = path.join(import.meta.dirname, "..", "bin");
37
+ const arch = process.arch;
38
+
39
+ // Binary naming convention (matches msger pattern):
40
+ // Windows: mailx-app.exe
41
+ // macOS x64: mailx-app
42
+ // macOS arm64: mailx-app-arm64
43
+ // Linux x64: mailx-app-linux
44
+ // Linux arm64: mailx-app-linux-aarch64
45
+ let binaryName;
46
+ if (process.platform === "darwin") {
47
+ binaryName = arch === "arm64" ? "mailx-app-arm64" : "mailx-app";
48
+ } else {
49
+ binaryName = arch === "arm64" ? "mailx-app-linux-aarch64" : "mailx-app-linux";
50
+ }
51
+
52
+ const binaryPath = path.join(binDir, binaryName);
53
+
54
+ if (!fs.existsSync(binaryPath)) {
55
+ console.warn(` mailx native launcher not available for ${process.platform} ${arch}`);
56
+ console.warn(" mailx will run in browser mode (server + open browser)");
57
+ return;
58
+ }
59
+
60
+ // Set executable permissions
61
+ try {
62
+ fs.chmodSync(binaryPath, 0o755);
63
+ console.log(` Set execute permissions on ${binaryName}`);
64
+ } catch (e) {
65
+ console.warn(` Could not chmod ${binaryPath}: ${e.message}`);
66
+ }
67
+
68
+ // Check system dependencies on Linux
69
+ if (process.platform === "linux") {
70
+ try {
71
+ const ldd = execSync(`ldd "${binaryPath}" 2>&1`, { encoding: "utf8" });
72
+ if (ldd.includes("not found")) {
73
+ showDependencyHelp(detectDistro());
74
+ }
75
+ } catch {
76
+ console.warn(" Could not check system dependencies");
77
+ }
78
+ }
79
+ }
80
+
81
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -17,13 +17,12 @@
17
17
  "start": "node --watch packages/mailx-server/index.js",
18
18
  "start:prod": "node packages/mailx-server/index.js",
19
19
  "release": "npmglobalize",
20
- "postinstall": "node bin/postinstall.js"
20
+ "postinstall": "node launcher/builder/postinstall.js"
21
21
  },
22
22
  "dependencies": {
23
23
  "@bobfrankston/iflow": "^1.0.2",
24
24
  "@bobfrankston/miscinfo": "^1.0.5",
25
25
  "@bobfrankston/oauthsupport": "^1.0.10",
26
- "@bobfrankston/certsupport": "^1.0.35",
27
26
  "mailparser": "^3.7.2",
28
27
  "quill": "^2.0.3",
29
28
  "express": "^4.21.0",
@@ -52,7 +51,6 @@
52
51
  "@bobfrankston/iflow": "file:../MailApps/iflow",
53
52
  "@bobfrankston/miscinfo": "file:../../projects/npm/miscinfo",
54
53
  "@bobfrankston/oauthsupport": "file:../../projects/oauth/oauthsupport",
55
- "@bobfrankston/certsupport": "file:../../projects/nodejs/certsupport",
56
54
  "mailparser": "^3.7.2",
57
55
  "quill": "^2.0.3",
58
56
  "express": "^4.21.0",
@@ -197,14 +197,57 @@ export function createApiRouter(db, imapManager) {
197
197
  res.json({ ok: true });
198
198
  });
199
199
  // ── Search ──
200
- router.get("/search", (req, res) => {
200
+ router.get("/search", async (req, res) => {
201
201
  const q = req.query.q || "";
202
202
  const page = Number(req.query.page) || 1;
203
203
  const pageSize = Number(req.query.pageSize) || 50;
204
+ const scope = req.query.scope || "all";
205
+ const accountId = req.query.accountId || "";
206
+ const folderId = Number(req.query.folderId) || 0;
204
207
  if (!q.trim())
205
208
  return res.json({ items: [], total: 0, page, pageSize });
206
- const result = db.searchMessages(q, page, pageSize);
207
- res.json(result);
209
+ try {
210
+ if (scope === "server" && accountId) {
211
+ // IMAP server search
212
+ const folders = db.getFolders(accountId);
213
+ const folder = folderId ? folders.find(f => f.id === folderId) : folders.find(f => f.specialUse === "inbox");
214
+ if (!folder)
215
+ return res.json({ items: [], total: 0, page, pageSize });
216
+ const criteria = {};
217
+ // Parse qualifiers
218
+ const fromMatch = q.match(/from:(\S+)/i);
219
+ const toMatch = q.match(/to:(\S+)/i);
220
+ const subjectMatch = q.match(/subject:(.+?)(?:\s+\w+:|$)/i);
221
+ const bodyText = q.replace(/(?:from|to|subject):\S+/gi, "").trim();
222
+ if (fromMatch)
223
+ criteria.from = fromMatch[1];
224
+ if (toMatch)
225
+ criteria.to = toMatch[1];
226
+ if (subjectMatch)
227
+ criteria.subject = subjectMatch[1].trim();
228
+ if (bodyText)
229
+ criteria.body = bodyText;
230
+ const uids = await imapManager.searchOnServer(accountId, folder.path, criteria);
231
+ // Fetch envelopes for matching UIDs from local DB
232
+ const items = uids.slice((page - 1) * pageSize, page * pageSize)
233
+ .map(uid => db.getMessageByUid(accountId, uid, folderId))
234
+ .filter(Boolean);
235
+ res.json({ items, total: uids.length, page, pageSize });
236
+ }
237
+ else if (scope === "current" && accountId && folderId) {
238
+ // Search within current folder only
239
+ const result = db.searchMessages(q, page, pageSize, accountId, folderId);
240
+ res.json(result);
241
+ }
242
+ else {
243
+ // All folders (default)
244
+ const result = db.searchMessages(q, page, pageSize);
245
+ res.json(result);
246
+ }
247
+ }
248
+ catch (e) {
249
+ res.status(500).json({ error: e.message });
250
+ }
208
251
  });
209
252
  router.post("/search/rebuild", (req, res) => {
210
253
  const count = db.rebuildSearchIndex();
@@ -30,6 +30,8 @@ export declare class ImapManager extends EventEmitter {
30
30
  constructor(db: MailxDB);
31
31
  /** Get OAuth access token for an account (for SMTP auth) */
32
32
  getOAuthToken(accountId: string): Promise<string | null>;
33
+ /** Search messages on the IMAP server — returns matching UIDs */
34
+ searchOnServer(accountId: string, mailboxPath: string, criteria: any): Promise<number[]>;
33
35
  /** Create a fresh ImapClient for an account (disposable, single-use) */
34
36
  private createClient;
35
37
  /** Register an account */
@@ -62,6 +62,19 @@ export class ImapManager extends EventEmitter {
62
62
  return null;
63
63
  return config.tokenProvider();
64
64
  }
65
+ /** Search messages on the IMAP server — returns matching UIDs */
66
+ async searchOnServer(accountId, mailboxPath, criteria) {
67
+ const client = this.createClient(accountId);
68
+ try {
69
+ return await client.searchMessages(mailboxPath, criteria);
70
+ }
71
+ finally {
72
+ try {
73
+ await client.logout();
74
+ }
75
+ catch { /* ignore */ }
76
+ }
77
+ }
65
78
  /** Create a fresh ImapClient for an account (disposable, single-use) */
66
79
  createClient(accountId) {
67
80
  const config = this.configs.get(accountId);
@@ -72,7 +72,7 @@ export declare class MailxDB {
72
72
  useCount: number;
73
73
  }[];
74
74
  /** Full-text search across all messages. Supports qualifiers: from:, to:, subject: */
75
- searchMessages(query: string, page?: number, pageSize?: number): PagedResult<MessageEnvelope>;
75
+ searchMessages(query: string, page?: number, pageSize?: number, accountId?: string, folderId?: number): PagedResult<MessageEnvelope>;
76
76
  /** Rebuild FTS index from existing messages */
77
77
  rebuildSearchIndex(): number;
78
78
  /** Queue a local action for later sync to IMAP */
@@ -375,7 +375,7 @@ export class MailxDB {
375
375
  }
376
376
  // ── Search ──
377
377
  /** Full-text search across all messages. Supports qualifiers: from:, to:, subject: */
378
- searchMessages(query, page = 1, pageSize = 50) {
378
+ searchMessages(query, page = 1, pageSize = 50, accountId, folderId) {
379
379
  // Parse qualifiers
380
380
  let ftsQuery = "";
381
381
  const parts = query.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
@@ -405,13 +405,23 @@ export class MailxDB {
405
405
  return { items: [], total: 0, page, pageSize };
406
406
  const offset = (page - 1) * pageSize;
407
407
  try {
408
- const countRow = this.db.prepare("SELECT COUNT(*) as cnt FROM messages_fts WHERE messages_fts MATCH ?").get(ftsQuery);
408
+ let scopeWhere = "";
409
+ const scopeParams = [];
410
+ if (accountId && folderId) {
411
+ scopeWhere = " AND m.account_id = ? AND m.folder_id = ?";
412
+ scopeParams.push(accountId, folderId);
413
+ }
414
+ else if (accountId) {
415
+ scopeWhere = " AND m.account_id = ?";
416
+ scopeParams.push(accountId);
417
+ }
418
+ const countRow = this.db.prepare(`SELECT COUNT(*) as cnt FROM messages m JOIN messages_fts fts ON m.id = fts.rowid WHERE messages_fts MATCH ?${scopeWhere}`).get(ftsQuery, ...scopeParams);
409
419
  const total = countRow?.cnt || 0;
410
420
  const rows = this.db.prepare(`SELECT m.* FROM messages m
411
421
  JOIN messages_fts fts ON m.id = fts.rowid
412
- WHERE messages_fts MATCH ?
422
+ WHERE messages_fts MATCH ?${scopeWhere}
413
423
  ORDER BY m.date DESC
414
- LIMIT ? OFFSET ?`).all(ftsQuery, pageSize, offset);
424
+ LIMIT ? OFFSET ?`).all(ftsQuery, ...scopeParams, pageSize, offset);
415
425
  const items = rows.map(r => ({
416
426
  id: r.id,
417
427
  accountId: r.account_id,
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:48.817 6494 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Extension Rules/MANIFEST-000001
2
- 2026/03/30-12:46:48.821 6494 Recovering log #3
3
- 2026/03/30-12:46:48.823 6494 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Extension Rules/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:49.347 6494 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Extension Scripts/MANIFEST-000001
2
- 2026/03/30-12:46:49.351 6494 Recovering log #3
3
- 2026/03/30-12:46:49.353 6494 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Extension Scripts/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:49.520 6494 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Extension State/MANIFEST-000001
2
- 2026/03/30-12:46:49.525 6494 Recovering log #3
3
- 2026/03/30-12:46:49.529 6494 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Extension State/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-13:02:28.120 1a28 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\IndexedDB\devtools_devtools_0.indexeddb.leveldb/MANIFEST-000001
2
- 2026/03/30-13:02:28.168 1a28 Recovering log #3
3
- 2026/03/30-13:02:28.190 1a28 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\IndexedDB\devtools_devtools_0.indexeddb.leveldb/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:49.225 c2c Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2
- 2026/03/30-12:46:49.311 c2c Recovering log #3
3
- 2026/03/30-12:46:49.348 c2c Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log
@@ -1 +0,0 @@
1
- {"aadc_info":{"age_group":0},"accessibility":{"captions":{"headless_caption_enabled":false}},"account_tracker_service_last_update":"13419318241229246","autocomplete":{"retention_policy_last_version":146},"autofill":{"edge_autofill_advanced_ml_enabled":true,"edge_autofill_purge_low_quality_profiles_by_timeline":false,"last_version_deduped":146},"bookmark":{"storage_computation_last_update":"13419318240722474"},"browser":{"app_window_placement":{"EdgeDevToolsApp":{"always_on_top":false,"bottom":1379,"left":1117,"maximized":false,"right":2917,"top":198,"work_area_bottom":1680,"work_area_left":0,"work_area_right":4096,"work_area_top":0}},"available_dark_theme_options":"All","recent_theme_color_list":[4293914607.0,4293914607.0,4293914607.0,4293914607.0,4293914607.0],"show_toolbar_edge_generic_sidebar_button":false,"user_level_features_context":{}},"browser_content_container_height":1143,"browser_content_container_width":1785,"browser_content_container_x":0,"browser_content_container_y":30,"collections":{"prism_collections":{"policy":{"cached":0}}},"commerce_daily_metrics_last_update_time":"13419318240723076","countryid_at_install":21843,"credentials_enable_service":false,"devtools":{"last_open_timestamp":"13419363747302","preferences":{"closeable-tabs":"{\"security\":true,\"heap-profiler\":true,\"resources\":true,\"lighthouse\":true,\"welcome\":true,\"timeline\":true,\"network\":true,\"cssoverview\":true,\"issues-pane\":true}","cloud-release-notes":"{\"edgeVersion\":146,\"shouldOpenWelcome\":false,\"help\":[{\"title\":\"DevTools documentation\",\"linkId\":\"2196640\",\"localizedAnnouncementKey\":\"helpCard1\",\"iconName\":\"edge-documentation_book_filled\"},{\"title\":\"Overview of all tools\",\"linkId\":\"2196549\",\"localizedAnnouncementKey\":\"helpCard2\",\"iconName\":\"edge-developer-resources\"},{\"title\":\"Use Copilot to explain Console errors\",\"linkId\":\"2257416\",\"localizedAnnouncementKey\":\"helpCard3\",\"iconName\":\"edge-copilot\"},{\"title\":\"Videos about web development with Microsoft Edge\",\"linkId\":\"2196701\",\"localizedAnnouncementKey\":\"helpCard5\",\"iconName\":\"edge-run_command\"},{\"title\":\"Accessibility testing features\",\"linkId\":\"2196801\",\"localizedAnnouncementKey\":\"helpCard6\",\"iconName\":\"edge-documentation_book_filled\"},{\"title\":\"Use the Console tool to track down problems\",\"linkId\":\"2196702\",\"localizedAnnouncementKey\":\"helpCard7\",\"iconName\":\"edge-console\"},{\"title\":\"Modify and debug JS with the Sources tool\",\"linkId\":\"2196900\",\"localizedAnnouncementKey\":\"helpCard8\",\"iconName\":\"edge-sources\"},{\"title\":\"Find source files for a page using the search tool\",\"linkId\":\"2196802\",\"localizedAnnouncementKey\":\"helpCard9\",\"iconName\":\"edge-sources-search-sources-tab\"},{\"title\":\"Microsoft Edge DevTools for Visual Studio Code\",\"linkId\":\"2196901\",\"localizedAnnouncementKey\":\"helpCard10\",\"iconName\":\"edge-help_tooltips\"}],\"releaseNotes\":[],\"header\":{\"localizedKey\":\"highlightsFromTheLatestMicrosoft\",\"title\":\"What's New\"},\"learnHeader\":{\"localizedKey\":\"learnHeader\",\"title\":\"Learn\"},\"allAnnouncementsLinkText\":{\"localizedKey\":\"allAnnouncementsLinkText\",\"title\":\"View all\"},\"whatsNewVideo\":{\"title\":\"What's New in DevTools 115 - 125\",\"subtitle\":\"Check out our video series on the latest and greatest features in DevTools!\",\"linkId\":\"26zDq9Xhz7k\",\"imageName\":\"whats-new-115-125-thumbnail.jpg\",\"imageAltText\":\"A title card for the Microsoft Edge: What's New in DevTools 115 - 125 video\",\"localizedKey\":\"whatsNewVideo\"},\"viewAllLinkId\":\"2353607\",\"localized\":{\"en-US\":{\"panels/edge_welcome/ReleaseNotes.ts | helpCard1\":{\"message\":\"DevTools documentation\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard2\":{\"message\":\"Overview of all tools\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard3\":{\"message\":\"Use Copilot to explain Console errors\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard5\":{\"message\":\"Videos about web development with Microsoft Edge\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard6\":{\"message\":\"Accessibility testing features\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard7\":{\"message\":\"Use the Console tool to track down problems\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard8\":{\"message\":\"Modify and debug JS with the Sources tool\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard9\":{\"message\":\"Find source files for a page using the search tool\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | helpCard10\":{\"message\":\"Microsoft Edge DevTools for Visual Studio Code\",\"description\":\"Title of a help link in a list of help section.\"},\"panels/edge_welcome/ReleaseNotes.ts | learnHeader\":{\"message\":\"Learn\",\"description\":\"Title text of a header bar in the welcome tool.\"},\"panels/edge_welcome/ReleaseNotes.ts | allAnnouncementsLinkText\":{\"message\":\"View all\",\"description\":\"Title text of a header bar in the welcome tool.\"},\"panels/edge_welcome/ReleaseNotes.ts | highlightsFromTheLatestMicrosoft\":{\"message\":\"What's New\",\"description\":\"Title text of a header bar in the welcome tool.\"},\"panels/edge_welcome/ReleaseNotes.ts | whatsNewVideo\":{\"message\":\"What's New in DevTools 115 - 125\",\"description\":\"Title of a video summarizing the latest release, shown next to a description, above a list of release notes.\"},\"panels/edge_welcome/ReleaseNotes.ts | whatsNewVideoDescription\":{\"message\":\"Check out our video series on the latest and greatest features in DevTools!\",\"description\":\"Description of a video link providing further details\"}}}}","console.sidebar-selected-filter":"\"message\"","console.sidebar.width":"{\"vertical\":{\"size\":0,\"showMode\":\"OnlyMain\"}}","edge-inspector.actions-tab-split-view-state":"{\"vertical\":{\"size\":0,\"showMode\":\"Both\"},\"horizontal\":{\"size\":30,\"showMode\":\"Both\"}}","elements.styles.sidebar.width":"{\"vertical\":{\"size\":0,\"showMode\":\"OnlyMain\"}}","inspector.drawer-split-view-state":"{\"horizontal\":{\"size\":0,\"showMode\":\"Both\"}}","inspectorVersion":"40","last-open-view-in-drawer":"\"console\"","panel-selected-tab":"\"elements\"","release-note-version-seen":"146","styles-pane-sidebar-tab-order":"{\"styles\":10,\"computed\":20}","tools-used":"{\"welcome\":1774878404111,\"console-view\":1774890147737,\"elements\":1774890147986}"},"synced_preferences_sync_disabled":{"adorner-settings":"[{\"adorner\":\"ad\",\"isEnabled\":true},{\"adorner\":\"container\",\"isEnabled\":true},{\"adorner\":\"flex\",\"isEnabled\":true},{\"adorner\":\"grid\",\"isEnabled\":true},{\"adorner\":\"grid-lanes\",\"isEnabled\":true},{\"adorner\":\"media\",\"isEnabled\":false},{\"adorner\":\"popover\",\"isEnabled\":true},{\"adorner\":\"reveal\",\"isEnabled\":true},{\"adorner\":\"scroll\",\"isEnabled\":true},{\"adorner\":\"scroll-snap\",\"isEnabled\":true},{\"adorner\":\"slot\",\"isEnabled\":true},{\"adorner\":\"view-source\",\"isEnabled\":true},{\"adorner\":\"starting-style\",\"isEnabled\":true},{\"adorner\":\"subgrid\",\"isEnabled\":true},{\"adorner\":\"top-layer\",\"isEnabled\":true}]","syncedInspectorVersion":"40"}},"edge":{"bookmarks":{"last_dup_info_record_time":"13419318250728140"},"msa_sso_info":{"allow_for_non_msa_profile":true},"profile_sso_info":{"is_msa_first_profile":true,"msa_sso_algo_state":1},"services":{"signin_scoped_device_id":"58f4690e-1674-401c-bb70-661276e077e6"}},"edge_journeys":{"latest_journeys_count":0},"edge_pinning_campaign":{"precomputed_campaign_data":{}},"edge_rewards":{"cache_data":"CAA=","coachmark_promotions":{},"hva_promotions":[],"hva_webui_action_status_dict":{},"refresh_status_muted_until":"13419923040552290"},"edge_ux_config":{"assignmentcontext":"","dataversion":"0","experimentvariables":{},"flights":{}},"edge_vpn":{"available":true},"edge_wallet":{"passwords":{"password_lost_report_date":"13419318270567466"}},"enterprise_profile_guid":"9ab61e7a-49cb-4cfc-b317-a850e236bb51","extension":{"installed_extension_count":2},"extensions":{"alerts":{"initialized":true},"chrome_url_overrides":{},"last_chrome_version":"146.0.3856.84","microsoft_install_signature":{"expire_date":"2026-06-22","ids":["cgjgjfacjflmgphhhepmbhhbgjieaecn","kfbdpdaobnofkbopebjglnaadopfikhh"],"invalid_ids":[],"salt":"cMEpJmVtBsNmQpFLUZRCOHsVinrGvb4WNRnK2ph3+5o=","signature":"nKoQkD9GBx7Bhyd7Blowo9FUbdSqstdLH6WKwpO50N+4P2mc1j/FHCj/a2Y1Xty6smkgzgEMegS3sTGCKWLcS8GFXZk3k6WNdio174K9zuNGlFcxDSbMqFfIfa7siTmGZE/O/dRNdw7QcOUtKjBJnLzsq+dRtnSssMrPwRoXNNGLwFFB7McFrsdNDPJkcVwloFAmVdkJZxtgM+0+4Wp6VbMLi6hDJRthncydRfiz5ZjgnN3//T5HlMCTTmw4lmjBwztI+HhcIq0t7AxdHRzxvMfhCd245kB63xOsBoxHuVCoyZ9hLSp2CXGpF9aFfe5pOURhMLAIddF3DJEb3rpTcg==","signature_format_version":2,"timestamp":"13419363761233040"},"pdf_upsell_triggered":false,"pinned_extension_migration":true,"pinned_extensions":[]},"fsd":{"retention_policy_last_version":146},"gaia_cookie":{"periodic_report_time_2":"13419318240551913"},"intl":{"selected_languages":"en-US,en"},"language_dwell_time_average":{"en":65.90909090909092},"language_model_counters":{"en":1},"language_usage_count":{"en":11},"media":{"engagement":{"schema_version":5}},"migrated_user_scripts_toggle":true,"muid":{"last_sync":"13419318240722745","values_seen":[]},"optimization_guide":{"hintsfetcher":{"hosts_successfully_fetched":{}},"previously_registered_optimization_types":{"ABOUT_THIS_SITE":true,"AUTOFILL_ACTOR_IFRAME_ORIGIN_ALLOWLIST":true,"GLIC_ACTION_PAGE_BLOCK":true,"HISTORY_CLUSTERS":true,"LOADING_PREDICTOR":true,"MERCHANT_TRUST_SIGNALS_V2":true,"PAGE_ENTITIES":true,"PRICE_INSIGHTS":true,"PRICE_TRACKING":true,"SALIENT_IMAGE":true,"SAVED_TAB_GROUP":true,"SHOPPING_DISCOUNTS":true,"SHOPPING_PAGE_TYPES":true,"V8_COMPILE_HINTS":true}},"password_manager":{"account_store_backup_password_cleaning_last_timestamp":"13419319349909375","account_store_migrated_to_os_crypt_async":true,"profile_store_backup_password_cleaning_last_timestamp":"13419319349910008","profile_store_migrated_to_os_crypt_async":true},"personalization_data_consent":{"personalization_in_context_consent_can_prompt":true,"personalization_in_context_count":0},"prefs":{"tracked_preferences_reset":["schedule_to_flush_to_disk","extensions.settings.cgjgjfacjflmgphhhepmbhhbgjieaecn","extensions.settings.dgiklkfkllikcanfonkcabmbdfmgleag","extensions.settings.kfbdpdaobnofkbopebjglnaadopfikhh","extensions.settings.mhjfbmdgcfjbbpaeojofohoefgiehjai","prefs.preference_reset_time"]},"privacy_sandbox":{"first_party_sets_data_access_allowed_initialized":true},"profile":{"avatar_index":20,"background_password_check":{"check_fri_weight":9,"check_interval":"2592000000000","check_mon_weight":6,"check_sat_weight":6,"check_sun_weight":6,"check_thu_weight":9,"check_tue_weight":9,"check_wed_weight":9,"next_check_time":"13420790644643520"},"content_settings":{"exceptions":{"3pcd_heuristics_grants":{},"abusive_notification_permissions":{},"access_to_get_all_screens_media_in_session":{},"anti_abuse":{},"app_banner":{},"ar":{},"are_suspicious_notifications_allowlisted_by_user":{},"auto_picture_in_picture":{},"auto_select_certificate":{},"automatic_downloads":{},"automatic_fullscreen":{},"autoplay":{},"background_sync":{},"bluetooth_chooser_data":{},"bluetooth_guard":{},"bluetooth_scanning":{},"camera_pan_tilt_zoom":{},"captured_surface_control":{},"clear_browsing_data_cookies_exceptions":{},"client_hints":{},"clipboard":{},"controlled_frame":{},"cookie_controls_metadata":{"file:///*,*":{"last_modified":"13419318242086815","setting":{}},"http://localhost,*":{"last_modified":"13419362809428426","setting":{}}},"cookies":{},"direct_sockets":{},"direct_sockets_private_network_access":{},"display_media_system_audio":{},"disruptive_notification_permissions":{},"durable_storage":{},"edge_ad_targeting":{},"edge_ad_targeting_data":{},"edge_all_file_read_access":{},"edge_browser_action":{},"edge_sdsm":{},"edge_split_screen":{},"edge_tech_scam_detection":{},"edge_u2f_api_request":{},"edge_user_agent_token":{},"fedcm_idp_registration":{},"fedcm_idp_signin":{},"fedcm_share":{},"file_system_access_chooser_data":{},"file_system_access_extended_permission":{},"file_system_access_restore_permission":{},"file_system_last_picked_directory":{},"file_system_read_guard":{},"file_system_write_guard":{},"formfill_metadata":{},"geolocation":{},"geolocation_with_options":{},"hand_tracking":{},"has_migrated_local_network_access":true,"hid_chooser_data":{},"hid_guard":{},"http_allowed":{},"https_enforced":{},"idle_detection":{},"images":{},"important_site_info":{},"initialized_translations":{},"intent_picker_auto_display":{},"javascript":{},"javascript_jit":{},"javascript_optimizer":{},"keyboard_lock":{},"legacy_cookie_access":{},"legacy_cookie_scope":{},"local_fonts":{},"local_network":{},"local_network_access":{},"loopback_network":{},"media_engagement":{"http://localhost:9333,*":{"expiration":"13427154500064324","last_modified":"13419378500064331","lifetime":"7776000000000","setting":{"hasHighScore":false,"lastMediaPlaybackTime":0.0,"mediaPlaybacks":0,"visits":10}}},"media_stream_camera":{},"media_stream_mic":{},"midi_sysex":{},"mixed_script":{},"nfc_devices":{},"notification_interactions":{},"notification_permission_review":{},"notifications":{},"ondevice_languages_downloaded":{},"password_protection":{},"payment_handler":{},"permission_actions_history":{},"permission_autoblocking_data":{},"permission_autorevocation_data":{},"pointer_lock":{},"popups":{},"protected_media_identifier":{},"protocol_handler":{},"reduced_accept_language":{},"safe_browsing_url_check_data":{},"secure_network":{},"secure_network_sites":{},"sensors":{},"serial_chooser_data":{},"serial_guard":{},"site_engagement":{"http://localhost:9333,*":{"last_modified":"13419363934922476","setting":{"lastEngagementTime":1.3419363934922464e+16,"lastShortcutLaunchTime":0.0,"pointsAddedToday":15.0,"rawScore":14.961}}},"sleeping_tabs":{},"sound":{},"speaker_selection":{},"ssl_cert_decisions":{},"storage_access":{},"storage_access_header_origin_trial":{},"subresource_filter":{},"subresource_filter_data":{},"suspicious_notification_ids":{},"suspicious_notification_show_original":{},"top_level_storage_access":{},"trackers":{},"trackers_data":{"https://files.constantcontact.com:443,*":{"last_modified":"13419351842036927","setting":{"count":2}},"https://imgssl.constantcontact.com:443,*":{"last_modified":"13419351842037372","setting":{"count":2}},"https://lrsut8qab.cc.rs6.net:443,*":{"last_modified":"13419351842028969","setting":{"count":2}},"https://msedgedevtools.microsoft.com:443,*":{"last_modified":"13419352005728057","setting":{"count":1}},"https://web-extract.constantcontact.com:443,*":{"last_modified":"13419351842037223","setting":{"count":2}}},"tracking_org_exceptions":{},"tracking_org_relationships":{},"typosquatting":{},"unused_site_permissions":{},"usb_chooser_data":{},"usb_guard":{},"vr":{},"web_app_installation":{},"webid_api":{},"webid_auto_reauthn":{},"window_placement":{}},"pref_version":1},"created_by_version":"146.0.3856.84","creation_time":"13419318240457630","default_content_setting_values":{"has_migrated_local_network_access":true},"edge_password_is_using_new_login_db_path":false,"edge_password_login_db_path_flip_flop_count":0,"edge_profile_id":"bffda019-ba0e-4159-8935-f883a0b1dcc1","edge_user_with_non_zero_passwords":false,"exit_type":"Normal","has_seen_signin_fre":false,"is_relative_to_aad":true,"last_engagement_time":"13419363934922463","last_time_obsolete_http_credentials_removed":1774845749.909482,"last_time_password_store_metrics_reported":1774844670.566023,"managed_user_id":"","name":"Profile 1","network_pbs":{},"observed_session_time":{"feedback_rating_in_product_help_observed_session_time_key_146.0.3856.84":720.0},"password_hash_data_list":[],"signin_fre_seen_time":"13419318240535888","were_old_google_logins_removed":true},"reset_prepopulated_engines":false,"safety_hub":{"unused_site_permissions_revocation":{"migration_completed":true}},"saved_tab_groups":{"did_enable_shared_tab_groups_in_last_session":false,"specifics_to_data_migration":true},"sessions":{"event_log":[{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419320672328210","type":2,"window_count":0},{"crashed":false,"time":"13419347087152422","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419347563521548","type":2,"window_count":0},{"crashed":false,"time":"13419347571574489","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419347579717250","type":2,"window_count":0},{"crashed":false,"time":"13419347685023530","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419347720306874","type":2,"window_count":0},{"crashed":false,"time":"13419348253502621","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419351181305067","type":2,"window_count":0},{"crashed":false,"time":"13419351333000803","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419351744186923","type":2,"window_count":0},{"crashed":false,"time":"13419351750736506","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":1,"time":"13419352025755988","type":2,"window_count":1},{"crashed":false,"time":"13419356442725023","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419356690352810","type":2,"window_count":0},{"crashed":false,"time":"13419361210207579","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":0,"time":"13419362137248419","type":2,"window_count":0},{"crashed":false,"time":"13419362808673195","type":0},{"did_schedule_command":false,"first_session_service":true,"tab_count":1,"time":"13419378500107201","type":2,"window_count":1}],"session_data_status":3},"signin":{"accounts_metadata_dict":{},"allowed":true},"spellcheck":{"dictionaries":["en-US"]},"syncing_theme_prefs_migrated_to_non_syncing":true,"total_passwords_available_for_account":0,"total_passwords_available_for_profile":0,"translate_site_blacklist":[],"translate_site_blocklist_with_time":{},"typosquatting":{"allowlist_migration_done":true},"user_experience_metrics":{"personalization_data_consent_enabled_last_known_value":false},"variations":{"state_reset_on_profile_load":{"timestamp":"13419362808648180"}},"webrtc":{"udp_port_range":"0-0"}}
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:49.611 c2c Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2
- 2026/03/30-12:46:49.624 c2c Recovering log #3
3
- 2026/03/30-12:46:49.650 c2c Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Session Storage/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:48.771 2750 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2
- 2026/03/30-12:46:48.815 2750 Recovering log #3
3
- 2026/03/30-12:46:48.817 2750 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Site Characteristics Database/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:48.772 7358 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Sync Data\LevelDB/MANIFEST-000001
2
- 2026/03/30-12:46:48.805 7358 Recovering log #3
3
- 2026/03/30-12:46:48.814 7358 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\Sync Data\LevelDB/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:49.521 1a28 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\shared_proto_db/MANIFEST-000001
2
- 2026/03/30-12:46:49.564 1a28 Recovering log #3
3
- 2026/03/30-12:46:49.567 1a28 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\shared_proto_db/000003.log
@@ -1,3 +0,0 @@
1
- 2026/03/30-12:46:49.348 1a28 Reusing MANIFEST Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\shared_proto_db\metadata/MANIFEST-000001
2
- 2026/03/30-12:46:49.360 1a28 Recovering log #3
3
- 2026/03/30-12:46:49.363 1a28 Reusing old log Y:\dev\email\mailx\launcher\bin\mailx-app.exe.WebView2\EBWebView\Default\shared_proto_db\metadata/000003.log
@@ -1 +0,0 @@
1
- {"accessibility":{"captions":{"common_models_path":"","soda_translation_binary_path":""}},"autofill":{"ablation_seed":"7c4MOFhKIeI="},"breadcrumbs":{"enabled":true,"enabled_time":"13419318240448488"},"cloned_install":{"count":2,"first_timestamp":"1774887609","last_timestamp":"1774889208","session_start_last_detection_timestamp":"1774889208"},"default_browser":{"browser_name_enum":13},"desktop_session_duration_tracker":{"last_session_end_timestamp":"1774904900"},"domain_actions_config":"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","edge":{"manageability":{"edge_last_active_time":"13419363938345282"},"mitigation_manager":{"renderer_app_container_compatible_count":2},"retrigger_features":[],"tab_stabs":{"closed_without_unfreeze_never_unfrozen":0,"closed_without_unfreeze_previously_unfrozen":0,"discard_without_unfreeze_never_unfrozen":0,"discard_without_unfreeze_previously_unfrozen":0},"tab_stats":{"frozen_daily":0,"unfrozen_daily":0}},"edge_ci":{"metrics_bookmark":"\u003CBookmarkList>\r\n\u003C/BookmarkList>","num_healthy_browsers_since_failure":11},"hardware_acceleration_mode_previous":true,"identity_combined_status":{"aad":1,"ad":1},"legacy":{"profile":{"name":{"migrated":true}}},"local":{"password_hash_data_list":[]},"network_time":{"network_time_mapping":{"local":1.774889210469219e+12,"network":1.774889209e+12,"ticks":389793160044.0,"uncertainty":1670502.0}},"optimization_guide":{"model_execution":{"last_usage_by_feature":{}},"model_store_metadata":{},"on_device":{"last_version":"146.0.3856.84","model_crash_count":0}},"os_crypt":{"audit_enabled":true,"encrypted_key":"RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAAC0g/etA6mdQoRB8Y26qq2iEAAAAB4AAABNAGkAYwByAG8AcwBvAGYAdAAgAEUAZABnAGUAAAAQZgAAAAEAACAAAAA9rSRW+YKTbrF6NK7S3kM3w1+SLuyByQiLzPCuZbuVngAAAAAOgAAAAAIAACAAAAC2bKLzX0jHLKi46EZPdOcY5tFSF2ClCOT8Pg/9oyYhajAAAACKxk2GXcVpE66fqz/wUzBNLlJubzWPN0LSSnsgIhgMJRJ5h+bstyCZaKBl2Yrz6IVAAAAAjg4cdfPEdGkoRiwsWGjGrYrxiJF+c124E3EQo5rfdRXBwdgo+UxHhnI29Wh9rqGBnLk9jkcSB5Ez1aTi3ypfvg=="},"performance_intervention":{"last_daily_sample":"13419318240613691"},"phoenix":{"user_laf_toggle_state_static":2},"policy":{"last_statistics_update":"13419318240445758"},"profile":{"info_cache":{"Default":{"active_time":1774904899.912184,"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_20","background_apps":false,"edge_account_cid":"","edge_account_environment":0,"edge_account_environment_string":"","edge_account_first_name":"","edge_account_last_name":"","edge_account_oid":"","edge_account_sovereignty":0,"edge_account_tenant_id":"","edge_account_type":0,"edge_create_profile_shortcut":false,"edge_non_signin_profile_type":1,"edge_profile_can_be_deleted":true,"edge_profile_can_be_edited":true,"edge_test_on_premises":false,"edge_wam_aad_for_app_account_type":0,"enterprise_label":"","force_signin_profile_locked":false,"gaia_given_name":"","gaia_id":"","gaia_name":"","hosted_domain":"","is_consented_primary_account":false,"is_ephemeral":false,"is_glic_eligible":false,"is_managed":0,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","metrics_bucket_index":1,"name":"Profile 1","signin.with_credential_provider":false,"user_name":""}},"last_active_profiles":[],"metrics":{"next_bucket_index":2},"profile_counts_reported":"13419318240199996","profiles_order":["Default"]},"profile_network_context_service":{"http_cache_finch_experiment_groups":"None None None None"},"profiles":{"edge":{"guided_switch_pref":[],"multiple_profiles_with_same_account":false},"edge_sso_info":{"msa_first_profile_key":"Default","msa_sso_algo_state":1},"signin_last_seen_version":"146.0.3856.84","signin_last_updated_time":1774844640.597125},"sentinel_creation_time":"0","session_id_generator_last_value":"746888710","signin":{"active_accounts_last_emitted":"13419318240192557"},"startup_boost":{"last_browser_open_time":"13419378500242261"},"subresource_filter":{"ruleset_version":{"checksum":860988201,"content":"10.34.0.81","format":37}},"tab_stats":{"discards_expired":0,"discards_external":0,"discards_proactive":0,"discards_urgent":0,"last_daily_sample":"13419318240385917","max_tabs_per_window":1,"reloads_expired":0,"reloads_external":0,"reloads_urgent":0,"total_tab_count_max":2,"window_count_max":2},"telemetry_client":{"cloned_install":{"user_data_dir_id":8554438},"governance":{"last_dma_change_date":"13419318240365580","last_known_cps":0},"host_telclient_path":"QzpcUHJvZ3JhbSBGaWxlcyAoeDg2KVxNaWNyb3NvZnRcRWRnZVdlYlZpZXdcQXBwbGljYXRpb25cMTQ2LjAuMzg1Ni44NFx0ZWxjbGllbnQuZGxs","sample_id":83918884},"uninstall_metrics":{"installation_date2":"1774844639"},"updateclientdata":{"apps":{"eeobbhfgfagbclfofmgbdfoicabjdbkn":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"1.0.0.10"},"efniojlnjndmcbiieegkicadnoecjjef":{"cohort":"","cohortname":"","installdate":-1},"fgbafbciocncjfbbonhocjaohoknlaco":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"2026.3.23.1"},"fppmbhmldokgmleojlplaaodlkibgikh":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"1.15.0.1"},"jbfaflocpnkhbgcijpkiafdpbjkedane":{"cohort":"","cohortname":"","installdate":-1},"kpfehajjjbbcifeehjgfgnabifknmdad":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"120.0.6050.0"},"laoigpblnllgcgjnjnllmfolckpjlhki":{"cohort":"","cohortname":"","installdate":-1},"ndikpojcjlepofdkaaldkinkjbeeebkl":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"10.34.0.81"},"oankkpibpaokgecfckkdkgaoafllipag":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"6498.2025.9.4"},"ohckeflnhegojcjlcpbfpciadgikcohk":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"0.0.1.7"},"ojblfafjmiikbkepnnolpgbbhejhlcim":{"cohort":"","cohortname":"","installdate":-1},"pghocgajpebopihickglahgebcmkcekh":{"cohort":"","cohortname":"","fp":"","installdate":-1,"max_pv":"0.0.0.0","pv":"3.0.0.16"}}},"updateclientlastupdatecheckerror":0,"updateclientlastupdatecheckerrorcategory":0,"updateclientlastupdatecheckerrorextracode1":0,"user_experience_metrics":{"chrome_download_action_count":0,"client_id2":"{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}C:\\Users\\Bob1s:EEEB1F6B-87F7-49E6-AC8C-6EC5664175F4","client_id_timestamp":"1774889208","diagnostics":{"last_data_collection_level_on_launch":3},"initial_logs2":[],"last_seen":{"CrashpadMetrics":"13419356689716854"},"limited_entropy_randomization_source":"48F5D1E845C6D0986EF5D1C4E653D4A0","log_finalized_record_id":6,"log_record_id":4,"low_entropy_source3":5854,"machine_id":13342739,"ongoing_logs2":[],"payload_counter":4,"pseudo_low_entropy_source":5891,"reporting_enabled":true,"reset_client_id_deterministic":true,"reset_metrics_ids":true,"session_id":15,"stability":{"browser_last_live_timestamp":"13419378500278531","exited_cleanly":true,"saved_system_profile":"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","saved_system_profile_hash":"4F774B8A2088F0FC422A3318EFB264565CF7AC21","stats_buildtime":"1774479459","stats_version":"146.0.3856.84-64","system_crash_count":0},"unsent_log_metadata":{"initial_logs":{"sent_samples_count":0,"unsent_persisted_size_in_kb":0,"unsent_samples_count":0},"ongoing_logs":{"sent_samples_count":0,"unsent_persisted_size_in_kb":0,"unsent_samples_count":0}}},"variations":{"state_reset":{"timestamp":"13419362808428996"}},"variations_compressed_seed":"H4sIAAAAAAAAAJVWbW/iOBD+K5W/XlzFeYfTfWh5aVHLLltgW+m2qkwypN46Nms7UK7iv58cUwq9ou7xAWXGzzPzzHjs5AX1OmPUfkEdzkCYjhRzVtaKGibFdFFQA70lCGMRXeCGXsuyJ+iMQ4Hac8o1eKhfcz4Gc3ylr+BXDSJfozbx/Y2Hes85rwvoPRtQgnKXdFDogbiWJWobVYOHnPdalhOqSjCojaAo4UEbmwPZKEUJDmTVXTHOxytm8scuNXSq+JBVMFkvYEQVrcCAGinQoJZNaZZRMG1D9YGaWoFG7b/Rb1HvNx7qOu61zCn/AmYl1dNZnoPWnUfIn45EP4LWTcTVMhhTUczk8xH2QEtODWxBUAzmVpzel9NnHMZrbaDaC8+ZNkdCvsd3mYLcSLUeGHAjcM6li+DqsrncJt9+D86KglkM5SMlLd1uARQT4FCBUWubFMT7nJW+hdl3BqvP+TbbuMgfXcZj4ewYWFQD/zYddCxw8bpzFvSCBK0AtVH+SIUAjjy0pLy2nj7aeLtlWMj8cW8x9N1vH6PAKCp0xUwzhw9SPKyYggfDKpC1eagY50xDLkWh90IFNooV+HUJSrECpldDfayi6VN1IZf2aIgcru323XtHKmrArzEb6FvOIcuV1HJuTvtMaTOiyqy303djD6Q2N6BrbjzikfjPQ3nNoT8q0K2ecS5Xn8lroJ8KvIXZuZIrDep0pKSRs3p+Or0anrrhHCk5Zxw83+r8DZKhRp9ey3JsqDKe70X/h9SR1YKDgYbnmrKbyJFcjKldbv6ZKI81qC9VDjvaDu2hStsLDbSZCjaXquoybRSb1fYcXDJtZKlodbyfpZL1ItjJOBiw/SktYE5rbi4s/CP0Abh+qo6GvN9sL9pmhG5q8Xbh9qqFWX+89N+WAMxVjppoYygrEGZ3DfeVFIaBOqsLBiK3mb9IYYUMzwZnnKM2al4nyEO3t71Dh84X89p6/Oa5rKkqXo0lqOZxGCZxRyo4ZHakMCDMGNSS5aDf5YHZ3eTQdc5EeeixpR96dlM21Tb31r/x0CXQotnJF9Sb0BK10Q80uvtjOVGdbt2/e5r+XEyTX0GvXo78afzPMF1cRDc/Z+TbZby6en766wey+Z4XrOkmGkrhnYT+yZCqk8APkhOStqOkHbVOLoaTprZaGLXuyMI2czpGHrLjXeutp7mMXl+wg67TZb8C0AjfYJLGJE58TDDxGtvPgjhtbOvo4igIswwHOEGH7+Atu0VaSYRDHDt2GiZxRHD8aockjjKCCc6cHUeEpAQnuLW1gyzwfRziyNmEhHFIcLRdT7IojXALk8CZJPATHEQ4CJ3tJyTFGQ6c9igO0xBnOEvRx2PsNPtpnCUxjnCG3s/ntiiSpCTExMfEd7KiNPRJ8lYGiVutLMbktUxCwhaJcRC7rtkkrSwMI0xw4pQmfpphgsOdle7YiZ9lASbY1RiFfhbsGhoFaWSjBGiz+Re/tfIzvQkAAA==","variations_country":"US","variations_crash_streak":0,"variations_failed_to_fetch_seed_streak":0,"variations_google_groups":{"Default":[]},"variations_last_fetch_time":"13419362811355811","variations_last_runtime_fetch_time":"13419362811356285","variations_permanent_consistency_country":["146.0.3856.84","US"],"variations_runtime_compressed_seed":"H4sIAAAAAAAAAG2PQWvCQBCF/8ucM7izs9nsBnqKEQs92LRCoPaQdrcq1ihJRI3kvxez7a3H730P3swNskP9tV0/TltIYYEFkrAsVYyEkqIQGC0UEnIycmJYaCQkE5C1HDFYzaRjVCj1iDFLxSgxSCWEZeQ/ySZRChO0wTIZa1FaVNZGC5wiUWw0KZSofi9hk2iBEklABLlb++JUd9u9D09AeoN8f+yu/xpfVx/ffuar7tT4FtI38L75hPdhiGDuK+eb9l7LDqe6a67ZwXlIYflyH3qt1pDCCub9ZXeekWqfeXnZlMXONZvqMjlO3LnP+lJuS1clPH/KC/OwAhiGH4atSSVfAQAA","variations_runtime_config_ids":"P-R-1093245-1-21,P-R-108604-1-37,P-R-78306-1-18,P-R-73626-1-17,P-R-63165-4-26,P-R-53243-2-7,P-R-40093-3-26,P-R-38744-7-97,P-R-31899-29-499,P-D-1158614-2-4,P-R-1038760-2-10","variations_seed_client_version_at_store":"146.0.3856.84","variations_seed_date":"13419362809000000","variations_seed_milestone":146,"variations_seed_runtime_etag":"\"HzxkwF14sQ3UxhXRkdrhax/p/dwzCzX2iXda73HLER8=\"","variations_seed_runtime_serial_number":"\"HzxkwF14sQ3UxhXRkdrhax/p/dwzCzX2iXda73HLER8=\"","variations_seed_serial_number":"\"PX+vTrCDuFXkUjpU6q2EuvP0U5zM7pG4Rjb1QH5wKxk=\"","variations_seed_signature":"","was":{"restarted":false}}
@@ -1 +0,0 @@
1
- {"user_experience_metrics.stability.exited_cleanly":true,"variations_crash_streak":0}
Binary file