← back to George Gmail

test/nodemailer-security.test.js

53 lines

'use strict';

const assert = require('node:assert/strict');
const { buildAttachmentMime } = require('../lib/attachment-mime');

async function compose(message) {
  return Buffer.from(await buildAttachmentMime(message)).toString('utf8');
}

async function expectRejected(message, expectedCode) {
  await assert.rejects(
    compose(message),
    (error) => error && error.code === expectedCode,
    `expected ${expectedCode}`,
  );
}

(async () => {
  const mime = await compose({
    from: 'info@designerwallcoverings.com',
    to: 'customer@real-domain.test',
    subject: 'UTF-8 sample — Café',
    html: '<p>Attached sample.</p>',
    attachments: [{
      filename: 'sample.txt',
      content: Buffer.from('known attachment bytes', 'utf8'),
      contentType: 'text/plain',
    }],
  });

  assert.match(mime, /^From: info@designerwallcoverings\.com$/m);
  assert.match(mime, /^To: customer@real-domain\.test$/m);
  assert.match(mime, /^Subject: =\?UTF-8\?/m);
  assert.match(mime, /Content-Type: multipart\/mixed;/);
  assert.match(mime, /filename=sample\.txt/);
  assert.match(mime, /a25vd24gYXR0YWNobWVudCBieXRlcw==/);

  const common = {
    from: 'info@designerwallcoverings.com',
    to: 'customer@real-domain.test',
    subject: 'Security boundary',
  };
  await expectRejected({ ...common, html: { path: '/etc/passwd' } }, 'EFILEACCESS');
  await expectRejected({ ...common, html: { href: 'http://127.0.0.1:9/internal' } }, 'EURLACCESS');
  await expectRejected({ ...common, raw: { path: '/etc/passwd' } }, 'EFILEACCESS');
  await expectRejected({ ...common, raw: { href: 'http://127.0.0.1:9/internal' } }, 'EURLACCESS');

  console.log('Nodemailer MIME compatibility and access controls: PASS');
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});