@nocobase/app-plugin-mail 1.0.0-beta.13 → 1.0.0-beta.15

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 (76) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +8 -0
  3. package/dist/client/pages/mail-accounts-page.d.ts.map +1 -1
  4. package/dist/client/pages/mail-accounts-page.js +44 -53
  5. package/dist/client/pages/mail-accounts-page.js.map +1 -1
  6. package/dist/client/pages/mail-workspace-page.d.ts.map +1 -1
  7. package/dist/client/pages/mail-workspace-page.js +78 -65
  8. package/dist/client/pages/mail-workspace-page.js.map +1 -1
  9. package/dist/client/subscription.d.ts +1 -1
  10. package/dist/client/subscription.d.ts.map +1 -1
  11. package/dist/client/subscription.js +7 -6
  12. package/dist/client/subscription.js.map +1 -1
  13. package/dist/database/migrations/.manifest.json +4 -0
  14. package/dist/database/migrations/202610250001_mail_imap_message_locations.d.ts +4 -0
  15. package/dist/database/migrations/202610250001_mail_imap_message_locations.d.ts.map +1 -0
  16. package/dist/database/migrations/202610250001_mail_imap_message_locations.js +297 -0
  17. package/dist/database/migrations/202610250001_mail_imap_message_locations.js.map +1 -0
  18. package/dist/server/adapters/imap-smtp/adapter.d.ts +60 -3
  19. package/dist/server/adapters/imap-smtp/adapter.d.ts.map +1 -1
  20. package/dist/server/adapters/imap-smtp/adapter.js +774 -83
  21. package/dist/server/adapters/imap-smtp/adapter.js.map +1 -1
  22. package/dist/server/adapters/imap-smtp/constants.d.ts +6 -0
  23. package/dist/server/adapters/imap-smtp/constants.d.ts.map +1 -1
  24. package/dist/server/adapters/imap-smtp/constants.js +6 -0
  25. package/dist/server/adapters/imap-smtp/constants.js.map +1 -1
  26. package/dist/server/adapters/imap-smtp/content.d.ts +11 -0
  27. package/dist/server/adapters/imap-smtp/content.d.ts.map +1 -1
  28. package/dist/server/adapters/imap-smtp/content.js +82 -3
  29. package/dist/server/adapters/imap-smtp/content.js.map +1 -1
  30. package/dist/server/adapters/imap-smtp/definition.d.ts +7 -0
  31. package/dist/server/adapters/imap-smtp/definition.d.ts.map +1 -1
  32. package/dist/server/adapters/imap-smtp/definition.js +19 -11
  33. package/dist/server/adapters/imap-smtp/definition.js.map +1 -1
  34. package/dist/server/adapters/imap-smtp/locators.d.ts +7 -0
  35. package/dist/server/adapters/imap-smtp/locators.d.ts.map +1 -1
  36. package/dist/server/adapters/imap-smtp/locators.js +53 -3
  37. package/dist/server/adapters/imap-smtp/locators.js.map +1 -1
  38. package/dist/server/adapters/imap-smtp/types.d.ts +87 -0
  39. package/dist/server/adapters/imap-smtp/types.d.ts.map +1 -1
  40. package/dist/server/operations/message-mutations.d.ts.map +1 -1
  41. package/dist/server/operations/message-mutations.js +57 -5
  42. package/dist/server/operations/message-mutations.js.map +1 -1
  43. package/dist/server/operations/sync-mailbox.d.ts +1 -0
  44. package/dist/server/operations/sync-mailbox.d.ts.map +1 -1
  45. package/dist/server/operations/sync-mailbox.js +41 -14
  46. package/dist/server/operations/sync-mailbox.js.map +1 -1
  47. package/dist/server/providers/mail-builtins.d.ts.map +1 -1
  48. package/dist/server/providers/mail-builtins.js +6 -2
  49. package/dist/server/providers/mail-builtins.js.map +1 -1
  50. package/dist/server/providers/mail-core.js +2 -2
  51. package/dist/server/providers/mail-core.js.map +1 -1
  52. package/dist/server/realtime.d.ts +1 -1
  53. package/dist/server/realtime.d.ts.map +1 -1
  54. package/dist/server/realtime.js +6 -3
  55. package/dist/server/realtime.js.map +1 -1
  56. package/dist/server/services/sync.d.ts +1 -1
  57. package/dist/server/services/sync.d.ts.map +1 -1
  58. package/dist/server/services/sync.js +3 -0
  59. package/dist/server/services/sync.js.map +1 -1
  60. package/dist/server/store/attachments.d.ts.map +1 -1
  61. package/dist/server/store/attachments.js +3 -0
  62. package/dist/server/store/attachments.js.map +1 -1
  63. package/dist/server/store/message-writes.d.ts +24 -1
  64. package/dist/server/store/message-writes.d.ts.map +1 -1
  65. package/dist/server/store/message-writes.js +357 -1
  66. package/dist/server/store/message-writes.js.map +1 -1
  67. package/dist/server/store/messages.d.ts.map +1 -1
  68. package/dist/server/store/messages.js +11 -3
  69. package/dist/server/store/messages.js.map +1 -1
  70. package/dist/server/store/rows.d.ts +20 -0
  71. package/dist/server/store/rows.d.ts.map +1 -1
  72. package/dist/server/store/sync.d.ts +7 -1
  73. package/dist/server/store/sync.d.ts.map +1 -1
  74. package/dist/server/store/sync.js +333 -7
  75. package/dist/server/store/sync.js.map +1 -1
  76. package/package.json +16 -15
