mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-12-27 02:10:52 +08:00
Merge branch 'master' of github.com:nodemailer/wildduck
This commit is contained in:
commit
5af8f24ddb
4 changed files with 121 additions and 107 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,5 +1,18 @@
|
||||||
# Changelog
|
# 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)
|
## [1.42.6](https://github.com/nodemailer/wildduck/compare/v1.42.5...v1.42.6) (2024-04-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,11 @@ const tools = require('../tools');
|
||||||
const Maildropper = require('../maildropper');
|
const Maildropper = require('../maildropper');
|
||||||
const roles = require('../roles');
|
const roles = require('../roles');
|
||||||
const Transform = require('stream').Transform;
|
const Transform = require('stream').Transform;
|
||||||
const { sessSchema, sessIPSchema, booleanSchema } = require('../schemas');
|
const { sessSchema, sessIPSchema, booleanSchema, metaDataSchema } = require('../schemas');
|
||||||
const { preprocessAttachments } = require('../data-url');
|
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 {
|
class StreamCollect extends Transform {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -620,113 +623,111 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => {
|
||||||
const submitMessageWrapper = util.promisify(submitMessage);
|
const submitMessageWrapper = util.promisify(submitMessage);
|
||||||
|
|
||||||
server.post(
|
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) => {
|
tools.responseWrapper(async (req, res) => {
|
||||||
res.charSet('utf-8');
|
res.charSet('utf-8');
|
||||||
|
|
||||||
const schema = Joi.object().keys({
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
||||||
user: Joi.string().hex().lowercase().length(24).required(),
|
|
||||||
|
|
||||||
mailbox: Joi.string().hex().lowercase().length(24),
|
const schema = Joi.object({
|
||||||
|
...pathParams,
|
||||||
reference: Joi.object().keys({
|
...requestBody,
|
||||||
mailbox: Joi.string().hex().lowercase().length(24).required(),
|
...queryParams
|
||||||
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
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// extract embedded attachments from HTML
|
// extract embedded attachments from HTML
|
||||||
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "wildduck",
|
"name": "wildduck",
|
||||||
"version": "1.42.6",
|
"version": "1.43.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "wildduck",
|
"name": "wildduck",
|
||||||
"version": "1.42.6",
|
"version": "1.43.0",
|
||||||
"license": "EUPL-1.2",
|
"license": "EUPL-1.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fidm/x509": "1.2.1",
|
"@fidm/x509": "1.2.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "wildduck",
|
"name": "wildduck",
|
||||||
"version": "1.42.6",
|
"version": "1.43.0",
|
||||||
"description": "IMAP/POP3 server built with Node.js and MongoDB",
|
"description": "IMAP/POP3 server built with Node.js and MongoDB",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
Loading…
Reference in a new issue