diff --git a/src/js/app-config.js b/src/js/app-config.js index baebd09..09dea00 100644 --- a/src/js/app-config.js +++ b/src/js/app-config.js @@ -38,7 +38,7 @@ define([], function() { */ app.string = { subjectPrefix: '[whiteout] ', - invitationSubject: 'Invitation to your secure eMail experience', + invitationSubject: 'Invitation to a private conversation', 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', cryptPrefix: '-----BEGIN PGP MESSAGE-----', diff --git a/src/js/bo/outbox.js b/src/js/bo/outbox.js index f23e4fe..d46dc50 100644 --- a/src/js/bo/outbox.js +++ b/src/js/bo/outbox.js @@ -8,8 +8,8 @@ define(function(require) { dbType = 'email_OUTBOX'; /** - * High level business object that orchestrates the local outbox. - * The local outbox takes care of the emails before they are being sent. + * High level business object that orchestrates the local outbox. + * The local outbox takes care of the emails before they are being sent. * It also checks periodically if there are any mails in the local device storage to be sent. */ var OutboxBO = function(emailDao, invitationDao) { @@ -47,6 +47,9 @@ define(function(require) { var self = this, emails; + // if a _processOutbox call is still in progress when a new timeout kicks + // in, since sending mails might take time, ignore it. otherwise, mails + // could get sent multiple times if (self._outboxBusy) { return; } @@ -72,25 +75,28 @@ define(function(require) { }); } + // process the next pending mail function processMails() { - // in the navigation controller, this updates the folder count - if (emails.length === 0) { + // in the navigation controller, this updates the folder count self._outboxBusy = false; callback(null, 0); return; } + // in the navigation controller, this updates the folder count callback(null, emails.length); var email = emails.shift(); checkReceivers(email); } + // check whether there are unregistered receivers, i.e. receivers without a public key function checkReceivers(email) { var unregisteredUsers, receiverChecked; unregisteredUsers = []; receiverChecked = _.after(email.to.length, function() { + // invite unregistered users if necessary if (unregisteredUsers.length > 0) { invite(unregisteredUsers); return; @@ -99,10 +105,13 @@ define(function(require) { sendEncrypted(email); }); + // find out if there are unregistered users email.to.forEach(function(recipient) { self._emailDao._keychain.getReceiverPublicKey(recipient.address, function(err, key) { if (err) { - // stop processing + self._outboxBusy = false; + callback(err); + return; } if (!key) { @@ -114,39 +123,50 @@ define(function(require) { }); } + // invite the unregistered receivers, if necessary 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 + // check which of the adresses has pending invitations addresses.forEach(function(recipient) { var recipientAddress = recipient.address; + self._invitationDao.check({ recipient: recipientAddress, sender: sender }, function(err, status) { + if (err) { + self._outboxBusy = false; + callback(err); + return; + } + 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); + self._outboxBusy = false; + callback(err); return; } if (status !== InvitationDAO.INVITE_SUCCESS) { - console.error('could not successfully invite ' + recipientAddress); + self._outboxBusy = false; + callback({ + errMsg: 'could not successfully invite ' + recipientAddress + }); return; } @@ -156,26 +176,28 @@ define(function(require) { }); }); + // send an invitation to the unregistered user, aka the recipient function sendInvitationMail(recipient, sender) { var to = (recipient.name || recipient.address).split('@')[0].split('.')[0].split(' ')[0], invitationMail = { from: [sender], to: [recipient], - subject: str.invitationSubject, + subject: str.subjectPrefix + 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); + self._outboxBusy = false; + callback(err); + return; } invitationFinished(); }); } } - function sendEncrypted(email) { self._emailDao.encryptedSend(email, function(err) { if (err) {