@remit/smtp-service 0.0.15 → 0.0.16

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/smtp-service",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -132,7 +132,7 @@ describe("buildMailMessage", () => {
132
132
  },
133
133
  ];
134
134
  const message = buildMailMessage(baseOutbox(), attachments);
135
- assert.equal(message.attachments, attachments);
135
+ assert.deepEqual(message.attachments, attachments);
136
136
  });
137
137
 
138
138
  it("leaves attachments undefined when none are provided", () => {
@@ -257,6 +257,53 @@ describe("renderRawMessage", () => {
257
257
  assert.ok(raw.includes(Buffer.from("png-bytes").toString("base64")));
258
258
  });
259
259
 
260
+ it("puts a file the html body refers to inline, next to the html", async () => {
261
+ const raw = String(
262
+ await renderRawMessage(
263
+ buildMailMessage(
264
+ baseOutbox({
265
+ textBody: "see below",
266
+ htmlBody: '<p>see below</p><p><img src="cid:shot-1@remit"></p>',
267
+ }),
268
+ [
269
+ {
270
+ filename: "shot.png",
271
+ content: Buffer.from("png-bytes"),
272
+ contentType: "image/png",
273
+ cid: "shot-1@remit",
274
+ },
275
+ ],
276
+ ),
277
+ ),
278
+ );
279
+
280
+ assert.match(raw, /Content-Type: multipart\/related; type="text\/html"/);
281
+ assert.match(raw, /Content-Disposition: inline; filename=shot\.png/);
282
+ assert.match(raw, /Content-ID: <shot-1@remit>/);
283
+ });
284
+
285
+ it("sends a file the html body does not refer to as an ordinary attachment", async () => {
286
+ const raw = String(
287
+ await renderRawMessage(
288
+ buildMailMessage(
289
+ baseOutbox({ textBody: "attached", htmlBody: "<p>attached</p>" }),
290
+ [
291
+ {
292
+ filename: "photo.png",
293
+ content: Buffer.from("png-bytes"),
294
+ contentType: "image/png",
295
+ cid: "photo-1@remit",
296
+ },
297
+ ],
298
+ ),
299
+ ),
300
+ );
301
+
302
+ assert.match(raw, /Content-Disposition: attachment; filename=photo\.png/);
303
+ assert.ok(!raw.includes("Content-ID"));
304
+ assert.ok(!raw.includes("multipart/related"));
305
+ });
306
+
260
307
  it("dates the rendered copy from the moment the send was recorded", async () => {
261
308
  const raw = String(
262
309
  await renderRawMessage(
@@ -30,6 +30,18 @@ export interface MailAttachment {
30
30
  const formatFrom = (address: string, name: string | undefined): string =>
31
31
  name ? `"${name.replace(/(["\\])/g, "\\$1")}" <${address}>` : address;
32
32
 
33
+ const placeAttachment = (
34
+ attachment: MailAttachment,
35
+ html: string | undefined,
36
+ ): MailAttachment => {
37
+ if (!attachment.cid || attachment.contentDisposition) return attachment;
38
+ if (html?.includes(`cid:${attachment.cid}`)) {
39
+ return { ...attachment, contentDisposition: "inline" };
40
+ }
41
+ const { cid: _unreferenced, ...standalone } = attachment;
42
+ return standalone;
43
+ };
44
+
33
45
  /** The one description of an outgoing message: the wire copy and the Sent copy. */
34
46
  export const buildMailMessage = (
35
47
  outbox: OutboxMessageItem,
@@ -50,7 +62,9 @@ export const buildMailMessage = (
50
62
  // submission is accepted, so on the wire path this is always absent and
51
63
  // nodemailer dates the message as it goes out.
52
64
  date: outbox.sentAt ? new Date(outbox.sentAt) : undefined,
53
- attachments,
65
+ attachments: attachments?.map((attachment) =>
66
+ placeAttachment(attachment, outbox.htmlBody),
67
+ ),
54
68
  });
55
69
 
56
70
  export const toNodemailerOptions = (message: MailMessage): SendMailOptions => ({