mirror of
https://github.com/moparisthebest/mail
synced 2024-11-29 20:32:15 -05:00
[WO-18] introduce invitation email functionality
This commit is contained in:
parent
8e8947e742
commit
93ddfb1c99
@ -38,6 +38,8 @@ define([], function() {
|
|||||||
*/
|
*/
|
||||||
app.string = {
|
app.string = {
|
||||||
subjectPrefix: '[whiteout] ',
|
subjectPrefix: '[whiteout] ',
|
||||||
|
invitationSubject: 'Invitation to your secure eMail experience',
|
||||||
|
invitationMessage: 'I would like to invite you to a private conversation. To read my encrypted messages, simply install Whiteout Mail for Chrome. The app is really easy to use and automatically encrypts sent emails, so that only the two of us can read them: https://chrome.google.com/webstore/detail/jjgghafhamholjigjoghcfcekhkonijg',
|
||||||
message: 'this is a private conversation. To read my encrypted message below, simply install Whiteout Mail for Chrome. The app is really easy to use and automatically encrypts sent emails, so that only the two of us can read them: https://chrome.google.com/webstore/detail/jjgghafhamholjigjoghcfcekhkonijg',
|
message: 'this is a private conversation. To read my encrypted message below, simply install Whiteout Mail for Chrome. The app is really easy to use and automatically encrypts sent emails, so that only the two of us can read them: https://chrome.google.com/webstore/detail/jjgghafhamholjigjoghcfcekhkonijg',
|
||||||
cryptPrefix: '-----BEGIN PGP MESSAGE-----',
|
cryptPrefix: '-----BEGIN PGP MESSAGE-----',
|
||||||
cryptSuffix: '-----END PGP MESSAGE-----',
|
cryptSuffix: '-----END PGP MESSAGE-----',
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
define(function(require) {
|
define(function(require) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var config = require('js/app-config').config,
|
var _ = require('underscore'),
|
||||||
|
str = require('js/app-config').string,
|
||||||
|
config = require('js/app-config').config,
|
||||||
|
InvitationDAO = require('js/dao/invitation-dao'),
|
||||||
dbType = 'email_OUTBOX';
|
dbType = 'email_OUTBOX';
|
||||||
|
|
||||||
var OutboxBO = function(emailDao, invitationDao) {
|
var OutboxBO = function(emailDao, invitationDao) {
|
||||||
@ -12,7 +15,7 @@ define(function(require) {
|
|||||||
|
|
||||||
OutboxBO.prototype.startChecking = function(callback) {
|
OutboxBO.prototype.startChecking = function(callback) {
|
||||||
// start periodic checking of outbox
|
// start periodic checking of outbox
|
||||||
this._intervalId = setInterval(this._emptyOutbox.bind(this, callback), config.checkOutboxInterval);
|
this._intervalId = setInterval(this._processOutbox.bind(this, callback), config.checkOutboxInterval);
|
||||||
};
|
};
|
||||||
|
|
||||||
OutboxBO.prototype.stopChecking = function() {
|
OutboxBO.prototype.stopChecking = function() {
|
||||||
@ -24,7 +27,7 @@ define(function(require) {
|
|||||||
delete this._intervalId;
|
delete this._intervalId;
|
||||||
};
|
};
|
||||||
|
|
||||||
OutboxBO.prototype._emptyOutbox = function(callback) {
|
OutboxBO.prototype._processOutbox = function(callback) {
|
||||||
var self = this,
|
var self = this,
|
||||||
emails;
|
emails;
|
||||||
|
|
||||||
@ -49,19 +52,115 @@ define(function(require) {
|
|||||||
emails = pending;
|
emails = pending;
|
||||||
|
|
||||||
// sending pending mails
|
// sending pending mails
|
||||||
send();
|
processMails();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function send() {
|
function processMails() {
|
||||||
callback(null, emails.length);
|
// in the navigation controller, this updates the folder count
|
||||||
|
|
||||||
if (emails.length === 0) {
|
if (emails.length === 0) {
|
||||||
self._outboxBusy = false;
|
self._outboxBusy = false;
|
||||||
|
callback(null, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback(null, emails.length);
|
||||||
var email = emails.shift();
|
var email = emails.shift();
|
||||||
|
checkReceivers(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkReceivers(email) {
|
||||||
|
var unregisteredUsers, receiverChecked;
|
||||||
|
|
||||||
|
unregisteredUsers = [];
|
||||||
|
receiverChecked = _.after(email.to.length, function() {
|
||||||
|
if (unregisteredUsers.length > 0) {
|
||||||
|
invite(unregisteredUsers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEncrypted(email);
|
||||||
|
});
|
||||||
|
|
||||||
|
email.to.forEach(function(recipient) {
|
||||||
|
self._emailDao._keychain.getReceiverPublicKey(recipient.address, function(err, key) {
|
||||||
|
if (err) {
|
||||||
|
// stop processing
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!key) {
|
||||||
|
unregisteredUsers.push(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
receiverChecked();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function invite(addresses) {
|
||||||
|
var sender = self._emailDao._account.emailAddress;
|
||||||
|
|
||||||
|
var invitationFinished = _.after(addresses.length, function() {
|
||||||
|
// after all of the invitations are checked and sent (if necessary),
|
||||||
|
//
|
||||||
|
processMails();
|
||||||
|
});
|
||||||
|
|
||||||
|
// send invite
|
||||||
|
addresses.forEach(function(recipient) {
|
||||||
|
var recipientAddress = recipient.address;
|
||||||
|
self._invitationDao.check({
|
||||||
|
recipient: recipientAddress,
|
||||||
|
sender: sender
|
||||||
|
}, function(err, status) {
|
||||||
|
if (status === InvitationDAO.INVITE_PENDING) {
|
||||||
|
// the recipient is already invited, we're done here.
|
||||||
|
invitationFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the recipient is not yet invited, so let's do that
|
||||||
|
self._invitationDao.invite({
|
||||||
|
recipient: recipientAddress,
|
||||||
|
sender: sender
|
||||||
|
}, function(err, status) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err.errMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (status !== InvitationDAO.INVITE_SUCCESS) {
|
||||||
|
console.error('could not successfully invite ' + recipientAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendInvitationMail(recipient, sender);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendInvitationMail(recipient, sender) {
|
||||||
|
var to = (recipient.name || recipient.address).split('@')[0].split('.')[0].split(' ')[0],
|
||||||
|
invitationMail = {
|
||||||
|
from: [sender],
|
||||||
|
to: [recipient],
|
||||||
|
subject: str.invitationSubject,
|
||||||
|
body: 'Hi ' + to + ',\n\n' + str.invitationMessage + '\n\n\n' + str.signature
|
||||||
|
};
|
||||||
|
|
||||||
|
// send invitation mail
|
||||||
|
self._emailDao.send(invitationMail, function(err) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err.errMsg);
|
||||||
|
}
|
||||||
|
invitationFinished();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function sendEncrypted(email) {
|
||||||
self._emailDao.encryptedSend(email, function(err) {
|
self._emailDao.encryptedSend(email, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self._outboxBusy = false;
|
self._outboxBusy = false;
|
||||||
@ -91,7 +190,7 @@ define(function(require) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
send();
|
processMails();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -578,8 +578,6 @@ define(function(require) {
|
|||||||
callback({
|
callback({
|
||||||
errMsg: 'User has no public key yet!'
|
errMsg: 'User has no public key yet!'
|
||||||
});
|
});
|
||||||
// user hasn't registered a public key yet... invite
|
|
||||||
//self.encryptForNewUser(email, callback);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,17 +2,24 @@ define(function(require) {
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var expect = chai.expect,
|
var expect = chai.expect,
|
||||||
|
_ = require('underscore'),
|
||||||
OutboxBO = require('js/bo/outbox'),
|
OutboxBO = require('js/bo/outbox'),
|
||||||
|
KeychainDAO = require('js/dao/keychain-dao'),
|
||||||
EmailDAO = require('js/dao/email-dao'),
|
EmailDAO = require('js/dao/email-dao'),
|
||||||
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
||||||
InvitationDAO = require('js/dao/invitation-dao');
|
InvitationDAO = require('js/dao/invitation-dao');
|
||||||
|
|
||||||
describe('Outbox Business Object unit test', function() {
|
describe('Outbox Business Object unit test', function() {
|
||||||
var outbox, emailDaoStub, devicestorageStub, invitationDaoStub;
|
var outbox, emailDaoStub, devicestorageStub, invitationDaoStub, keychainStub,
|
||||||
|
dummyUser = 'spiderpig@springfield.com';
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
emailDaoStub = sinon.createStubInstance(EmailDAO);
|
emailDaoStub = sinon.createStubInstance(EmailDAO);
|
||||||
|
emailDaoStub._account = {
|
||||||
|
emailAddress: dummyUser
|
||||||
|
};
|
||||||
emailDaoStub._devicestorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO);
|
emailDaoStub._devicestorage = devicestorageStub = sinon.createStubInstance(DeviceStorageDAO);
|
||||||
|
emailDaoStub._keychain = keychainStub = sinon.createStubInstance(KeychainDAO);
|
||||||
invitationDaoStub = sinon.createStubInstance(InvitationDAO);
|
invitationDaoStub = sinon.createStubInstance(InvitationDAO);
|
||||||
outbox = new OutboxBO(emailDaoStub, invitationDaoStub);
|
outbox = new OutboxBO(emailDaoStub, invitationDaoStub);
|
||||||
});
|
});
|
||||||
@ -42,25 +49,55 @@ define(function(require) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('empty outbox', function() {
|
describe('process outbox', function() {
|
||||||
it('should work', function(done) {
|
it('should work', function(done) {
|
||||||
devicestorageStub.listItems.yields(null, [{
|
var dummyMails = [{
|
||||||
id: '12345'
|
id: '123',
|
||||||
}]);
|
to: [{
|
||||||
emailDaoStub.encryptedSend.yields();
|
name: 'member',
|
||||||
devicestorageStub.removeList.yields();
|
address: 'member@whiteout.io'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
id: '456',
|
||||||
|
to: [{
|
||||||
|
name: 'invited',
|
||||||
|
address: 'invited@whiteout.io'
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
id: '789',
|
||||||
|
to: [{
|
||||||
|
name: 'notinvited',
|
||||||
|
address: 'notinvited@whiteout.io'
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
|
||||||
|
devicestorageStub.listItems.yieldsAsync(null, dummyMails);
|
||||||
|
emailDaoStub.encryptedSend.yieldsAsync();
|
||||||
|
emailDaoStub.send.yieldsAsync();
|
||||||
|
devicestorageStub.removeList.yieldsAsync();
|
||||||
|
invitationDaoStub.check.withArgs(sinon.match(function(o) { return o.recipient === 'invited@whiteout.io'; })).yieldsAsync(null, InvitationDAO.INVITE_PENDING);
|
||||||
|
invitationDaoStub.check.withArgs(sinon.match(function(o) { return o.recipient === 'notinvited@whiteout.io'; })).yieldsAsync(null, InvitationDAO.INVITE_MISSING);
|
||||||
|
invitationDaoStub.invite.withArgs(sinon.match(function(o) { return o.recipient === 'notinvited@whiteout.io'; })).yieldsAsync(null, InvitationDAO.INVITE_SUCCESS);
|
||||||
|
keychainStub.getReceiverPublicKey.withArgs(sinon.match(function(o) { return o === 'member@whiteout.io'; })).yieldsAsync(null, 'this is not the key you are looking for...');
|
||||||
|
keychainStub.getReceiverPublicKey.withArgs(sinon.match(function(o) { return o === 'invited@whiteout.io' || o === 'notinvited@whiteout.io'; })).yieldsAsync();
|
||||||
|
|
||||||
|
var check = _.after(dummyMails.length + 1, function() {
|
||||||
|
expect(devicestorageStub.listItems.callCount).to.equal(1);
|
||||||
|
expect(emailDaoStub.encryptedSend.callCount).to.equal(1);
|
||||||
|
expect(emailDaoStub.send.callCount).to.equal(1);
|
||||||
|
expect(devicestorageStub.removeList.callCount).to.equal(1);
|
||||||
|
expect(invitationDaoStub.check.callCount).to.equal(2);
|
||||||
|
expect(invitationDaoStub.invite.callCount).to.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
function onOutboxUpdate(err, count) {
|
function onOutboxUpdate(err, count) {
|
||||||
expect(err).to.not.exist;
|
expect(err).to.not.exist;
|
||||||
if (count === 0) {
|
expect(count).to.exist;
|
||||||
expect(devicestorageStub.listItems.callCount).to.equal(1);
|
check();
|
||||||
expect(emailDaoStub.encryptedSend.callCount).to.equal(1);
|
|
||||||
expect(devicestorageStub.removeList.callCount).to.equal(1);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outbox._emptyOutbox(onOutboxUpdate);
|
outbox._processOutbox(onOutboxUpdate);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user