mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-01-03 22:53:00 +08:00
395 lines
12 KiB
JavaScript
395 lines
12 KiB
JavaScript
'use strict';
|
|
|
|
const Joi = require('joi');
|
|
const ObjectID = require('mongodb').ObjectID;
|
|
const imapTools = require('../../imap-core/lib/imap-tools');
|
|
const tools = require('../tools');
|
|
|
|
module.exports = (db, server, mailboxHandler) => {
|
|
server.get('/users/:user/mailboxes', (req, res, next) => {
|
|
res.charSet('utf-8');
|
|
|
|
const schema = Joi.object().keys({
|
|
user: Joi.string().hex().lowercase().length(24).required(),
|
|
counters: Joi.boolean().truthy(['Y', 'true', 'yes', 1]).default(false)
|
|
});
|
|
|
|
if (req.query.counters) {
|
|
req.params.counters = req.query.counters;
|
|
}
|
|
|
|
const result = Joi.validate(req.params, schema, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.json({
|
|
error: result.error.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
let user = new ObjectID(result.value.user);
|
|
let counters = result.value.counters;
|
|
|
|
db.users.collection('users').findOne({
|
|
_id: user
|
|
}, {
|
|
fields: {
|
|
address: true
|
|
}
|
|
}, (err, userData) => {
|
|
if (err) {
|
|
res.json({
|
|
error: 'MongoDB Error: ' + err.message
|
|
});
|
|
return next();
|
|
}
|
|
if (!userData) {
|
|
res.json({
|
|
error: 'This user does not exist'
|
|
});
|
|
return next();
|
|
}
|
|
|
|
db.database
|
|
.collection('mailboxes')
|
|
.find({
|
|
user
|
|
})
|
|
.toArray((err, mailboxes) => {
|
|
if (err) {
|
|
res.json({
|
|
error: 'MongoDB Error: ' + err.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
if (!mailboxes) {
|
|
mailboxes = [];
|
|
}
|
|
|
|
let list = new Map();
|
|
|
|
mailboxes = mailboxes
|
|
.map(mailbox => {
|
|
list.set(mailbox.path, mailbox);
|
|
return mailbox;
|
|
})
|
|
.sort((a, b) => {
|
|
if (a.path === 'INBOX') {
|
|
return -1;
|
|
}
|
|
if (b.path === 'INBOX') {
|
|
return 1;
|
|
}
|
|
if (a.subscribed !== b.subscribed) {
|
|
return (a.subscribed ? 0 : 1) - (b.subscribed ? 0 : 1);
|
|
}
|
|
return a.path.localeCompare(b.path);
|
|
});
|
|
|
|
let responses = [];
|
|
let position = 0;
|
|
let checkMailboxes = () => {
|
|
if (position >= mailboxes.length) {
|
|
res.json({
|
|
success: true,
|
|
results: responses
|
|
});
|
|
|
|
return next();
|
|
}
|
|
|
|
let mailbox = mailboxes[position++];
|
|
let path = mailbox.path.split('/');
|
|
let name = path.pop();
|
|
|
|
let response = {
|
|
id: mailbox._id,
|
|
name,
|
|
path: mailbox.path,
|
|
specialUse: mailbox.specialUse,
|
|
modifyIndex: mailbox.modifyIndex,
|
|
subscribed: mailbox.subscribed
|
|
};
|
|
|
|
if (!counters) {
|
|
responses.push(response);
|
|
return setImmediate(checkMailboxes);
|
|
}
|
|
|
|
tools.getMailboxCounter(db, mailbox._id, false, (err, total) => {
|
|
if (err) {
|
|
// ignore
|
|
}
|
|
tools.getMailboxCounter(db, mailbox._id, 'unseen', (err, unseen) => {
|
|
if (err) {
|
|
// ignore
|
|
}
|
|
response.total = total;
|
|
response.unseen = unseen;
|
|
responses.push(response);
|
|
return setImmediate(checkMailboxes);
|
|
});
|
|
});
|
|
};
|
|
checkMailboxes();
|
|
});
|
|
});
|
|
});
|
|
|
|
server.post('/users/:user/mailboxes', (req, res, next) => {
|
|
res.charSet('utf-8');
|
|
|
|
const schema = Joi.object().keys({
|
|
user: Joi.string().hex().lowercase().length(24).required(),
|
|
path: Joi.string().regex(/\/{2,}|\/$/g, { invert: true }).required(),
|
|
retention: Joi.number().min(0)
|
|
});
|
|
|
|
const result = Joi.validate(req.params, schema, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.json({
|
|
error: result.error.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
let user = new ObjectID(result.value.user);
|
|
let path = imapTools.normalizeMailbox(result.value.path);
|
|
let retention = result.value.retention;
|
|
|
|
let opts = {
|
|
subscribed: true
|
|
};
|
|
if (retention) {
|
|
opts.retention = retention;
|
|
}
|
|
|
|
mailboxHandler.create(user, path, opts, (err, status, id) => {
|
|
if (err) {
|
|
res.json({
|
|
error: err.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
if (typeof status === 'string') {
|
|
res.json({
|
|
error: 'Mailbox creation failed with code ' + status
|
|
});
|
|
return next();
|
|
}
|
|
|
|
res.json({
|
|
success: !!status,
|
|
id
|
|
});
|
|
return next();
|
|
});
|
|
});
|
|
|
|
server.get('/users/:user/mailboxes/:mailbox', (req, res, next) => {
|
|
res.charSet('utf-8');
|
|
|
|
const schema = Joi.object().keys({
|
|
user: Joi.string().hex().lowercase().length(24).required(),
|
|
mailbox: Joi.string().hex().lowercase().length(24).required()
|
|
});
|
|
|
|
const result = Joi.validate(req.params, schema, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.json({
|
|
error: result.error.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
let user = new ObjectID(result.value.user);
|
|
let mailbox = new ObjectID(result.value.mailbox);
|
|
|
|
db.users.collection('users').findOne({
|
|
_id: user
|
|
}, {
|
|
fields: {
|
|
address: true
|
|
}
|
|
}, (err, userData) => {
|
|
if (err) {
|
|
res.json({
|
|
error: 'MongoDB Error: ' + err.message
|
|
});
|
|
return next();
|
|
}
|
|
if (!userData) {
|
|
res.json({
|
|
error: 'This user does not exist'
|
|
});
|
|
return next();
|
|
}
|
|
|
|
db.database.collection('mailboxes').findOne({
|
|
_id: mailbox,
|
|
user
|
|
}, (err, mailboxData) => {
|
|
if (err) {
|
|
res.json({
|
|
error: 'MongoDB Error: ' + err.message
|
|
});
|
|
return next();
|
|
}
|
|
if (!mailboxData) {
|
|
res.json({
|
|
error: 'This mailbox does not exist'
|
|
});
|
|
return next();
|
|
}
|
|
|
|
let path = mailboxData.path.split('/');
|
|
let name = path.pop();
|
|
|
|
tools.getMailboxCounter(db, mailbox, false, (err, total) => {
|
|
if (err) {
|
|
// ignore
|
|
}
|
|
tools.getMailboxCounter(db, mailbox, 'unseen', (err, unseen) => {
|
|
if (err) {
|
|
// ignore
|
|
}
|
|
res.json({
|
|
success: true,
|
|
id: mailbox,
|
|
name,
|
|
path: mailboxData.path,
|
|
specialUse: mailboxData.specialUse,
|
|
modifyIndex: mailboxData.modifyIndex,
|
|
subscribed: mailboxData.subscribed,
|
|
total,
|
|
unseen
|
|
});
|
|
return next();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
server.put('/users/:user/mailboxes/:mailbox', (req, res, next) => {
|
|
res.charSet('utf-8');
|
|
|
|
const schema = Joi.object().keys({
|
|
user: Joi.string().hex().lowercase().length(24).required(),
|
|
mailbox: Joi.string().hex().lowercase().length(24).required(),
|
|
path: Joi.string().regex(/\/{2,}|\/$/g, { invert: true }),
|
|
retention: Joi.number().min(0),
|
|
subscribed: Joi.boolean().truthy(['Y', 'true', 'yes', 1])
|
|
});
|
|
|
|
const result = Joi.validate(req.params, schema, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.json({
|
|
error: result.error.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
let user = new ObjectID(result.value.user);
|
|
let mailbox = new ObjectID(result.value.mailbox);
|
|
|
|
let updates = {};
|
|
let update = false;
|
|
Object.keys(result.value || {}).forEach(key => {
|
|
if (!['user', 'mailbox'].includes(key)) {
|
|
updates[key] = result.value[key];
|
|
update = true;
|
|
}
|
|
});
|
|
|
|
if (!update) {
|
|
res.json({
|
|
error: 'Nothing was changed'
|
|
});
|
|
return next();
|
|
}
|
|
|
|
mailboxHandler.update(user, mailbox, updates, (err, status) => {
|
|
if (err) {
|
|
res.json({
|
|
error: err.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
if (typeof status === 'string') {
|
|
res.json({
|
|
error: 'Mailbox update failed with code ' + status
|
|
});
|
|
return next();
|
|
}
|
|
|
|
res.json({
|
|
success: true
|
|
});
|
|
return next();
|
|
});
|
|
});
|
|
|
|
server.del('/users/:user/mailboxes/:mailbox', (req, res, next) => {
|
|
res.charSet('utf-8');
|
|
|
|
const schema = Joi.object().keys({
|
|
user: Joi.string().hex().lowercase().length(24).required(),
|
|
mailbox: Joi.string().hex().lowercase().length(24).required()
|
|
});
|
|
|
|
const result = Joi.validate(req.params, schema, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.json({
|
|
error: result.error.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
let user = new ObjectID(result.value.user);
|
|
let mailbox = new ObjectID(result.value.mailbox);
|
|
|
|
mailboxHandler.del(user, mailbox, (err, status) => {
|
|
if (err) {
|
|
res.json({
|
|
error: err.message
|
|
});
|
|
return next();
|
|
}
|
|
|
|
if (typeof status === 'string') {
|
|
res.json({
|
|
error: 'Mailbox deletion failed with code ' + status
|
|
});
|
|
return next();
|
|
}
|
|
|
|
res.json({
|
|
success: true
|
|
});
|
|
return next();
|
|
});
|
|
});
|
|
};
|