@@ -3,7 +3,7 @@ import type { RealtimeUserTopic } from '@nocobase/app-server/realtime';
3
3
  import type { MailRealtimeEvent } from '../shared/realtime.js';
4
4
  export { MAIL_REALTIME_TOPIC, type MailRealtimeEvent, } from '../shared/realtime.js';
5
5
  export interface MailMessageChangeNotifier {
6
- notify(userId: string): void;
6
+ notify(userId: string): void | Promise<void>;
7
7
  }
8
8
  export type MailRealtimeTopic = Pick<RealtimeUserTopic<MailRealtimeEvent>, 'publishFor'>;
9
9
  export declare function createMailMessageChangeNotifier(topic: MailRealtimeTopic): MailMessageChangeNotifier;
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../server/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EACL,mBAAmB,EACnB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,iBAAiB,CAAC,iBAAiB,CAAC,EACpC,YAAY,CACb,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,iBAAiB,GACvB,yBAAyB,CAM3B;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,yBAAyB,GAAG,SAAS,EAC/C,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,UAAU,GAClB,IAAI,CAYN"}
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../server/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EACL,mBAAmB,EACnB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,iBAAiB,CAAC,iBAAiB,CAAC,EACpC,YAAY,CACb,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,iBAAiB,GACvB,yBAAyB,CAM3B;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,yBAAyB,GAAG,SAAS,EAC/C,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,UAAU,GAClB,IAAI,CAeN"}
@@ -2,8 +2,8 @@ import { mailLogError, writeMailLog } from './logging.js';
2
2
  export { MAIL_REALTIME_TOPIC, } from '../shared/realtime.js';
