From 5f9132ab5fc622746ab8e60dc12f508bd69f1a40 Mon Sep 17 00:00:00 2001 From: Felix Hammerl Date: Wed, 22 Oct 2014 12:25:27 +0200 Subject: [PATCH] [WO-651] Do not error if imap upload fails after send --- src/js/dao/email-dao.js | 95 ++++++++++++++++++++++++++----------- test/unit/email-dao-test.js | 85 +++++++++++++++++++++++++++++---- 2 files changed, 142 insertions(+), 38 deletions(-) diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index a64d3b1..46b5e37 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -259,7 +259,6 @@ EmailDAO.prototype.openFolder = function(options, callback) { path: options.folder.path }, callback); }; - /** * Synchronizes a folder's contents from disk to memory, i.e. if * a message has disappeared from the disk, this method will remove it from folder.messages, and @@ -1022,22 +1021,13 @@ EmailDAO.prototype.sendEncrypted = function(options, callback) { return callback(err); } - // upload the sent message to the sent folder if necessary - var sentFolder = _.findWhere(self._account.folders, { - type: FOLDER_TYPE_SENT - }); - - if (self.ignoreUploadOnSent || !sentFolder || !rfcText) { - self.done(); - return callback(); - } - - self._imapClient.uploadMessage({ - path: sentFolder.path, + // try to upload to sent, but we don't actually care if the upload failed or not + // this should not negatively impact the process of sending + self._uploadToSent({ message: rfcText - }, function(err) { + }, function() { self.done(); - callback(err); + callback(); }); }); }; @@ -1072,22 +1062,13 @@ EmailDAO.prototype.sendPlaintext = function(options, callback) { return callback(err); } - // upload the sent message to the sent folder if necessary - var sentFolder = _.findWhere(self._account.folders, { - type: FOLDER_TYPE_SENT - }); - - if (self.ignoreUploadOnSent || !sentFolder || !rfcText) { - self.done(); - return callback(); - } - - self._imapClient.uploadMessage({ - path: sentFolder.path, + // try to upload to sent, but we don't actually care if the upload failed or not + // this should not negatively impact the process of sending + self._uploadToSent({ message: rfcText - }, function(err) { + }, function() { self.done(); - callback(err); + callback(); }); }); }; @@ -1567,6 +1548,20 @@ EmailDAO.prototype._imapListMessages = function(options, callback) { self._imapClient.listMessages(options, callback); }; +/** + * Uploads a built message to a folder + * + * @param {Object} options.folder The folder where to find the message + * @param {String} options.message The rfc2822 compatible raw ASCII e-mail source + * @param {Function} callback (error) The callback when the imap client is done uploading + */ +EmailDAO.prototype._imapUploadMessage = function(options, callback) { + this._imapClient.uploadMessage({ + path: options.folder.path, + message: options.message + }, callback); +}; + /** * Stream an email messsage's body * @param {String} options.folder The folder @@ -1653,6 +1648,48 @@ EmailDAO.prototype._localDeleteMessage = function(options, callback) { }; +// +// +// Internal Helper Methods +// +// + +/** + * Uploads a message to the sent folder, if necessary. + * Calls back immediately if ignoreUploadOnSent == true or not sent folder was found. + * + * @param {String} options.message The rfc2822 compatible raw ASCII e-mail source + * @param {Function} callback (error) The callback when the imap client is done uploading + */ +EmailDAO.prototype._uploadToSent = function(options, callback) { + var self = this; + + self.busy(); + + // upload the sent message to the sent folder if necessary + var sentFolder = _.findWhere(self._account.folders, { + type: FOLDER_TYPE_SENT + }); + + // return for wrong usage + if (self.ignoreUploadOnSent || !sentFolder || !options.message) { + self.done(); + return callback(); + } + + // upload + self._imapUploadMessage({ + folder: sentFolder, + message: options.message + }, function(err) { + self.done(); + callback(err); + }); +}; + + + + // // // Helper Functions diff --git a/test/unit/email-dao-test.js b/test/unit/email-dao-test.js index 0ba3553..88690ce 100644 --- a/test/unit/email-dao-test.js +++ b/test/unit/email-dao-test.js @@ -1565,11 +1565,10 @@ describe('Email DAO unit tests', function() { var publicKeys = ["PUBLIC KEY"], dummyMail = { publicKeysArmored: publicKeys - }; + }, + msg = 'wow. such message. much rfc2822.'; it('should send encrypted and upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - imapClientStub.uploadMessage.withArgs({ path: sentFolder.path, message: msg @@ -1595,8 +1594,6 @@ describe('Email DAO unit tests', function() { }); it('should send encrypted and not upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - dao.ignoreUploadOnSent = true; pgpMailerStub.send.withArgs({ @@ -1618,6 +1615,22 @@ describe('Email DAO unit tests', function() { }); }); + it('should send encrypted and ignore error on upload', function(done) { + imapClientStub.uploadMessage.yields(new Error()); + pgpMailerStub.send.yieldsAsync(null, msg); + + dao.sendEncrypted({ + email: dummyMail + }, function(err) { + expect(err).to.not.exist; + + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.calledOnce).to.be.true; + + done(); + }); + }); + it('should not send when pgpmailer fails', function(done) { pgpMailerStub.send.yieldsAsync({}); @@ -1648,10 +1661,9 @@ describe('Email DAO unit tests', function() { describe('#sendPlaintext', function() { var dummyMail = {}; + var msg = 'wow. such message. much rfc2822.'; it('should send in the plain and upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - pgpMailerStub.send.withArgs({ smtpclient: undefined, mail: dummyMail @@ -1673,8 +1685,6 @@ describe('Email DAO unit tests', function() { }); it('should send in the plain and not upload to sent', function(done) { - var msg = 'wow. such message. much rfc2822.'; - dao.ignoreUploadOnSent = true; pgpMailerStub.send.withArgs({ @@ -1692,6 +1702,22 @@ describe('Email DAO unit tests', function() { }); }); + it('should send and ignore error on upload', function(done) { + imapClientStub.uploadMessage.yields(new Error()); + pgpMailerStub.send.yieldsAsync(null, msg); + + dao.sendEncrypted({ + email: dummyMail + }, function(err) { + expect(err).to.not.exist; + + expect(pgpMailerStub.send.calledOnce).to.be.true; + expect(imapClientStub.uploadMessage.calledOnce).to.be.true; + + done(); + }); + }); + it('should not send due to error', function(done) { pgpMailerStub.send.yieldsAsync({}); @@ -2189,6 +2215,27 @@ describe('Email DAO unit tests', function() { }); }); + describe('#_imapUploadMessage', function() { + it('should upload a message', function(done) { + var msg = 'wow. such message. much rfc2822.'; + + imapClientStub.uploadMessage.withArgs({ + path: draftsFolder.path, + message: msg + }).yields(); + + dao._imapUploadMessage({ + folder: draftsFolder, + message: msg + }, function(err) { + expect(err).to.not.exist; + expect(imapClientStub.uploadMessage.calledOnce).to.be.true; + + done(); + }); + }); + }); + describe('#_getBodyParts', function() { it('should get bodyParts', function(done) { imapClientStub.getBodyParts.withArgs({ @@ -2297,5 +2344,25 @@ describe('Email DAO unit tests', function() { }); }); + + describe('#_uploadToSent', function() { + it('should upload', function(done) { + var msg = 'wow. such message. much rfc2822.'; + + imapClientStub.uploadMessage.withArgs({ + path: sentFolder.path, + message: msg + }).yields(); + + dao._uploadToSent({ + message: msg + }, function(err) { + expect(err).to.not.exist; + + expect(imapClientStub.uploadMessage.calledOnce).to.be.true; + done(); + }); + }); + }); }); }); \ No newline at end of file