mirror of
https://github.com/moparisthebest/mail
synced 2024-11-26 10:52:17 -05:00
sending end-2-end encrypted emails internally work
This commit is contained in:
parent
a4f03bdca1
commit
699871276c
@ -84,6 +84,14 @@ define(['jquery', 'js/app-config'], function($, app) {
|
|||||||
self.put(item, uri, callback);
|
self.put(item, uri, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deliver an email to the user's outbox
|
||||||
|
*/
|
||||||
|
self.deliverEmail = function(email, from, to, callback) {
|
||||||
|
var uri = app.config.cloudUrl + '/email/user/' + from + '/folder/outbox/' + email.id + '?to=' + to;
|
||||||
|
self.put(email, uri, callback);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an encrypted item from the cloud
|
* Delete an encrypted item from the cloud
|
||||||
* @param type [String] The type of item e.g. 'email'
|
* @param type [String] The type of item e.g. 'email'
|
||||||
|
@ -143,7 +143,7 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/lawnchair-da
|
|||||||
var filter = '';
|
var filter = '';
|
||||||
if (localItems && localItems.length > 0) {
|
if (localItems && localItems.length > 0) {
|
||||||
// sync delta of last item sent date
|
// sync delta of last item sent date
|
||||||
filter = '?date=' + localItems[localItems.length - 1].sentDate;
|
//filter = '?date=' + localItems[localItems.length - 1].sentDate;
|
||||||
startSync(filter);
|
startSync(filter);
|
||||||
} else {
|
} else {
|
||||||
// do a full sync of all items on the cloud
|
// do a full sync of all items on the cloud
|
||||||
@ -225,9 +225,9 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/lawnchair-da
|
|||||||
|
|
||||||
// validate email addresses
|
// validate email addresses
|
||||||
var invalidRecipient;
|
var invalidRecipient;
|
||||||
_.each(email.to, function(address) {
|
_.each(email.to, function(i) {
|
||||||
if (!validateEmail(address)) {
|
if (!validateEmail(i.address)) {
|
||||||
invalidRecipient = address;
|
invalidRecipient = i.address;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (invalidRecipient) {
|
if (invalidRecipient) {
|
||||||
@ -236,7 +236,7 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/lawnchair-da
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!validateEmail(email.from)) {
|
if (!validateEmail(email.from[0].address)) {
|
||||||
callback({
|
callback({
|
||||||
errMsg: 'Invalid sender: ' + email.from
|
errMsg: 'Invalid sender: ' + email.from
|
||||||
});
|
});
|
||||||
@ -245,11 +245,59 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/lawnchair-da
|
|||||||
|
|
||||||
// generate a new UUID for the new email
|
// generate a new UUID for the new email
|
||||||
email.id = util.UUID();
|
email.id = util.UUID();
|
||||||
|
// set sent date
|
||||||
|
email.sentDate = util.formatDate(new Date());
|
||||||
|
|
||||||
|
// only support single recipient for e-2-e encryption
|
||||||
|
var recipient = email.to[0].address;
|
||||||
|
|
||||||
|
// check if receiver has a public key
|
||||||
|
keychain.getReveiverPublicKey(recipient, function(err, receiverPubkey) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receiverPubkey) {
|
||||||
|
// public key found... encrypt and send
|
||||||
|
encrypt(email, receiverPubkey);
|
||||||
|
} else {
|
||||||
|
// no public key found... send plaintext mail via SMTP
|
||||||
|
send(email);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function encrypt(email, receiverPubkey) {
|
||||||
|
// encrypt the email
|
||||||
|
crypto.encryptListForUser([email], [receiverPubkey], function(err, encryptedList) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ct = encryptedList[0];
|
||||||
|
|
||||||
|
var envelope = {
|
||||||
|
id: email.id,
|
||||||
|
crypto: 'rsa-1024-sha-256-aes-128-cbc',
|
||||||
|
sentDate: email.sentDate,
|
||||||
|
ciphertext: ct.ciphertext,
|
||||||
|
encryptedKey: ct.encryptedKey,
|
||||||
|
iv: ct.iv,
|
||||||
|
signature: ct.signature,
|
||||||
|
senderPk: ct.senderPk
|
||||||
|
};
|
||||||
|
|
||||||
|
send(envelope);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function send(email) {
|
||||||
// send email to cloud service
|
// send email to cloud service
|
||||||
cloudstorage.putEncryptedItem(email, 'email', userId, 'outbox', function(err) {
|
cloudstorage.deliverEmail(email, userId, recipient, function(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,6 +46,51 @@ define(['underscore', 'js/dao/lawnchair-dao'], function(_, jsonDao) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a reveiver's public key by user id
|
||||||
|
* @param userId [String] the receiver's email address
|
||||||
|
*/
|
||||||
|
self.getReveiverPublicKey = function(userId, callback) {
|
||||||
|
// search local keyring for public key
|
||||||
|
jsonDao.list('publickey', 0, null, function(allPubkeys) {
|
||||||
|
var pubkey = _.findWhere(allPubkeys, {
|
||||||
|
userId: userId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pubkey || !pubkey._id) {
|
||||||
|
// no public key by that user id in storage
|
||||||
|
// find from cloud by email address
|
||||||
|
cloudstorage.getPublicKeyByUserId(userId, function(err, cloudPubkey) {
|
||||||
|
if (err || !cloudPubkey) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cloudPubkey && cloudPubkey._id) {
|
||||||
|
// there is a public key for that user already in the cloud...
|
||||||
|
// save to local storage
|
||||||
|
saveLocalPublicKey(cloudPubkey, function(err) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, cloudPubkey);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// no public key for that user
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// that user's public key is already in local storage
|
||||||
|
callback(null, pubkey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the local user's key either from local storage
|
* Gets the local user's key either from local storage
|
||||||
* or fetches it from the cloud. The private key is encrypted.
|
* or fetches it from the cloud. The private key is encrypted.
|
||||||
|
@ -105,11 +105,21 @@ define(['jquery', 'underscore', 'backbone', 'js/app-config'], function($, _, Bac
|
|||||||
var signature = '\n\nSent with whiteout mail - get your free mailbox for end-2-end encrypted messaging!\nhttps://mail.whiteout.io';
|
var signature = '\n\nSent with whiteout mail - get your free mailbox for end-2-end encrypted messaging!\nhttps://mail.whiteout.io';
|
||||||
|
|
||||||
var email = {
|
var email = {
|
||||||
from: self.account,
|
to: [],
|
||||||
to: to,
|
|
||||||
subject: page.find('#subjectInput').val(),
|
subject: page.find('#subjectInput').val(),
|
||||||
body: page.find('#bodyTextarea').val() + signature
|
body: page.find('#bodyTextarea').val() + signature
|
||||||
};
|
};
|
||||||
|
email.from = [{
|
||||||
|
name: '',
|
||||||
|
address: self.account
|
||||||
|
}
|
||||||
|
];
|
||||||
|
to.forEach(function(address) {
|
||||||
|
email.to.push({
|
||||||
|
name: '',
|
||||||
|
address: address
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// post message to main window
|
// post message to main window
|
||||||
app.util.postMessage('sendEmail', {
|
app.util.postMessage('sendEmail', {
|
||||||
|
@ -161,13 +161,40 @@ define(['js/dao/email-dao', 'js/dao/keychain-dao', 'js/dao/lawnchair-dao',
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("Send Plaintext Email item", 1, function() {
|
asyncTest("Send e-2-e Encrypted Email item", 1, function() {
|
||||||
var email = {
|
var email = {
|
||||||
from: cloudstoragedaoTest.user, // sender address
|
|
||||||
to: [cloudstoragedaoTest.user], // list of receivers
|
|
||||||
subject: 'Client Email DAO Test', // Subject line
|
subject: 'Client Email DAO Test', // Subject line
|
||||||
body: 'Hello world' // plaintext body
|
body: 'Hello world' // plaintext body
|
||||||
};
|
};
|
||||||
|
email.from = [{
|
||||||
|
address: cloudstoragedaoTest.user
|
||||||
|
}
|
||||||
|
];
|
||||||
|
email.to = [{
|
||||||
|
address: cloudstoragedaoTest.user
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
cloudstoragedaoTest.emailDao.sendEmail(email, function(err) {
|
||||||
|
ok(!err, 'Email sent');
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("Send Plaintext Email item", 1, function() {
|
||||||
|
var email = {
|
||||||
|
subject: 'Client Email DAO Test', // Subject line
|
||||||
|
body: 'Hello world' // plaintext body
|
||||||
|
};
|
||||||
|
email.from = [{
|
||||||
|
address: cloudstoragedaoTest.user
|
||||||
|
}
|
||||||
|
];
|
||||||
|
email.to = [{
|
||||||
|
address: 'safewithme.testuser@gmail.com'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
cloudstoragedaoTest.emailDao.sendEmail(email, function(err) {
|
cloudstoragedaoTest.emailDao.sendEmail(email, function(err) {
|
||||||
ok(!err, 'Email sent');
|
ok(!err, 'Email sent');
|
||||||
|
@ -81,4 +81,13 @@ define(['js/dao/keychain-dao', 'js/dao/lawnchair-dao'], function(KeychainDAO, js
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
asyncTest("Get User Keypair", 2, function() {
|
||||||
|
keychaindaoTest.keychainDao.getReveiverPublicKey(keychaindaoTest.user, function(err, pubkey) {
|
||||||
|
ok(!err);
|
||||||
|
ok(pubkey && pubkey.publicKey);
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user