3
3
  export function createMailMessageChangeNotifier(topic) {
4
4
  return {
5
- notify(userId) {
6
- topic.publishFor(userId, { kind: 'mail.changed' });
5
+ async notify(userId) {
6
+ await topic.publishFor(userId, { kind: 'mail.changed' });
7
7
  },
8
8
  };
9
9
  }
@@ -11,9 +11,12 @@ export function notifyMailMessageChange(notifier, userId, logger) {
11
11
  if (!notifier)
12
12
  return;
13
13
  try {
14
- notifier.notify(userId);
14
+ void Promise.resolve(notifier.notify(userId)).catch(report);
15
15
  }
16
16
  catch (error) {
17
+ report(error);
18
+ }
19
+ function report(error) {
17
20
  writeMailLog(logger, 'error', { event: 'mail.realtime.failed', userId, err: mailLogError(error) }, 'Failed to publish Mail realtime event.');
18
21
  }
19
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../../server/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAmB,MAAM,cAAc,CAAC;AAK3E,OAAO,EACL,mBAAmB,GAEpB,MAAM,uBAAuB,CAAC;AAW/B,MAAM,UAAU,+BAA+B,CAC7C,KAAwB;IAExB,OAAO;QACL,MAAM,CAAC,MAAc;YACnB,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,QAA+C,EAC/C,MAAc,EACd,MAAmB;IAEnB,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,IAAI,CAAC;QACH,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CACV,MAAM,EACN,OAAO,EACP,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,EACnE,wCAAwC,CACzC,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../../server/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAmB,MAAM,cAAc,CAAC;AAK3E,OAAO,EACL,mBAAmB,GAEpB,MAAM,uBAAuB,CAAC;AAW/B,MAAM,UAAU,+BAA+B,CAC7C,KAAwB;IAExB,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,MAAc;YACzB,MAAM,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAC3D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,QAA+C,EAC/C,MAAc,EACd,MAAmB;IAEnB,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,IAAI,CAAC;QACH,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC;IACD,SAAS,MAAM,CAAC,KAAc;QAC5B,YAAY,CACV,MAAM,EACN,OAAO,EACP,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,EACnE,wCAAwC,CACzC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -3,7 +3,7 @@ import { type MailServiceDependencies } from './dependencies.js';
3
3
  export declare class MailSyncService {
4
4
  private readonly dependencies;
5
5
  private readonly scheduler;
6
- constructor(dependencies: MailServiceDependencies<'cancelSyncRun' | 'countSyncRuns' | 'createSyncRun' | 'findActiveSyncRun' | 'getAccount' | 'getSyncCursor' | 'getSyncRun' | 'listSyncRuns', 'outbox'>, syncBatchSize: number);
6
+ constructor(dependencies: MailServiceDependencies<'cancelSyncRun' | 'countSyncRuns' | 'createSyncRun' | 'findActiveSyncRun' | 'getAccount' | 'getSyncCursor' | 'getSyncRun' | 'listSyncRuns', 'outbox' | 'messageChangeNotifier' | 'logger'>, syncBatchSize: number);
7
7
  startSync(context: MailOperationContext, input: MailStartSyncInput): Promise<MailSyncRunView>;
8
8
  getSyncRun(context: MailOperationContext, syncRunId: string): Promise<MailSyncRunView | undefined>;
9
9
  listSyncRunsPage(context: MailOperationContext, offset?: number, limit?: number): Promise<MailOffsetPage<MailSyncRunView>>;
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../server/services/sync.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAEvB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAIjE,qBAAa,eAAe;IAGxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAF/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAE3B,YAAY,EAAE,uBAAuB,CAClD,eAAe,GACf,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,cAAc,EAChB,QAAQ,CACT,EACD,aAAa,EAAE,MAAM;IAKV,SAAS,CACpB,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,eAAe,CAAC;IAed,UAAU,CACrB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAO1B,gBAAgB,CAC3B,OAAO,EAAE,oBAAoB,EAC7B,MAAM,SAAI,EACV,KAAK,SAAK,GACT,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IAQ9B,YAAY,CACvB,OAAO,EAAE,oBAAoB,EAC7B,MAAM,SAAI,EACV,KAAK,SAAM,GACV,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;IAMzB,YAAY,CACvB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC;IAwBd,aAAa,CACxB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC;YAiBb,mBAAmB;CAclC"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../server/services/sync.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAEvB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAIjE,qBAAa,eAAe;IAGxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAF/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAE3B,YAAY,EAAE,uBAAuB,CAClD,eAAe,GACf,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,cAAc,EAChB,QAAQ,GAAG,uBAAuB,GAAG,QAAQ,CAC9C,EACD,aAAa,EAAE,MAAM;IAKV,SAAS,CACpB,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,eAAe,CAAC;IAoBd,UAAU,CACrB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAO1B,gBAAgB,CAC3B,OAAO,EAAE,oBAAoB,EAC7B,MAAM,SAAI,EACV,KAAK,SAAK,GACT,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IAQ9B,YAAY,CACvB,OAAO,EAAE,oBAAoB,EAC7B,MAAM,SAAI,EACV,KAAK,SAAM,GACV,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;IAMzB,YAAY,CACvB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC;IAwBd,aAAa,CACxB,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC;YAsBb,mBAAmB;CAclC"}
@@ -1,3 +1,4 @@
1
+ import { notifyMailMessageChange } from '../realtime.js';
1
2
  import { MailSyncScheduler } from '../operations/schedule-sync.js';
2
3
  import { toSyncRunView } from '../views.js';
3
4
  import { requireActiveAccount, requireOwnedAccount } from './access.js';
@@ -14,6 +15,7 @@ export class MailSyncService {
14
15
  const account = await requireActiveAccount(this.dependencies.store, context, input.accountId);
15
16
  const { run } = await this.scheduler.request(account, context.actorId, input);
16
17
  this.dependencies.outbox.kick();
18
+ notifyMailMessageChange(this.dependencies.messageChangeNotifier, account.userId, this.dependencies.logger);
17
19
  return toSyncRunView(run);
18
20
  }
19
21
  async getSyncRun(context, syncRunId) {
@@ -58,6 +60,7 @@ export class MailSyncService {
58
60
  const cancelled = await this.dependencies.store.cancelSyncRun(syncRunId);
59
61
  if (!cancelled)
60
62
  throw mailFailedPrecondition('MAIL_SYNC_RUN_STATE_INVALID', 'Mail sync run is no longer active.');
63
+ notifyMailMessageChange(this.dependencies.messageChangeNotifier, context.actorId, this.dependencies.logger);
61
64
  return toSyncRunView(cancelled);
62
65
  }
63
66
  async requireOwnedSyncRun(context, syncRunId) {
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../server/services/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAQnE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,OAAO,eAAe;IAGP;IAFF,SAAS,CAAoB;IAC9C,YACmB,YAUhB,EACD,aAAqB;QAXJ,iBAAY,GAAZ,YAAY,CAU5B;QAGD,IAAI,CAAC,SAAS,GAAG,IAAI,iBAAiB,CAAC,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC5E,CAAC;IAEM,KAAK,CAAC,SAAS,CACpB,OAA6B,EAC7B,KAAyB;QAEzB,MAAM,OAAO,GAAG,MAAM,oBAAoB,CACxC,IAAI,CAAC,YAAY,CAAC,KAAK,EACvB,OAAO,EACP,KAAK,CAAC,SAAS,CAChB,CAAC;QACF,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAC1C,OAAO,EACP,OAAO,CAAC,OAAO,EACf,KAAK,CACN,CAAC;QACF,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAChC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,UAAU,CACrB,OAA6B,EAC7B,SAAiB;QAEjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxE,OAAO,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAC3B,OAA6B,EAC7B,MAAM,GAAG,CAAC,EACV,KAAK,GAAG,EAAE;QAEV,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACvC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC;SACvD,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;IAEM,KAAK,CAAC,YAAY,CACvB,OAA6B,EAC7B,MAAM,GAAG,CAAC,EACV,KAAK,GAAG,GAAG;QAEX,OAAO,CACL,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAC3E,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACvB,CAAC;IAEM,KAAK,CAAC,YAAY,CACvB,OAA6B,EAC7B,SAAiB;QAEjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,sBAAsB,CAC1B,6BAA6B,EAC7B,oDAAoD,CACrD,CAAC;QACJ,CAAC;QACD,MAAM,aAAa,GACjB,GAAG,CAAC,IAAI,KAAK,SAAS;YACpB,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;gBAC/C,oBAAoB,CAClB,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;oBACvD,EAAE,wBAAwB,CAC7B;gBACD,IAAI,IAAI,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;YAClE,CAAC,CAAC,SAAS,CAAC;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;YAC7B,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,aAAa;SACd,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,aAAa,CACxB,OAA6B,EAC7B,SAAiB;QAEjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,MAAM,sBAAsB,CAC1B,6BAA6B,EAC7B,yCAAyC,CAC1C,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS;YACZ,MAAM,sBAAsB,CAC1B,6BAA6B,EAC7B,oCAAoC,CACrC,CAAC;QACJ,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAC/B,OAA6B,EAC7B,SAAiB;QAEjB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG;YACN,MAAM,YAAY,CAChB,yBAAyB,EACzB,8BAA8B,EAC9B,WAAW,CACZ,CAAC;QACJ,MAAM,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3E,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,SAAS,oBAAoB,CAAC,KAAyB;IACrD,OAAO,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACzE,CAAC"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../server/services/sync.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../server/store/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,KAAK,sBAAsB,EAE5B,MAAM,sBAAsB,CAAC;AAQ9B,qBAAa,oBAAoB;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,eAAe;IAEhD,wBAAwB,CACnC,UAAU,EAAE,sBAAsB,GACjC,OAAO,CAAC,IAAI,CAAC;IAQH,qBAAqB,CAChC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IAajC,yBAAyB,CACpC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAYH,8BAA8B,CACzC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC,GACvD,OAAO,CAAC,SAAS,sBAAsB,EAAE,CAAC;YA6C/B,yBAAyB;IAyE1B,wBAAwB,CACnC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC;CAQpB"}
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../server/store/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,KAAK,sBAAsB,EAE5B,MAAM,sBAAsB,CAAC;AAQ9B,qBAAa,oBAAoB;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,eAAe;IAEhD,wBAAwB,CACnC,UAAU,EAAE,sBAAsB,GACjC,OAAO,CAAC,IAAI,CAAC;IAQH,qBAAqB,CAChC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IAgBjC,yBAAyB,CACpC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAYH,8BAA8B,CACzC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC,GACvD,OAAO,CAAC,SAAS,sBAAsB,EAAE,CAAC;YA6C/B,yBAAyB;IAyE1B,wBAAwB,CACnC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC;CAQpB"}
@@ -12,6 +12,9 @@ export class MailAttachmentsStore {
12
12
  .execute();
13
13
  }
14
14
  async getOutboundAttachment(userId, attachmentId) {
15
+ // Provider part IDs are opaque; local upload IDs must be UUIDs.
16
+ if (!/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(attachmentId))
17
+ return undefined;
15
18
  const row = await this.database
16
19
  .query()
17
20
  .selectFrom('mailOutboundAttachments')
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../server/store/attachments.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../server/store/attachments.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,31 @@
1
1
  import { type QueryAdapter } from '@nocobase/db';
2
2
  import { type NormalizedMailMessage } from '../contracts/provider.js';
3
- export declare function upsertMessages(query: QueryAdapter, accountId: string, messages: readonly NormalizedMailMessage[], preserveUpdatedAfter?: string): Promise<void>;
3
+ import type { ImapCopyEvidence, ImapLocationChange, ImapStoredLocation, ImapLocationTuple, ImapIdSource } from '../adapters/imap-smtp/types.js';
4
+ export declare function upsertMessages(query: QueryAdapter, accountId: string, messages: readonly NormalizedMailMessage[], preserveUpdatedAfter?: string, replaceFolders?: boolean): Promise<void>;
4
5
  export declare function removeStaleMessageFolders(query: QueryAdapter, accountId: string, completeProviderFolderIds: readonly string[]): Promise<void>;
5
6
  export declare function upsertFolders(query: QueryAdapter, accountId: string, folders: readonly import('../contracts/provider.js').NormalizedMailFolder[]): Promise<void>;
6
7
  export declare function deleteMessages(query: QueryAdapter, accountId: string, providerMessageIds: readonly string[]): Promise<void>;
7
8
  export declare function removeMessagesFromFolders(query: QueryAdapter, accountId: string, removals: readonly import('../contracts/provider.js').MailProviderFolderRemoval[]): Promise<void>;
9
+ export declare function validateImapLocation(tuple: ImapLocationTuple, source?: ImapIdSource): void;
10
+ export declare function validateImapStoredLocation(location: ImapStoredLocation): void;
11
+ export declare function validateImapCopyEvidence(copy: ImapCopyEvidence): void;
12
+ /**
13
+ * Write one sync step's IMAP copies: one business message per identity, a
14
+ * location per copy, and aggregates derived from every verified copy.
15
+ */
16
+ export declare function upsertImapMessages(query: QueryAdapter, accountId: string, messages: readonly NormalizedMailMessage[], copies: readonly ImapCopyEvidence[], runId: string, preserveUpdatedAfter?: string): Promise<void>;
17
+ /** Apply verified status changes of stored copies. */
18
+ export declare function applyImapLocationChanges(query: QueryAdapter, accountId: string, changes: readonly ImapLocationChange[], runId: string): Promise<void>;
19
+ /**
20
+ * Derive message state from its copies: read when every verified copy is read,
21
+ * starred when any is, received at the earliest verified copy. A message with
22
+ * no verified copy keeps its state and is marked as an orphan of this run.
23
+ */
24
+ export declare function refreshImapMessages(query: QueryAdapter, accountId: string, messageIds: readonly string[], runId?: string, updatedAt?: string): Promise<void>;
25
+ /**
26
+ * Delete IMAP messages with no valid or pending copy after a complete,
27
+ * twice-verified run. Local, submitted and scheduled messages are never IMAP
28
+ * orphans: they carry no IMAP identity source or are locked by a schedule.
29
+ */
30
+ export declare function deleteImapOrphans(query: QueryAdapter, accountId: string, runId: string): Promise<void>;
8
31
  //# sourceMappingURL=message-writes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message-writes.d.ts","sourceRoot":"","sources":["../../../server/store/message-writes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AActE,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,EAC1C,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkIf;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,yBAAyB,EAAE,SAAS,MAAM,EAAE,GAC3C,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,OAAO,0BAA0B,EAAE,oBAAoB,EAAE,GAC1E,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,SAAS,MAAM,EAAE,GACpC,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,OAAO,0BAA0B,EAAE,yBAAyB,EAAE,GAChF,OAAO,CAAC,IAAI,CAAC,CAef"}
1
+ {"version":3,"file":"message-writes.d.ts","sourceRoot":"","sources":["../../../server/store/message-writes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAStE,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACb,MAAM,gCAAgC,CAAC;AAOxC,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,EAC1C,oBAAoB,CAAC,EAAE,MAAM,EAC7B,cAAc,UAAO,GACpB,OAAO,CAAC,IAAI,CAAC,CAoIf;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,yBAAyB,EAAE,SAAS,MAAM,EAAE,GAC3C,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,OAAO,0BAA0B,EAAE,oBAAoB,EAAE,GAC1E,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,kBAAkB,EAAE,SAAS,MAAM,EAAE,GACpC,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,OAAO,0BAA0B,EAAE,yBAAyB,EAAE,GAChF,OAAO,CAAC,IAAI,CAAC,CAef;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,iBAAiB,EACxB,MAAM,CAAC,EAAE,YAAY,GACpB,IAAI,CAgBN;AA+BD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAU7E;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAkBrE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,EAC1C,MAAM,EAAE,SAAS,gBAAgB,EAAE,EACnC,KAAK,EAAE,MAAM,EACb,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Jf;AAED,sDAAsD;AACtD,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,kBAAkB,EAAE,EACtC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CA0Df;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA2Ff;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
@@ -5,7 +5,7 @@ import { MAIL_LOCAL_DRAFT_FOLDER_ID } from '../../shared/mail.js';
5
5
  import { toMessageRow } from './mappers.js';
6
6
  import { chunks } from './serialization.js';
7
7
  import { deleteMessageParticipants, replaceMessageParticipants, } from './message-participants.js';
8
- export async function upsertMessages(query, accountId, messages, preserveUpdatedAfter) {
8
+ export async function upsertMessages(query, accountId, messages, preserveUpdatedAfter, replaceFolders = true) {
9
9
  const uniqueMessages = [
10
10
  ...new Map(messages.map((message) => [message.providerMessageId, message])).values(),
11
11
  ];
@@ -73,6 +73,9 @@ export async function upsertMessages(query, accountId, messages, preserveUpdated
73
73
  if (rows.length === 0)
74
74
  return;
75
75
  await replaceMessageParticipants(query, rows);
76
+ // IMAP derives folders from every stored copy instead of the latest one.
77
+ if (!replaceFolders)
78
+ return;
76
79
  const messageIds = rows.map((row) => row.id);
77
80
  await query
78
81
  .deleteFrom('mailMessageFolders')
@@ -180,4 +183,357 @@ export async function removeMessagesFromFolders(query, accountId, removals) {
180
183
  .execute();
181
184
  }
182
185
  }
186
+ const IMAP_LOCATIONS = 'mailMessageImapLocations';
187
+ export function validateImapLocation(tuple, source) {
188
+ if (typeof tuple.folder !== 'string' ||
189
+ !tuple.folder.length ||
190
+ tuple.folder.length > 500 ||
191
+ !Number.isSafeInteger(tuple.uid) ||
192
+ tuple.uid < 1 ||
193
+ tuple.uid > 4294967295 ||
194
+ typeof tuple.uidValidity !== 'string' ||
195
+ !/^[1-9]\d{0,9}$/.test(tuple.uidValidity) ||
196
+ BigInt(tuple.uidValidity) > 4294967295n ||
197
+ (source !== undefined &&
198
+ !['objectid', 'x-gm-msgid', 'rfc-message-id', 'locator'].includes(source))) {
199
+ throw new Error('Invalid IMAP location evidence.');
200
+ }
201
+ }
202
+ function unchanged(row, observed) {
203
+ return row
204
+ ? Boolean(observed &&
205
+ row.id === observed.id &&
206
+ row.messageId === observed.messageId &&
207
+ row.providerFolderId === observed.folder &&
208
+ row.uidValidity === observed.uidValidity &&
209
+ Number(row.uid) === observed.uid &&
210
+ new Date(row.updatedAt).toISOString() === observed.updatedAt &&
211
+ row.status === observed.status)
212
+ : !observed;
213
+ }
214
+ function validImapIdentity(value, source) {
215
+ if (typeof value !== 'string' || !value || value.length > 500)
216
+ return false;
217
+ if (source === 'objectid')
218
+ return /^[A-Za-z0-9_-]{1,255}$/.test(value);
219
+ if (source === 'x-gm-msgid')
220
+ return (/^(0|[1-9]\d{0,19})$/.test(value) &&
221
+ BigInt(value) <= 18446744073709551615n);
222
+ return true;
223
+ }
224
+ export function validateImapStoredLocation(location) {
225
+ validateImapLocation(location, location.source);
226
+ if (!['valid', 'pending', 'invalid'].includes(location.status) ||
227
+ !location.id ||
228
+ !location.messageId ||
229
+ !validImapIdentity(location.providerMessageId, location.source) ||
230
+ !Number.isFinite(Date.parse(location.updatedAt)))
231
+ throw new Error('Invalid stored IMAP location.');
232
+ }
233
+ export function validateImapCopyEvidence(copy) {
234
+ validateImapLocation(copy, copy.source);
235
+ if (typeof copy.locationId !== 'string' ||
236
+ !/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(copy.locationId) ||
237
+ !validImapIdentity(copy.providerMessageId, copy.source) ||
238
+ !['objectid', 'x-gm-msgid', 'rfc-message-id', 'locator'].includes(copy.source) ||
239
+ (copy.flagsOnly !== undefined && typeof copy.flagsOnly !== 'boolean') ||
240
+ (copy.flagsOnly && !copy.observed) ||
241
+ typeof copy.read !== 'boolean' ||
242
+ typeof copy.starred !== 'boolean' ||
243
+ (copy.receivedAt !== undefined &&
244
+ (typeof copy.receivedAt !== 'string' ||
245
+ !Number.isFinite(Date.parse(copy.receivedAt)))))
246
+ throw new Error('Invalid IMAP copy evidence.');
247
+ }
248
+ /**
249
+ * Write one sync step's IMAP copies: one business message per identity, a
250
+ * location per copy, and aggregates derived from every verified copy.
251
+ */
252
+ export async function upsertImapMessages(query, accountId, messages, copies, runId, preserveUpdatedAfter) {
253
+ const safe = [];
254
+ const mirrors = new Map();
255
+ for (const copy of copies) {
256
+ validateImapCopyEvidence(copy);
257
+ const row = await query
258
+ .selectFrom(IMAP_LOCATIONS)
259
+ .selectAll()
260
+ .where('accountId', '=', accountId)
261
+ .where('providerFolderId', '=', copy.folder)
262
+ .where('uidValidity', '=', copy.uidValidity)
263
+ .where('uid', '=', copy.uid)
264
+ .executeTakeFirst();
265
+ if (!unchanged(row, copy.observed))
266
+ throw Object.assign(new Error('The IMAP copy changed during synchronization.'), { code: 'IMAP_MESSAGE_COPY_CHANGED' });
267
+ const candidates = await query
268
+ .selectFrom('mailMessages')
269
+ .selectAll()
270
+ .where('accountId', '=', accountId)
271
+ .where((builder) => builder.or([
272
+ builder('providerMessageId', '=', copy.providerMessageId),
273
+ builder('providerDraftMessageId', '=', copy.providerMessageId),
274
+ ]))
275
+ .execute();
276
+ if (candidates.length > 1)
277
+ throw new Error('The IMAP identity has conflicting owners.');
278
+ const owner = candidates[0];
279
+ const mirror = owner?.providerMessageId.startsWith('local-draft:') &&
280
+ owner.providerDraftMessageId === copy.providerMessageId;
281
+ const source = mirror
282
+ ? owner.providerDraftMessageIdSource
283
+ : owner?.imapIdSource;
284
+ if (owner && source !== copy.source)
285
+ throw new Error('The IMAP identity source conflicts with a stored message.');
286
+ if (row && owner?.id !== row.messageId)
287
+ throw new Error('The IMAP copy belongs to another message.');
288
+ if (mirror)
289
+ mirrors.set(copy.providerMessageId, owner.id);
290
+ if (owner?.scheduledSubmissionId)
291
+ continue;
292
+ safe.push(copy);
293
+ }
294
+ copies = safe;
295
+ const representatives = new Map();
296
+ for (const message of messages) {
297
+ // A remote draft mirror never overwrites locally authored content or UUID.
298
+ if (mirrors.has(message.providerMessageId) ||
299
+ !safe.some((copy) => !copy.flagsOnly &&
300
+ copy.providerMessageId === message.providerMessageId))
301
+ continue;
302
+ const current = representatives.get(message.providerMessageId);
303
+ // An incomplete copy never replaces complete content from another copy.
304
+ if (!current ||
305
+ (current.contentStatus !== undefined &&
306
+ current.contentStatus !== 'complete' &&
307
+ (message.contentStatus ?? 'complete') === 'complete'))
308
+ representatives.set(message.providerMessageId, message);
309
+ }
310
+ await upsertMessages(query, accountId, [...representatives.values()], preserveUpdatedAfter, false);
311
+ const owners = new Map(mirrors);
312
+ for (const ids of chunks([...new Set(copies.map((copy) => copy.providerMessageId))], 100)) {
313
+ const rows = await query
314
+ .selectFrom('mailMessages')
315
+ .select(['id', 'providerMessageId'])
316
+ .where('accountId', '=', accountId)
317
+ .where('providerMessageId', 'in', ids)
318
+ .execute();
319
+ for (const row of rows)
320
+ owners.set(row.providerMessageId, row.id);
321
+ }
322
+ const now = new Date().toISOString();
323
+ const touched = new Set();
324
+ for (const copy of copies) {
325
+ const messageId = owners.get(copy.providerMessageId);
326
+ // Skipped writes, such as a closed or accepted draft, keep no location.
327
+ if (!messageId)
328
+ continue;
329
+ const existing = await query
330
+ .selectFrom(IMAP_LOCATIONS)
331
+ .selectAll()
332
+ .where('accountId', '=', accountId)
333
+ .where('providerFolderId', '=', copy.folder)
334
+ .where('uidValidity', '=', copy.uidValidity)
335
+ .where('uid', '=', copy.uid)
336
+ .executeTakeFirst();
337
+ // A stored copy keeps its owner; a new identity never takes it over.
338
+ if (existing && existing.messageId !== messageId)
339
+ continue;
340
+ const values = {
341
+ status: 'valid',
342
+ invalidationReason: null,
343
+ read: copy.read,
344
+ starred: copy.starred,
345
+ receivedAt: copy.flagsOnly
346
+ ? (existing?.receivedAt ?? null)
347
+ : (copy.receivedAt ?? null),
348
+ updatedAt: existing
349
+ ? new Date(Math.max(Date.now(), Date.parse(existing.updatedAt) + 1)).toISOString()
350
+ : now,
351
+ };
352
+ if (existing) {
353
+ await query
354
+ .updateTable(IMAP_LOCATIONS)
355
+ .set(values)
356
+ .where('id', '=', existing.id)
357
+ .execute();
358
+ }
359
+ else {
360
+ await query
361
+ .insertInto(IMAP_LOCATIONS)
362
+ .values({
363
+ id: copy.locationId,
364
+ accountId,
365
+ messageId,
366
+ providerFolderId: copy.folder,
367
+ uidValidity: copy.uidValidity,
368
+ uid: copy.uid,
369
+ ...values,
370
+ createdAt: now,
371
+ })
372
+ .execute();
373
+ }
374
+ await query
375
+ .updateTable('mailMessages')
376
+ .set(mirrors.has(copy.providerMessageId)
377
+ ? { providerDraftMessageIdSource: copy.source }
378
+ : { imapIdSource: copy.source })
379
+ .where('id', '=', messageId)
380
+ .execute();
381
+ touched.add(messageId);
382
+ }
383
+ await refreshImapMessages(query, accountId, [...touched], runId);
384
+ }
385
+ /** Apply verified status changes of stored copies. */
386
+ export async function applyImapLocationChanges(query, accountId, changes, runId) {
387
+ const touched = new Set();
388
+ for (const change of changes) {
389
+ validateImapStoredLocation(change.observed);
390
+ if (change.id !== change.observed.id ||
391
+ !['valid', 'pending', 'invalid'].includes(change.status) ||
392
+ (change.reason !== undefined &&
393
+ ![
394
+ 'uid-missing',
395
+ 'folder-unavailable',
396
+ 'generation-changed',
397
+ 'generation-replaced',
398
+ ].includes(change.reason)))
399
+ throw new Error('Invalid IMAP location change.');
400
+ const row = await query
401
+ .selectFrom(IMAP_LOCATIONS)
402
+ .selectAll()
403
+ .where('accountId', '=', accountId)
404
+ .where('id', '=', change.id)
405
+ .executeTakeFirst();
406
+ if (!unchanged(row, change.observed))
407
+ throw new Error('The IMAP copy changed during verification.');
408
+ if (!row)
409
+ continue;
410
+ const owner = await query
411
+ .selectFrom('mailMessages')
412
+ .selectAll()
413
+ .where('accountId', '=', accountId)
414
+ .where('id', '=', row.messageId)
415
+ .executeTakeFirst();
416
+ const remote = owner?.providerMessageId.startsWith('local-draft:')
417
+ ? owner.providerDraftMessageId
418
+ : owner?.providerMessageId;
419
+ const source = remote === owner?.providerDraftMessageId
420
+ ? owner?.providerDraftMessageIdSource
421
+ : owner?.imapIdSource;
422
+ if (!owner ||
423
+ remote !== change.observed.providerMessageId ||
424
+ source !== change.observed.source)
425
+ throw new Error('The IMAP identity changed during verification.');
426
+ await query
427
+ .updateTable(IMAP_LOCATIONS)
428
+ .set({
429
+ status: change.status,
430
+ invalidationReason: change.reason ?? null,
431
+ updatedAt: new Date(Math.max(Date.now(), Date.parse(row.updatedAt) + 1)).toISOString(),
432
+ })
433
+ .where('id', '=', change.id)
434
+ .execute();
435
+ touched.add(row.messageId);
436
+ }
437
+ await refreshImapMessages(query, accountId, [...touched], runId);
438
+ }
439
+ /**
440
+ * Derive message state from its copies: read when every verified copy is read,
441
+ * starred when any is, received at the earliest verified copy. A message with
442
+ * no verified copy keeps its state and is marked as an orphan of this run.
443
+ */
444
+ export async function refreshImapMessages(query, accountId, messageIds, runId, updatedAt) {
445
+ if (messageIds.length === 0)
446
+ return;
447
+ const folders = new Set((await query
448
+ .selectFrom('mailFolders')
449
+ .select('providerFolderId')
450
+ .where('accountId', '=', accountId)
451
+ .execute()).map((row) => row.providerFolderId));
452
+ for (const ids of chunks(messageIds, 100)) {
453
+ const locations = await query
454
+ .selectFrom(IMAP_LOCATIONS)
455
+ .select(['messageId', 'providerFolderId', 'status', 'read', 'starred'])
456
+ .select('receivedAt')
457
+ .where('accountId', '=', accountId)
458
+ .where('messageId', 'in', ids)
459
+ .execute();
460
+ const messages = await query
461
+ .selectFrom('mailMessages')
462
+ .select(['id', 'receivedAt', 'sentAt', 'createdAt', 'providerMessageId'])
463
+ .where('accountId', '=', accountId)
464
+ .where('id', 'in', ids)
465
+ .execute();
466
+ for (const message of messages) {
467
+ const own = locations.filter((location) => location.messageId === message.id);
468
+ const valid = own.filter((location) => location.status === 'valid');
469
+ const times = valid
470
+ .map((location) => location.receivedAt ? Date.parse(String(location.receivedAt)) : NaN)
471
+ .filter((time) => Number.isFinite(time));
472
+ const receivedAt = !message.providerMessageId.startsWith('local-draft:') && times.length
473
+ ? new Date(Math.min(...times)).toISOString()
474
+ : message.receivedAt;
475
+ const values = valid.length
476
+ ? {
477
+ read: valid.every((location) => Boolean(location.read)),
478
+ starred: valid.some((location) => Boolean(location.starred)),
479
+ receivedAt,
480
+ sortAt: receivedAt ?? message.sentAt ?? message.createdAt,
481
+ imapOrphanRunId: null,
482
+ }
483
+ : runId
484
+ ? { imapOrphanRunId: runId }
485
+ : {};
486
+ if (updatedAt)
487
+ values.updatedAt = updatedAt;
488
+ if (Object.keys(values).length > 0)
489
+ await query
490
+ .updateTable('mailMessages')
491
+ .set(values)
492
+ .where('id', '=', message.id)
493
+ .execute();
494
+ // Unconfirmed copies keep their folder until verification decides.
495
+ const folderIds = new Set(own
496
+ .filter((location) => location.status === 'valid' ||
497
+ (location.status === 'pending' &&
498
+ folders.has(location.providerFolderId)))
499
+ .map((location) => location.providerFolderId));
500
+ await query
501
+ .deleteFrom('mailMessageFolders')
502
+ .where('messageId', '=', message.id)
503
+ .where('providerFolderId', '!=', MAIL_LOCAL_DRAFT_FOLDER_ID)
504
+ .execute();
505
+ if (folderIds.size > 0)
506
+ await query
507
+ .insertInto('mailMessageFolders')
508
+ .values([...folderIds].map((providerFolderId) => ({
509
+ accountId,
510
+ messageId: message.id,
511
+ providerFolderId,
512
+ })))
513
+ .execute();
514
+ }
515
+ }
516
+ }
517
+ /**
518
+ * Delete IMAP messages with no valid or pending copy after a complete,
519
+ * twice-verified run. Local, submitted and scheduled messages are never IMAP
520
+ * orphans: they carry no IMAP identity source or are locked by a schedule.
521
+ */
522
+ export async function deleteImapOrphans(query, accountId, runId) {
523
+ const orphans = await query
524
+ .selectFrom('mailMessages')
525
+ .select(['id', 'providerMessageId'])
526
+ .where('accountId', '=', accountId)
527
+ .where('imapIdSource', 'is not', null)
528
+ .where('imapOrphanRunId', '=', runId)
529
+ .where('providerMessageId', 'not like', 'local-draft:%')
530
+ .where('scheduledSubmissionId', 'is', null)
531
+ .where((builder) => builder.not(builder.exists(builder
532
+ .selectFrom(IMAP_LOCATIONS)
533
+ .select('id')
534
+ .whereRef(`${IMAP_LOCATIONS}.messageId`, '=', 'mailMessages.id')
535
+ .where(`${IMAP_LOCATIONS}.status`, 'in', ['valid', 'pending']))))
536
+ .execute();
537
+ await deleteMessages(query, accountId, orphans.map((row) => row.providerMessageId));
538
+ }
183
539
  //# sourceMappingURL=message-writes.js.map