@remit/smtp-service 0.0.20 → 1.0.0

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,42 +1,42 @@
1
1
  {
2
- "name": "@remit/smtp-service",
3
- "version": "0.0.20",
4
- "type": "module",
5
- "main": "src/index.ts",
6
- "exports": {
7
- ".": {
8
- "types": "./src/index.ts",
9
- "default": "./src/index.ts"
10
- },
11
- "./message-builder": {
12
- "types": "./src/message-builder.ts",
13
- "default": "./src/message-builder.ts"
14
- },
15
- "./test-fake-smtp": {
16
- "types": "./src/test-fake-smtp.ts",
17
- "default": "./src/test-fake-smtp.ts"
18
- }
19
- },
20
- "scripts": {
21
- "test:typecheck": "tsgo --noEmit",
22
- "test:run": "node $NODE_TEST_FLAGS --env-file=../../localhost-test-unit.env --experimental-test-coverage --test-coverage-include='src/**' --test-coverage-exclude='src/**/*.test.ts' --test-coverage-exclude='src/**/*.test.tsx' --test-coverage-lines=95 --test 'src/**/*.test.ts'",
23
- "test": "npm run test:typecheck && npm run test:run"
24
- },
25
- "devDependencies": {
26
- "@types/node": "*"
27
- },
28
- "dependencies": {
29
- "nodemailer": "^10.0.6",
30
- "@remit/data-ports": "*",
31
- "@types/nodemailer": "^8.0.1"
32
- },
33
- "license": "MIT",
34
- "publishConfig": {
35
- "access": "public"
36
- },
37
- "repository": {
38
- "type": "git",
39
- "url": "git+https://github.com/remit-mail/reader.git",
40
- "directory": "packages/smtp-service"
41
- }
2
+ "name": "@remit/smtp-service",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "src/index.ts",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./src/index.ts",
9
+ "default": "./src/index.ts"
10
+ },
11
+ "./message-builder": {
12
+ "types": "./src/message-builder.ts",
13
+ "default": "./src/message-builder.ts"
14
+ },
15
+ "./test-fake-smtp": {
16
+ "types": "./src/test-fake-smtp.ts",
17
+ "default": "./src/test-fake-smtp.ts"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "test:typecheck": "tsgo --noEmit",
22
+ "test:run": "node $NODE_TEST_FLAGS --env-file=../../localhost-test-unit.env --experimental-test-coverage --test-coverage-include='src/**' --test-coverage-exclude='src/**/*.test.ts' --test-coverage-exclude='src/**/*.test.tsx' --test-coverage-lines=95 --test 'src/**/*.test.ts'",
23
+ "test": "npm run test:typecheck && npm run test:run"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "*"
27
+ },
28
+ "dependencies": {
29
+ "nodemailer": "^10.0.6",
30
+ "@remit/data-ports": "*",
31
+ "@types/nodemailer": "^8.0.1"
32
+ },
33
+ "license": "MIT",
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/remit-mail/reader.git",
40
+ "directory": "packages/smtp-service"
41
+ }
42
42
  }
@@ -367,3 +367,49 @@ describe("renderRawMessage", () => {
367
367
  assert.equal(headerOf(raw, "Bcc"), "hidden@example.com");
368
368
  });
369
369
  });
370
+
371
+ describe("a calendar scheduling message", () => {
372
+ const ICAL = [
373
+ "BEGIN:VCALENDAR",
374
+ "VERSION:2.0",
375
+ "METHOD:REQUEST",
376
+ "BEGIN:VEVENT",
377
+ "UID:meeting@test",
378
+ "DTSTAMP:20260901T000000Z",
379
+ "DTSTART:20260907T090000Z",
380
+ "END:VEVENT",
381
+ "END:VCALENDAR",
382
+ ].join("\r\n");
383
+
384
+ it("carries its iCalendar as a text/calendar part with the iTIP method", async () => {
385
+ const raw = (
386
+ await renderRawMessage(
387
+ buildMailMessage(
388
+ baseOutbox({
389
+ subject: "Invitation: Planning",
390
+ textBody: "Invitation",
391
+ }),
392
+ [],
393
+ { method: "Request", icalData: ICAL },
394
+ ),
395
+ )
396
+ ).toString("utf8");
397
+
398
+ assert.match(raw, /Content-Type: multipart\/alternative/);
399
+ assert.match(
400
+ raw,
401
+ /Content-Type: text\/calendar; charset=utf-8; method=REQUEST/,
402
+ );
403
+ assert.match(raw, /Content-Type: text\/plain/);
404
+ });
405
+
406
+ it("is a plain message when the outbox row carries no part", async () => {
407
+ const raw = (
408
+ await renderRawMessage(
409
+ buildMailMessage(baseOutbox({ textBody: "Hi" }), [], null),
410
+ )
411
+ ).toString("utf8");
412
+
413
+ assert.doesNotMatch(raw, /text\/calendar/);
414
+ });
415
+ });
@@ -1,4 +1,7 @@
1
- import type { OutboxMessageItem } from "@remit/data-ports";
1
+ import type {
2
+ OutboxMessageItem,
3
+ OutboxSchedulingPartItem,
4
+ } from "@remit/data-ports";
2
5
  import { wireMessageId } from "@remit/data-ports/id";
3
6
  import nodemailer, { type SendMailOptions } from "nodemailer";
4
7
 
@@ -16,6 +19,8 @@ export interface MailMessage {
16
19
  references?: string | undefined;
17
20
  date?: Date | undefined;
18
21
  attachments?: MailAttachment[] | undefined;
22
+ /** A calendar scheduling message's `text/calendar; method=…` part (RFC 6047). */
23
+ icalEvent?: { method: string; content: string } | undefined;
19
24
  }
20
25
 
21
26
  export interface MailAttachment {
@@ -47,6 +52,7 @@ const placeAttachment = (
47
52
  export const buildMailMessage = (
48
53
  outbox: OutboxMessageItem,
49
54
  attachments?: MailAttachment[],
55
+ schedulingPart?: Pick<OutboxSchedulingPartItem, "method" | "icalData"> | null,
50
56
  ): MailMessage => ({
51
57
  from: formatFrom(outbox.fromAddress, outbox.fromName),
52
58
  to: outbox.toAddresses,
@@ -66,6 +72,12 @@ export const buildMailMessage = (
66
72
  attachments: attachments?.map((attachment) =>
67
73
  placeAttachment(attachment, outbox.htmlBody),
68
74
  ),
75
+ icalEvent: schedulingPart
76
+ ? {
77
+ method: schedulingPart.method.toUpperCase(),
78
+ content: schedulingPart.icalData,
79
+ }
80
+ : undefined,
69
81
  });
70
82
 
71
83
  export const toNodemailerOptions = (message: MailMessage): SendMailOptions => ({
@@ -88,6 +100,7 @@ export const toNodemailerOptions = (message: MailMessage): SendMailOptions => ({
88
100
  cid: a.cid,
89
101
  contentDisposition: a.contentDisposition,
90
102
  })),
103
+ icalEvent: message.icalEvent,
91
104
  });
92
105
 
93
106
  /** The same message as RFC822 bytes, for an IMAP APPEND. */