From 48ffa5d80c93243798256bf477552bc848d7e952 Mon Sep 17 00:00:00 2001 From: harryadel Date: Sat, 3 Feb 2024 16:00:46 +0200 Subject: [PATCH] Add nodemailer-openpgp --- .../email/.npm/package/npm-shrinkwrap.json | 46 +++++++++++++++++-- packages/email/email.js | 24 ++++++---- packages/email/email_tests.js | 26 +++++++++++ packages/email/package.js | 1 + 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json index 3f7ff7a0a2..9f74f661fc 100644 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ b/packages/email/.npm/package/npm-shrinkwrap.json @@ -2,24 +2,64 @@ "lockfileVersion": 1, "dependencies": { "@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==" }, "@types/nodemailer": { "version": "6.4.7", "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz", "integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==" }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==" + }, + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, "nodemailer": { "version": "6.6.3", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz", "integrity": "sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==" }, + "nodemailer-openpgp": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nodemailer-openpgp/-/nodemailer-openpgp-2.2.0.tgz", + "integrity": "sha512-e6+pgGVpMEZ2ywHcAtTdKhUCU5HwZI23RFoNUA/mJPytUW369mQqEcHFLUoxEITOLrzeoLjn5wOYFYzSpef+Tg==" + }, + "openpgp": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-5.9.0.tgz", + "integrity": "sha512-wEI6TAinCAq8ZLZA4oZ3ZtJ2BhhHj+CiPCd8TzE7zCicr0V8tvG5UF76OtddLLOJcK63w3Aj3KiRd+VLMScirQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "stream-buffers": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==" + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" } } } diff --git a/packages/email/email.js b/packages/email/email.js index eed8dbd9b3..fa0710364c 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -5,6 +5,7 @@ import { Hook } from 'meteor/callback-hook'; import url from 'url'; import nodemailer from 'nodemailer'; import wellKnow from 'nodemailer/lib/well-known'; +import { openpgpEncrypt } from 'nodemailer-openpgp'; export const Email = {}; export const EmailTest = {}; @@ -24,7 +25,7 @@ export const EmailInternals = { const MailComposer = EmailInternals.NpmModules.mailcomposer.module; -const makeTransport = function (mailUrlString) { +const makeTransport = function (mailUrlString, options) { const mailUrl = new URL(mailUrlString); if (mailUrl.protocol !== 'smtp:' && mailUrl.protocol !== 'smtps:') { @@ -53,13 +54,15 @@ const makeTransport = function (mailUrlString) { } const transport = nodemailer.createTransport(url.format(mailUrl)); - + if (options?.encryptionKeys || options?.shouldSign) { + transport.use('stream', openpgpEncrypt(options)); + } transport._syncSendMail = Meteor.wrapAsync(transport.sendMail, transport); return transport; }; // More info: https://nodemailer.com/smtp/well-known/ -const knownHostsTransport = function (settings = undefined, url = undefined) { +const knownHostsTransport = function (settings = undefined, url = undefined, options) { let service, user, password; const hasSettings = settings && Object.keys(settings).length; @@ -104,12 +107,15 @@ const knownHostsTransport = function (settings = undefined, url = undefined) { }, }); + if (options?.encryptionKeys || options?.shouldSign) { + transport.use('stream', openpgpEncrypt(options)); + } transport._syncSendMail = Meteor.wrapAsync(transport.sendMail, transport); return transport; }; EmailTest.knowHostsTransport = knownHostsTransport; -const getTransport = function () { +const getTransport = function (options) { const packageSettings = Meteor.settings.packages?.email || {}; // We delay this check until the first call to Email.send, in case someone // set process.env.MAIL_URL in startup code. Then we store in a cache until @@ -127,10 +133,10 @@ const getTransport = function () { wellKnow(url?.split(':')[0] || '') ) { this.cacheKey = packageSettings.service || 'settings'; - this.cache = knownHostsTransport(packageSettings, url); + this.cache = knownHostsTransport(packageSettings, url, options); } else { this.cacheKey = url; - this.cache = url ? makeTransport(url, packageSettings) : null; + this.cache = url ? makeTransport(url, options) : null; } } return this.cache; @@ -282,7 +288,9 @@ Email.send = function (options) { * object representing the message to be sent. Overrides all other options. * You can create a `MailComposer` object via * `new EmailInternals.NpmModules.mailcomposer.module`. - */ + * @param {String} [options.encryptionKeys] An array that holds the public keys used to encrypt. + * @param {String} [options.shouldSign] Enables you to allow or disallow email signing. +*/ Email.sendAsync = async function (options) { const email = options.mailComposer ? options.mailComposer.mail : options; @@ -313,7 +321,7 @@ Email.sendAsync = async function (options) { } if (mailUrlEnv || mailUrlSettings) { - const transport = getTransport(); + const transport = getTransport(options); smtpSend(transport, email); return; } diff --git a/packages/email/email_tests.js b/packages/email/email_tests.js index 6f016f26b9..1c384d9b25 100644 --- a/packages/email/email_tests.js +++ b/packages/email/email_tests.js @@ -273,6 +273,32 @@ Tinytest.addAsync( } ); +Tinytest.addAsync( + '[Async] email - with custom encryption', + function (test, onComplete) { + const allPromises = []; + smokeEmailTest((stream) => { + Email.customTransport = (options) => { + test.equal(options.encryptionKeys, ['-----BEGIN PGP PUBLIC KEY BLOCK-----…']); + test.equal(options.shouldSign, true); + }; + allPromises.push( + Email.sendAsync({ + from: 'foo@example.com', + to: 'bar@example.com', + text: '*Cool*, man', + html: 'Cool, man', + encryptionKeys: ['-----BEGIN PGP PUBLIC KEY BLOCK-----…'], + shouldSign: true + }).then(() => { + test.equal(stream.getContentsAsString('utf8'), false); + }) + ); + Promise.all(allPromises).then(() => onComplete()); + }); + } +); + Tinytest.addAsync( '[Async] email - with custom transport long time running', async function (test) { diff --git a/packages/email/package.js b/packages/email/package.js index 4f5a14bf98..ba6db7ea87 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -7,6 +7,7 @@ Npm.depends({ nodemailer: '6.6.3', 'stream-buffers': '3.0.2', '@types/nodemailer': '6.4.7', + 'nodemailer-openpgp' : '2.2.0' }); Package.onUse(function(api) {