From 10be9e6b257829ed3b949f3a572ece451b6d08e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:41:28 +0300 Subject: [PATCH 1/2] chore(master): release 1.43.0 [skip-ci] (#678) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 13 +++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f09d99c..26f66591 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [1.43.0](https://github.com/nodemailer/wildduck/compare/v1.42.6...v1.43.0) (2024-04-29) + + +### Features + +* **autoacme:** Allow setting up automatic ACME certificate generation ([cd8596a](https://github.com/nodemailer/wildduck/commit/cd8596a84d36f9870858f3fdc4249f2af42347d9)) +* **SNI:** Autogenerate TLS certificates for SNI ([40db519](https://github.com/nodemailer/wildduck/commit/40db519d9c08ebe588a6ce820f6287d4f52f038f)) + + +### Bug Fixes + +* **SNI:** delete expired autogenerated SNI certificate ([61c03e1](https://github.com/nodemailer/wildduck/commit/61c03e1725c68fcb0c41e505b4d8cb80b0d73d15)) + ## [1.42.6](https://github.com/nodemailer/wildduck/compare/v1.42.5...v1.42.6) (2024-04-22) diff --git a/package-lock.json b/package-lock.json index 20e9c171..2c62dd9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wildduck", - "version": "1.42.6", + "version": "1.43.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wildduck", - "version": "1.42.6", + "version": "1.43.0", "license": "EUPL-1.2", "dependencies": { "@fidm/x509": "1.2.1", diff --git a/package.json b/package.json index 8772716e..7cfad885 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wildduck", - "version": "1.42.6", + "version": "1.43.0", "description": "IMAP/POP3 server built with Node.js and MongoDB", "main": "server.js", "scripts": { From 82133df0c9b01e9bf4fcfcfea6ed660f37aeffe3 Mon Sep 17 00:00:00 2001 From: NickOvt Date: Mon, 29 Apr 2024 13:11:27 +0300 Subject: [PATCH 2/2] fix(api-submit): Added submission api endpoint to api docs generation (#676) --- lib/api/submit.js | 209 +++++++++++++++++++++++----------------------- 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/lib/api/submit.js b/lib/api/submit.js index 86561551..47af61c9 100644 --- a/lib/api/submit.js +++ b/lib/api/submit.js @@ -12,8 +12,11 @@ const tools = require('../tools'); const Maildropper = require('../maildropper'); const roles = require('../roles'); const Transform = require('stream').Transform; -const { sessSchema, sessIPSchema, booleanSchema } = require('../schemas'); +const { sessSchema, sessIPSchema, booleanSchema, metaDataSchema } = require('../schemas'); const { preprocessAttachments } = require('../data-url'); +const { userId, mailboxId } = require('../schemas/request/general-schemas'); +const { AddressOptionalName, AddressOptionalNameArray, Header, Attachment, ReferenceWithAttachments } = require('../schemas/request/messages-schemas'); +const { successRes } = require('../schemas/response/general-schemas'); class StreamCollect extends Transform { constructor() { @@ -620,113 +623,111 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => { const submitMessageWrapper = util.promisify(submitMessage); server.post( - { name: 'send', path: '/users/:user/submit' }, + { + name: 'send', + path: '/users/:user/submit', + tags: ['Submission'], + summary: 'Submit a Message for Delivery', + description: 'Use this method to send emails from a user account', + validationObjs: { + requestBody: { + mailbox: mailboxId, + from: AddressOptionalName.description('Addres for the From: header'), + replyTo: AddressOptionalName.description('Address for the Reply-To: header'), + to: Joi.array() + .items( + Joi.object({ + name: Joi.string().empty('').max(255).description('Name of the sender'), + address: Joi.string().email({ tlds: false }).failover('').required().description('Address of the sender') + }).$_setFlag('objectName', 'AddressOptionalName') + ) + .description('Addresses for the To: header'), + + cc: AddressOptionalNameArray.description('Addresses for the Cc: header'), + + bcc: AddressOptionalNameArray.description('Addresses for the Bcc: header'), + + headers: Joi.array() + .items(Header) + .description( + 'Custom headers for the message. If reference message is set then In-Reply-To and References headers are set automatically' + ), + subject: Joi.string() + .empty('') + .max(2 * 1024) + .description('Message subject. If not then resolved from Reference message'), + text: Joi.string() + .empty('') + .max(1024 * 1024) + .description('Plaintext message'), + html: Joi.string() + .empty('') + .max(1024 * 1024) + .description('HTML formatted message'), + attachments: Joi.array().items(Attachment).description('Attachments for the message'), + + meta: metaDataSchema.label('metaData').description('Optional metadata, must be an object or JSON formatted string'), + sess: sessSchema, + ip: sessIPSchema, + reference: ReferenceWithAttachments.description( + 'Optional referenced email. If uploaded message is a reply draft and relevant fields are not provided then these are resolved from the message to be replied to' + ), + // if true then treat this message as a draft + isDraft: booleanSchema.default(false).description('Is the message a draft or not'), + // if set then this message is based on a draft that should be deleted after processing + draft: Joi.object() + .keys({ + mailbox: mailboxId, + id: Joi.number().required().description('Message ID') + }) + .description('Draft message to base this one on'), + sendTime: Joi.date().description('Send time'), + uploadOnly: booleanSchema.default(false).description('If true only uploads the message but does not send it'), + envelope: Joi.object() + .keys({ + from: AddressOptionalName.description('Addres for the From: header'), + to: Joi.array().items( + Joi.object() + .keys({ + name: Joi.string().empty('').max(255).description('Name of the sender'), + address: Joi.string().email({ tlds: false }).required().description('Address of the sender') + }) + .description('Addresses for the To: header') + ) + }) + .description('Optional envelope') + }, + queryParams: {}, + pathParams: { + user: userId + }, + response: { + 200: { + description: 'Success', + model: Joi.object({ + success: successRes, + message: Joi.object({ + mailbox: Joi.string().required().description('Mailbox ID the message was stored to'), + id: Joi.number().description('Message ID in the Mailbox').required(), + queueId: Joi.string().required().description('Queue ID in MTA') + }) + .required() + .description('Information about submitted Message') + .$_setFlag('objectName', 'MessageWithQueueId') + }) + } + } + } + }, tools.responseWrapper(async (req, res) => { res.charSet('utf-8'); - const schema = Joi.object().keys({ - user: Joi.string().hex().lowercase().length(24).required(), + const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs; - mailbox: Joi.string().hex().lowercase().length(24), - - reference: Joi.object().keys({ - mailbox: Joi.string().hex().lowercase().length(24).required(), - id: Joi.number().required(), - action: Joi.string().valid('reply', 'replyAll', 'forward').required() - }), - - // if true then treat this message as a draft - isDraft: booleanSchema.default(false), - - // if set then this message is based on a draft that should be deleted after processing - draft: Joi.object().keys({ - mailbox: Joi.string().hex().lowercase().length(24).required(), - id: Joi.number().required() - }), - - uploadOnly: booleanSchema.default(false), - - sendTime: Joi.date(), - - envelope: Joi.object().keys({ - from: Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }), - to: Joi.array().items( - Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }) - ) - }), - - from: Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }), - - replyTo: Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }), - - to: Joi.array().items( - Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }) - ), - - cc: Joi.array().items( - Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }) - ), - - bcc: Joi.array().items( - Joi.object().keys({ - name: Joi.string().empty('').max(255), - address: Joi.string().email({ tlds: false }).required() - }) - ), - - headers: Joi.array().items( - Joi.object().keys({ - key: Joi.string().empty('').max(255), - value: Joi.string() - .empty('') - .max(100 * 1024) - }) - ), - - subject: Joi.string() - .empty('') - .max(2 * 1024), - text: Joi.string() - .empty('') - .max(1024 * 1024), - html: Joi.string() - .empty('') - .max(1024 * 1024), - - attachments: Joi.array().items( - Joi.object().keys({ - filename: Joi.string().empty('').max(255), - - contentType: Joi.string().empty('').max(255), - contentTransferEncoding: Joi.string().empty('').trim().lowercase(), - contentDisposition: Joi.string().empty('').trim().lowercase().valid('inline', 'attachment'), - cid: Joi.string().empty('').max(255), - - encoding: Joi.string().empty('').default('base64'), - content: Joi.string().required() - }) - ), - meta: Joi.object().unknown(true), - sess: sessSchema, - ip: sessIPSchema + const schema = Joi.object({ + ...pathParams, + ...requestBody, + ...queryParams }); // extract embedded attachments from HTML