Merge pull request #32 from whiteout-io/dev/improve-verification

make verification mail handling more resilitent
This commit is contained in:
Tankred Hase 2014-03-07 13:05:05 +01:00
commit 6b67995d40
2 changed files with 50 additions and 32 deletions

View File

@ -573,6 +573,7 @@ define(function(require) {
return; return;
} }
// list the messages starting from the lowest new uid to the highest new uid
self._imapListMessages({ self._imapListMessages({
folder: folder.path, folder: folder.path,
firstUid: Math.min.apply(null, delta4), firstUid: Math.min.apply(null, delta4),
@ -584,27 +585,40 @@ define(function(require) {
return; return;
} }
// if there is a verification message in the synced messages, handle it // if there are verification messages in the synced messages, handle it
var verificationMessage = _.findWhere(messages, { var verificationMessages = _.filter(messages, function(message) {
subject: str.subjectPrefix + str.verificationSubject return message.subject === (str.subjectPrefix + str.verificationSubject);
}); });
if (verificationMessage) { // if there are verification messages, continue after we've tried to verify
handleVerification(verificationMessage, function(err) { if (verificationMessages.length > 0) {
// eliminate the verification mail if the verification worked, otherwise display an error and it in the mail list var after = _.after(verificationMessages.length, storeHeaders);
if (err) {
callback(err);
} else {
messages = _.filter(messages, function(message) {
return message.subject !== (str.subjectPrefix + str.verificationSubject);
});
}
storeHeaders(); verificationMessages.forEach(function(verificationMessage) {
handleVerification(verificationMessage, function(err, isValid) {
// if it was NOT a valid verification mail, do nothing
if (!isValid) {
after();
return;
}
// if an error occurred and the mail was a valid verification mail, display the error, but
// keep the mail in the list so the user can see it and verify manually
if (err) {
callback(err);
after();
return;
}
// if verification worked, we remove the mail from the list.
messages.splice(messages.indexOf(verificationMessage), 1);
after();
});
}); });
return; return;
} }
// no verification messages, just proceed as usual
storeHeaders(); storeHeaders();
function storeHeaders() { function storeHeaders() {
@ -801,34 +815,29 @@ define(function(require) {
folder: options.folder, folder: options.folder,
message: message message: message
}, function(error) { }, function(error) {
var verificationUrlPrefix = config.cloudUrl + config.verificationUrl, // we could not stream the text to determine if the verification was valid or not
uuid, isValidUuid, index; // so handle it as if it were valid
if (error) { if (error) {
localCallback(error); localCallback(error, true);
return; return;
} }
index = message.body.indexOf(verificationUrlPrefix); var verificationUrlPrefix = config.cloudUrl + config.verificationUrl,
if (index === -1) { uuid = message.body.split(verificationUrlPrefix).pop().substr(0, config.verificationUuidLength),
// there's no url in the message, so forget about that. isValidUuid = new RegExp('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}').test(uuid);
localCallback();
return;
}
uuid = message.body.substr(index + verificationUrlPrefix.length, config.verificationUuidLength); // there's no valid uuid in the message, so forget about it
isValidUuid = new RegExp('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}').test(uuid);
if (!isValidUuid) { if (!isValidUuid) {
// there's no valid uuid in the message, so forget about that, too. localCallback(null, false);
localCallback();
return; return;
} }
// there's a valid uuid in the message, so try to verify it
self._keychain.verifyPublicKey(uuid, function(err) { self._keychain.verifyPublicKey(uuid, function(err) {
if (err) { if (err) {
localCallback({ localCallback({
errMsg: 'Verifying your public key failed: ' + err.errMsg errMsg: 'Verifying your public key failed: ' + err.errMsg
}); }, true);
return; return;
} }
@ -839,7 +848,7 @@ define(function(require) {
}, function() { }, function() {
// if we could successfully not delete the message or not doesn't matter. // if we could successfully not delete the message or not doesn't matter.
// just don't show it in whiteout and keep quiet about it // just don't show it in whiteout and keep quiet about it
localCallback(); localCallback(null, true);
}); });
}); });
}); });

View File

@ -2041,7 +2041,7 @@ define(function(require) {
}); });
it('should not bother about corrupted authentication mails', function(done) { it('should not bother about corrupted authentication mails', function(done) {
var invocations, folder, localListStub, imapSearchStub, imapGetStub, imapListMessagesStub, imapDeleteStub; var invocations, folder, localListStub, imapSearchStub, imapGetStub, imapListMessagesStub, imapDeleteStub, localStoreStub;
invocations = 0; invocations = 0;
folder = 'FOLDAAAA'; folder = 'FOLDAAAA';
@ -2065,6 +2065,13 @@ define(function(require) {
folder: folder, folder: folder,
answered: true answered: true
}).yields(null, []); }).yields(null, []);
localStoreStub = sinon.stub(dao, '_localStoreMessages').withArgs({
folder: folder,
emails: [corruptedVerificationMail]
}).yields();
imapListMessagesStub = sinon.stub(dao, '_imapListMessages').yields(null, [corruptedVerificationMail]); imapListMessagesStub = sinon.stub(dao, '_imapListMessages').yields(null, [corruptedVerificationMail]);
imapGetStub = sinon.stub(dao, '_imapStreamText').yields(null); imapGetStub = sinon.stub(dao, '_imapStreamText').yields(null);
keychainStub.verifyPublicKey.withArgs(corruptedVerificationUuid).yields({ keychainStub.verifyPublicKey.withArgs(corruptedVerificationUuid).yields({
@ -2084,13 +2091,15 @@ define(function(require) {
} }
expect(dao._account.busy).to.be.false; expect(dao._account.busy).to.be.false;
expect(dao._account.folders[0].messages).to.be.empty; expect(dao._account.folders[0].messages).to.not.be.empty;
expect(localListStub.calledOnce).to.be.true; expect(localListStub.calledOnce).to.be.true;
expect(imapSearchStub.calledThrice).to.be.true; expect(imapSearchStub.calledThrice).to.be.true;
expect(imapGetStub.calledOnce).to.be.true; expect(imapGetStub.calledOnce).to.be.true;
expect(localStoreStub.calledOnce).to.be.true;
expect(keychainStub.verifyPublicKey.called).to.be.false; expect(keychainStub.verifyPublicKey.called).to.be.false;
expect(imapDeleteStub.called).to.be.false; expect(imapDeleteStub.called).to.be.false;
done(); done();
}); });
}); });