mirror of
https://github.com/moparisthebest/mail
synced 2025-01-31 07:00:17 -05:00
add missing methods and tests
This commit is contained in:
parent
150cf23948
commit
0c1003c48f
@ -434,10 +434,136 @@ define(function(require) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EmailDAO.prototype.markRead = function(options, callback) {
|
||||||
|
this._imapClient.updateFlags({
|
||||||
|
path: options.folder,
|
||||||
|
uid: options.uid,
|
||||||
|
unread: false
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
EmailDAO.prototype.markAnswered = function(options, callback) {
|
||||||
|
this._imapClient.updateFlags({
|
||||||
|
path: options.folder,
|
||||||
|
uid: options.uid,
|
||||||
|
answered: true
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
EmailDAO.prototype.encryptedSend = function(options, callback) {
|
||||||
|
var self = this,
|
||||||
|
email = options.email;
|
||||||
|
|
||||||
|
// validate the email input
|
||||||
|
if (!email.to || !email.from || !email.to[0].address || !email.from[0].address) {
|
||||||
|
callback({
|
||||||
|
errMsg: 'Invalid email object!'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate email addresses
|
||||||
|
for (var i = email.to.length - 1; i >= 0; i--) {
|
||||||
|
if (!util.validateEmailAddress(email.to[i].address)) {
|
||||||
|
callback({
|
||||||
|
errMsg: 'Invalid recipient: ' + email.to[i].address
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!util.validateEmailAddress(email.from[0].address)) {
|
||||||
|
callback({
|
||||||
|
errMsg: 'Invalid sender: ' + email.from
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only support single recipient for e-2-e encryption
|
||||||
|
// check if receiver has a public key
|
||||||
|
self._keychain.getReceiverPublicKey(email.to[0].address, function(err, receiverPubkey) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate public key
|
||||||
|
if (!receiverPubkey) {
|
||||||
|
callback({
|
||||||
|
errMsg: 'User has no public key yet!'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public key found... encrypt and send
|
||||||
|
self._encrypt({
|
||||||
|
email: email,
|
||||||
|
keys: receiverPubkey.publicKey
|
||||||
|
}, function(err, email) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send({
|
||||||
|
email: email
|
||||||
|
}, callback);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
EmailDAO.prototype.send = function(options, callback) {
|
||||||
|
this._smtpClient.send(options.email, callback);
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Internal API
|
// Internal API
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// Encryption API
|
||||||
|
|
||||||
|
EmailDAO.prototype._encrypt = function(options, callback) {
|
||||||
|
var self = this,
|
||||||
|
pt = options.email.body;
|
||||||
|
|
||||||
|
options.keys = [options.keys] || [];
|
||||||
|
|
||||||
|
// get own public key so send message can be read
|
||||||
|
self._crypto.exportKeys(function(err, ownKeys) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add own public key to receiver list
|
||||||
|
options.keys.push(ownKeys.publicKeyArmored);
|
||||||
|
// encrypt the email
|
||||||
|
self._crypto.encrypt(pt, options.keys, function(err, ct) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bundle encrypted email together for sending
|
||||||
|
frameEncryptedMessage(options.email, ct);
|
||||||
|
callback(null, options.email);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function frameEncryptedMessage(email, ct) {
|
||||||
|
var greeting,
|
||||||
|
message = str.message + '\n\n\n',
|
||||||
|
signature = '\n\n' + str.signature + '\n\n';
|
||||||
|
|
||||||
|
// get first name of recipient
|
||||||
|
greeting = 'Hi ' + (email.to[0].name || email.to[0].address).split('@')[0].split('.')[0].split(' ')[0] + ',\n\n';
|
||||||
|
|
||||||
|
// build encrypted text body
|
||||||
|
email.body = greeting + message + ct + signature;
|
||||||
|
email.subject = email.subject;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Local Storage API
|
// Local Storage API
|
||||||
|
|
||||||
EmailDAO.prototype._localListMessages = function(options, callback) {
|
EmailDAO.prototype._localListMessages = function(options, callback) {
|
||||||
|
@ -15,7 +15,7 @@ define(function(require) {
|
|||||||
var dao, keychainStub, imapClientStub, smtpClientStub, pgpStub, devicestorageStub;
|
var dao, keychainStub, imapClientStub, smtpClientStub, pgpStub, devicestorageStub;
|
||||||
|
|
||||||
var emailAddress, passphrase, asymKeySize, mockkeyId, dummyEncryptedMail,
|
var emailAddress, passphrase, asymKeySize, mockkeyId, dummyEncryptedMail,
|
||||||
dummyDecryptedMail, mockKeyPair, account;
|
dummyDecryptedMail, mockKeyPair, account, publicKey;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
emailAddress = 'asdf@asdf.com';
|
emailAddress = 'asdf@asdf.com';
|
||||||
@ -60,6 +60,7 @@ define(function(require) {
|
|||||||
emailAddress: emailAddress,
|
emailAddress: emailAddress,
|
||||||
asymKeySize: asymKeySize,
|
asymKeySize: asymKeySize,
|
||||||
};
|
};
|
||||||
|
publicKey = "-----BEGIN PUBLIC KEY-----\r\n" + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxy+Te5dyeWd7g0P+8LNO7fZDQ\r\n" + "g96xTb1J6pYE/pPTMlqhB6BRItIYjZ1US5q2vk5Zk/5KasBHAc9RbCqvh9v4XFEY\r\n" + "JVmTXC4p8ft1LYuNWIaDk+R3dyYXmRNct/JC4tks2+8fD3aOvpt0WNn3R75/FGBt\r\n" + "h4BgojAXDE+PRQtcVQIDAQAB\r\n" + "-----END PUBLIC KEY-----";
|
||||||
|
|
||||||
keychainStub = sinon.createStubInstance(KeychainDAO);
|
keychainStub = sinon.createStubInstance(KeychainDAO);
|
||||||
imapClientStub = sinon.createStubInstance(ImapClient);
|
imapClientStub = sinon.createStubInstance(ImapClient);
|
||||||
@ -694,7 +695,198 @@ define(function(require) {
|
|||||||
folder: folder
|
folder: folder
|
||||||
}, after);
|
}, after);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('markAsRead', function() {
|
||||||
|
it('should work', function(done) {
|
||||||
|
imapClientStub.updateFlags.yields();
|
||||||
|
|
||||||
|
dao.markRead({
|
||||||
|
folder: 'asdf',
|
||||||
|
uid: 1
|
||||||
|
}, function(err) {
|
||||||
|
expect(imapClientStub.updateFlags.calledOnce).to.be.true;
|
||||||
|
expect(err).to.not.exist;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('markAsAnswered', function() {
|
||||||
|
it('should work', function(done) {
|
||||||
|
imapClientStub.updateFlags.yields();
|
||||||
|
|
||||||
|
dao.markAnswered({
|
||||||
|
folder: 'asdf',
|
||||||
|
uid: 1
|
||||||
|
}, function(err) {
|
||||||
|
expect(imapClientStub.updateFlags.calledOnce).to.be.true;
|
||||||
|
expect(err).to.not.exist;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('send', function() {
|
||||||
|
it('should work', function(done) {
|
||||||
|
smtpClientStub.send.withArgs(dummyEncryptedMail).yields();
|
||||||
|
|
||||||
|
dao.send({
|
||||||
|
email: dummyEncryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.not.exist;
|
||||||
|
expect(smtpClientStub.send.calledOnce).to.be.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('encryptedSend', function() {
|
||||||
|
it('should work', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt').yields(null, {});
|
||||||
|
keychainStub.getReceiverPublicKey.withArgs(dummyDecryptedMail.to[0].address).yields(null, {
|
||||||
|
_id: "fcf8b4aa-5d09-4089-8b4f-e3bc5091daf3",
|
||||||
|
userId: dummyDecryptedMail.to[0].address,
|
||||||
|
publicKey: publicKey
|
||||||
|
});
|
||||||
|
smtpClientStub.send.yields();
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.not.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true;
|
||||||
|
expect(encryptStub.calledOnce).to.be.true;
|
||||||
|
expect(smtpClientStub.send.calledOnce).to.be.true;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not work when encryption fails', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt').yields({});
|
||||||
|
keychainStub.getReceiverPublicKey.withArgs(dummyDecryptedMail.to[0].address).yields(null, {
|
||||||
|
_id: "fcf8b4aa-5d09-4089-8b4f-e3bc5091daf3",
|
||||||
|
userId: dummyDecryptedMail.to[0].address,
|
||||||
|
publicKey: publicKey
|
||||||
|
});
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true;
|
||||||
|
expect(encryptStub.calledOnce).to.be.true;
|
||||||
|
expect(smtpClientStub.send.called).to.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not work when key retrieval fails', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt');
|
||||||
|
keychainStub.getReceiverPublicKey.withArgs(dummyDecryptedMail.to[0].address).yields({});
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.calledOnce).to.be.true;
|
||||||
|
expect(encryptStub.called).to.be.false;
|
||||||
|
expect(smtpClientStub.send.called).to.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not work invalid recipients', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt');
|
||||||
|
dummyDecryptedMail.to[0].address = 'asd@asd';
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
|
||||||
|
expect(encryptStub.called).to.be.false;
|
||||||
|
expect(smtpClientStub.send.called).to.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not work with without sender', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt');
|
||||||
|
dummyDecryptedMail.from[0].address = 'asd@asd';
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
|
||||||
|
expect(encryptStub.called).to.be.false;
|
||||||
|
expect(smtpClientStub.send.called).to.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not work without recipients', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt');
|
||||||
|
delete dummyDecryptedMail.to;
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
|
||||||
|
expect(encryptStub.called).to.be.false;
|
||||||
|
expect(smtpClientStub.send.called).to.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should not work with without sender', function(done) {
|
||||||
|
var encryptStub = sinon.stub(dao, '_encrypt');
|
||||||
|
delete dummyDecryptedMail.from;
|
||||||
|
|
||||||
|
dao.encryptedSend({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.exist;
|
||||||
|
|
||||||
|
expect(keychainStub.getReceiverPublicKey.called).to.be.false;
|
||||||
|
expect(encryptStub.called).to.be.false;
|
||||||
|
expect(smtpClientStub.send.called).to.be.false;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_encrypt', function() {
|
||||||
|
it('should work without attachments', function(done) {
|
||||||
|
var ct = 'OMGSOENCRYPTED';
|
||||||
|
|
||||||
|
pgpStub.exportKeys.yields(null, {
|
||||||
|
privateKeyArmored: mockKeyPair.privateKey.encryptedKey,
|
||||||
|
publicKeyArmored: mockKeyPair.publicKey.publicKey
|
||||||
|
});
|
||||||
|
pgpStub.encrypt.yields(null, ct);
|
||||||
|
|
||||||
|
dao._encrypt({
|
||||||
|
email: dummyDecryptedMail
|
||||||
|
}, function(err) {
|
||||||
|
expect(err).to.not.exist;
|
||||||
|
|
||||||
|
expect(pgpStub.exportKeys.calledOnce).to.be.true;
|
||||||
|
expect(pgpStub.encrypt.calledOnce).to.be.true;
|
||||||
|
expect(dummyDecryptedMail.body).to.contain(ct);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user