@remit/mailbox-service 0.0.105 → 0.0.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/mailbox-service",
3
- "version": "0.0.105",
3
+ "version": "0.0.106",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -125,7 +125,9 @@ const createHarness = (
125
125
  outboxAttachmentService: {
126
126
  unfinishedUpload: async () => undefined,
127
127
  } as unknown as OutboxAttachmentService,
128
- accountService: {} as unknown as IAccountRepository,
128
+ accountService: {
129
+ get: async () => ({ syncedServices: ["Mail"] }),
130
+ } as unknown as IAccountRepository,
129
131
  sqsSmtpQueueUrl: "http://localhost/queue",
130
132
  sqsClient: {
131
133
  send: async (command: { input: { MessageBody: string } }) => {
@@ -89,7 +89,9 @@ const createHarness = (stored: OutboxMessageItem): Harness => {
89
89
  },
90
90
  unfinishedUpload: async () => undefined,
91
91
  } as unknown as OutboxAttachmentService,
92
- accountService: {} as unknown as IAccountRepository,
92
+ accountService: {
93
+ get: async () => ({ syncedServices: ["Mail"] }),
94
+ } as unknown as IAccountRepository,
93
95
  sqsSmtpQueueUrl: "http://localhost/queue",
94
96
  sqsClient: {
95
97
  send: async (command: { input: { MessageBody: string } }) => {
@@ -18,7 +18,7 @@ import type {
18
18
  OutboxAttachmentItem,
19
19
  OutboxMessageItem,
20
20
  } from "@remit/data-ports";
21
- import { BadRequestError } from "@remit/data-ports/errors";
21
+ import { BadRequestError, MailSyncOffError } from "@remit/data-ports/errors";
22
22
  import { OutboxMessageStatus } from "@remit/domain-enums";
23
23
  import type { OutboxAttachmentService } from "./outbox-attachment.js";
24
24
  import { OutboxQueueService } from "./outbox-queue.js";
@@ -55,6 +55,7 @@ const createHarness = (
55
55
  stored: OutboxMessageItem,
56
56
  attachments: OutboxAttachmentItem[] = [],
57
57
  lateAttachments: OutboxAttachmentItem[] = [],
58
+ syncedServices: string[] = ["Mail"],
58
59
  ): Harness => {
59
60
  let unfinishedChecks = 0;
60
61
  const harness: Harness = {
@@ -98,7 +99,9 @@ const createHarness = (
98
99
  return held.find((item) => item.state !== "Stored");
99
100
  },
100
101
  } as unknown as OutboxAttachmentService,
101
- accountService: {} as unknown as IAccountRepository,
102
+ accountService: {
103
+ get: async () => ({ syncedServices }),
104
+ } as unknown as IAccountRepository,
102
105
  sqsSmtpQueueUrl: "http://localhost/queue",
103
106
  sqsClient: {
104
107
  send: async (command: { input: { MessageBody: string } }) => {
@@ -241,3 +244,48 @@ describe("OutboxQueueService and a message with nowhere to go", () => {
241
244
  assert.equal(harness.enqueued.length, 1);
242
245
  });
243
246
  });
247
+
248
+ describe("OutboxQueueService and an account with mail off", () => {
249
+ const refusesWithTheFix = (error: unknown): boolean => {
250
+ assert.ok(error instanceof MailSyncOffError);
251
+ assert.equal(error.statusCode, 400);
252
+ assert.equal(error.publicApiError?.code, "mail_sync_off");
253
+ assert.match(error.message, /Turn Mail back on .* in Settings/);
254
+ return true;
255
+ };
256
+
257
+ it("refuses to queue a stored draft and leaves it a draft", async () => {
258
+ const harness = createHarness(draft({}), [], [], ["Calendar"]);
259
+
260
+ await assert.rejects(
261
+ () => harness.service.send(ACCOUNT_CONFIG_ID, OUTBOX_MESSAGE_ID),
262
+ refusesWithTheFix,
263
+ );
264
+
265
+ assert.deepEqual(harness.statusWrites, []);
266
+ assert.deepEqual(harness.enqueued, []);
267
+ });
268
+
269
+ it("refuses a send-immediately create before writing a row", async () => {
270
+ const harness = createHarness(draft({}), [], [], ["Calendar"]);
271
+
272
+ await assert.rejects(
273
+ () =>
274
+ harness.service.createAndSend(
275
+ sendInput({ toAddresses: ["them@example.com"] }),
276
+ ),
277
+ refusesWithTheFix,
278
+ );
279
+
280
+ assert.equal(harness.created, 0);
281
+ assert.deepEqual(harness.enqueued, []);
282
+ });
283
+
284
+ it("sends from an account syncing mail and calendar", async () => {
285
+ const harness = createHarness(draft({}), [], [], ["Mail", "Calendar"]);
286
+
287
+ await harness.service.send(ACCOUNT_CONFIG_ID, OUTBOX_MESSAGE_ID);
288
+
289
+ assert.equal(harness.enqueued.length, 1);
290
+ });
291
+ });
@@ -5,8 +5,12 @@ import type {
5
5
  IOutboxMessageRepository,
6
6
  OutboxMessageItem,
7
7
  } from "@remit/data-ports";
8
- import { BadRequestError, ConflictError } from "@remit/data-ports/errors";
9
- import { OutboxMessageStatus } from "@remit/domain-enums";
8
+ import {
9
+ BadRequestError,
10
+ ConflictError,
11
+ MailSyncOffError,
12
+ } from "@remit/data-ports/errors";
13
+ import { AccountService, OutboxMessageStatus } from "@remit/domain-enums";
10
14
  import { createQueueProducer } from "@remit/sqs-client/producer";
11
15
  import type { OutboxAttachmentService } from "./outbox-attachment.js";
12
16
  import { isOpenForWork } from "./outbox-status.js";
@@ -88,6 +92,9 @@ const hasNowhereToGo = (message: {
88
92
  const NO_RECIPIENT_MESSAGE =
89
93
  "This message has nobody to send to. Add a recipient before sending it.";
90
94
 
95
+ const MAIL_SYNC_OFF_SEND_MESSAGE =
96
+ "Mail is turned off for this account, so it cannot send. Turn Mail back on for this account in Settings to send from it.";
97
+
91
98
  const ENQUEUE_FAILED_MESSAGE =
92
99
  "This message could not be handed to the outgoing queue, so it was not sent. Send it again.";
93
100
 
@@ -250,6 +257,12 @@ export class OutboxQueueService {
250
257
  return updated;
251
258
  };
252
259
 
260
+ private refuseWithoutMail = async (accountId: string): Promise<void> => {
261
+ const account = await this.accountService.get(accountId);
262
+ if (account.syncedServices.includes(AccountService.Mail)) return;
263
+ throw new MailSyncOffError(MAIL_SYNC_OFF_SEND_MESSAGE, accountId);
264
+ };
265
+
253
266
  send = async (
254
267
  accountConfigId: string,
255
268
  outboxMessageId: string,
@@ -268,6 +281,7 @@ export class OutboxQueueService {
268
281
  if (hasNowhereToGo(existing)) {
269
282
  throw new BadRequestError(NO_RECIPIENT_MESSAGE);
270
283
  }
284
+ await this.refuseWithoutMail(existing.accountId);
271
285
 
272
286
  const unfinished = await this.outboxAttachmentService.unfinishedUpload(
273
287
  accountConfigId,
@@ -339,6 +353,7 @@ export class OutboxQueueService {
339
353
  if (hasNowhereToGo(input)) {
340
354
  throw new BadRequestError(NO_RECIPIENT_MESSAGE);
341
355
  }
356
+ await this.refuseWithoutMail(input.accountId);
342
357
 
343
358
  const domain = extractDomain(input.fromAddress);
344
359
  const messageIdValue = generateMessageId(domain);