diff --git a/src/js/controller/read.js b/src/js/controller/read.js index 5f6f88e..9673790 100644 --- a/src/js/controller/read.js +++ b/src/js/controller/read.js @@ -117,7 +117,7 @@ define(function(require) { var email = $scope.state.mailList.selected; emailDao.getAttachment({ - path: folder.path, + folder: folder.path, uid: email.uid, attachment: attachment }, function(err) { diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index 2ee8152..0e6e5a3 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -306,9 +306,19 @@ define(function(require) { var localMessage = localMessages[0]; + // treat attachment and non-attachment body parts separately: + // we need to fetch the content for non-attachment body parts (encrypted, signed, text, html) + // but we spare the effort and fetch attachment content later upon explicit user request. + var contentParts = localMessage.bodyParts.filter(function(bodyPart) { + return bodyPart.type !== "attachment"; + }); + var attachmentParts = localMessage.bodyParts.filter(function(bodyPart) { + return bodyPart.type === "attachment"; + }); + // do we need to fetch content from the imap server? var needsFetch = false; - localMessage.bodyParts.forEach(function(part) { + contentParts.forEach(function(part) { needsFetch = (typeof part.content === 'undefined'); }); @@ -324,15 +334,16 @@ define(function(require) { self._emailSync._getBodyParts({ folder: folder, uid: localMessage.uid, - bodyParts: localMessage.bodyParts + bodyParts: contentParts }, function(err, parsedBodyParts) { if (err) { done(err); return; } - message.bodyParts = parsedBodyParts; - localMessage.bodyParts = parsedBodyParts; + // piece together the parsed bodyparts and the empty attachments which have not been parsed + message.bodyParts = parsedBodyParts.concat(attachmentParts); + localMessage.bodyParts = parsedBodyParts.concat(attachmentParts); // persist it to disk self._emailSync._localStoreMessages({ @@ -384,6 +395,22 @@ define(function(require) { } }; + EmailDAO.prototype.getAttachment = function(options, callback) { + this._emailSync._getBodyParts({ + folder: options.folder, + uid: options.uid, + bodyParts: [options.attachment] + }, function(err, parsedBodyParts) { + if (err) { + callback(err); + return; + } + + options.attachment.content = parsedBodyParts[0].content; + callback(err, err ? undefined : options.attachment); + }); + }; + EmailDAO.prototype.decryptBody = function(options, callback) { var self = this, message = options.message; diff --git a/src/js/dao/email-sync.js b/src/js/dao/email-sync.js index f5eb2ca..13b35c7 100644 --- a/src/js/dao/email-sync.js +++ b/src/js/dao/email-sync.js @@ -447,6 +447,13 @@ define(function(require) { return; } + // this enables us to already show the attachment clip in the message list ui + messages.forEach(function(message) { + message.attachments = message.bodyParts.filter(function(bodyPart) { + return bodyPart.type === 'attachment'; + }); + }); + // if persisting worked, add them to the messages array folder.messages = folder.messages.concat(messages); self.onIncomingMessage(messages); diff --git a/test/new-unit/email-dao-test.js b/test/new-unit/email-dao-test.js index 6439815..b4dd420 100644 --- a/test/new-unit/email-dao-test.js +++ b/test/new-unit/email-dao-test.js @@ -866,6 +866,63 @@ define(function(require) { }); }); + describe('getAttachment', function() { + var folder = 'asdasdasdasdasd', + uid = 1234, + imapGetStub; + + beforeEach(function() { + imapGetStub = sinon.stub(emailSync, '_getBodyParts'); + }); + + afterEach(function() { + emailSync._getBodyParts.restore(); + }); + + it('should fetch an attachment from imap', function(done) { + var attmt = {}; + + imapGetStub.withArgs({ + folder: folder, + uid: uid, + bodyParts: [attmt] + }).yieldsAsync(null, [{ + content: 'CONTENT!!!' + }]); + + dao.getAttachment({ + folder: folder, + uid: uid, + attachment: attmt + }, function(err, fetchedAttmt) { + expect(err).to.not.exist; + expect(fetchedAttmt).to.equal(attmt); + expect(attmt.content).to.not.be.empty; + expect(imapGetStub.calledOnce).to.be.true; + + done(); + }); + }); + + it('should error during fetch', function(done) { + var attmt = {}; + + imapGetStub.yieldsAsync({}); + + dao.getAttachment({ + folder: folder, + uid: uid, + attachment: attmt + }, function(err, fetchedAttmt) { + expect(err).to.exist; + expect(fetchedAttmt).to.not.exist; + expect(imapGetStub.calledOnce).to.be.true; + + done(); + }); + }); + }); + describe('decryptBody', function() { it('should do nothing when the message is not encrypted', function() { var message = {