Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions lib/api/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
const putMessage = util.promisify(messageHandler.put.bind(messageHandler));
const updateMessage = util.promisify(messageHandler.update.bind(messageHandler));

const encryptMessage = util.promisify(messageHandler.encryptMessage.bind(messageHandler));

const getMailboxCounter = tools.getMailboxCounter;
const asyncForward = util.promisify(forward);
Expand Down Expand Up @@ -2537,12 +2536,29 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
if ((userData.encryptMessages || mailboxData.encryptMessages) && !result.value.draft) {
// encrypt message if global encryption ON or encrypted target mailbox
try {
let encrypted = await encryptMessage(userData.pubKey, raw);
if (encrypted) {
raw = encrypted;
let encryptResult = await messageHandler.encryptMessageAsync(tools.getUserEncryptionKey(userData), raw);
if (encryptResult) {
raw = encryptResult.raw;
} else {
log.error('ENCRYPT', 'Encryption returned false for user %s, message stored unencrypted (source: api_messages)', user);
server.loggelf({
short_message: '[ENCRYPTSKIP] Encryption returned false during API message upload',
_mail_action: 'encrypt_skip',
_user: user,
_ip: result.value.ip || req.remoteAddress,
_source: 'api_messages'
});
}
} catch (err) {
// ignore
server.loggelf({
short_message: '[ENCRYPTFAIL] Encryption failed during API message upload',
_mail_action: 'encrypt_fail',
_user: user,
_error: err.message,
_code: err.code || 'EncryptionError',
_ip: result.value.ip || req.remoteAddress,
_source: 'api_messages'
});
}
}

Expand Down
113 changes: 69 additions & 44 deletions lib/api/submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => {
recipients: true,
encryptMessages: true,
pubKey: true,
smimeCerts: true,
smimeCipher: true,
smimeKeyTransport: true,
disabled: true,
suspended: true,
fromWhitelist: true,
Expand Down Expand Up @@ -529,56 +532,79 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => {
}

// Checks if the message needs to be encrypted before storing it
messageHandler.encryptMessage(
userData.encryptMessages ? userData.pubKey : false,
{ chunks: collector.chunks, chunklen: collector.chunklen },
(err, encrypted) => {
let raw = false;
if (!err && encrypted) {
// message was encrypted, so use the result instead of raw
raw = encrypted;
}

let meta = {
source: 'API',
from: compiledEnvelope.from,
to: compiledEnvelope.to,
origin: options.ip,
sess: options.sess,
time: new Date()
};

if (options.meta) {
Object.keys(options.meta || {}).forEach(key => {
if (!(key in meta)) {
meta[key] = options.meta[key];
}
(async () => {
let raw = false;
try {
let encryptResult = await messageHandler.encryptMessageAsync(
userData.encryptMessages ? tools.getUserEncryptionKey(userData) : false,
{ chunks: collector.chunks, chunklen: collector.chunklen }
);
if (encryptResult) {
raw = encryptResult.raw;
} else {
log.error('ENCRYPT', 'Encryption returned false for user %s, message stored unencrypted (source: api_submit)', userData._id);
server.loggelf({
short_message: '[ENCRYPTFAIL] Encryption returned false during API submit',
_mail_action: 'encrypt_skip',
_user: userData._id,
_ip: options.ip,
_sess: options.sess,
_source: 'api_submit'
});
}
} catch (err) {
server.loggelf({
short_message: '[ENCRYPTFAIL] Encryption failed during API submit',
_mail_action: 'encrypt_fail',
_user: userData._id,
_error: err.message,
_code: err.code || 'EncryptionError',
_ip: options.ip,
_sess: options.sess,
_source: 'api_submit'
});
}

let messageOptions = {
user: userData._id,
[options.mailbox ? 'mailbox' : 'specialUse']: options.mailbox
? new ObjectId(options.mailbox)
: options.isDraft
? '\\Drafts'
: '\\Sent',
let meta = {
source: 'API',
from: compiledEnvelope.from,
to: compiledEnvelope.to,
origin: options.ip,
sess: options.sess,
time: new Date()
};

if (options.meta) {
Object.keys(options.meta || {}).forEach(key => {
if (!(key in meta)) {
meta[key] = options.meta[key];
}
});
}

outbound,
let messageOptions = {
user: userData._id,
[options.mailbox ? 'mailbox' : 'specialUse']: options.mailbox
? new ObjectId(options.mailbox)
: options.isDraft
? '\\Drafts'
: '\\Sent',

meta,
outbound,

date: false,
flags: ['\\Seen'].concat(options.isDraft ? '\\Draft' : [])
};
meta,

if (raw) {
messageOptions.raw = raw;
} else {
messageOptions.raw = Buffer.concat(collector.chunks, collector.chunklen);
}
date: false,
flags: ['\\Seen'].concat(options.isDraft ? '\\Draft' : [])
};

messageHandler.add(messageOptions, (err, success, info) => {
if (raw) {
messageOptions.raw = raw;
} else {
messageOptions.raw = Buffer.concat(collector.chunks, collector.chunklen);
}

messageHandler.add(messageOptions, (err, success, info) => {
if (err) {
log.error('API', 'SUBMITFAIL user=%s error=%s', user, err.message);
err.responseCode = 500;
Expand Down Expand Up @@ -621,8 +647,7 @@ module.exports = (db, server, messageHandler, userHandler, settingsHandler) => {
}
done();
});
}
);
})();
});
});
});
Expand Down
Loading