diff --git a/Gruntfile.js b/Gruntfile.js index b91ab7b..010714c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -139,10 +139,9 @@ module.exports = function(grunt) { 'imap-client/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/src/*.js', 'imap-client/node_modules/mailparser/src/*.js', 'imap-client/node_modules/mime/src/mime.js', - 'smtp-client/src/*.js', - 'smtp-client/node_modules/mailcomposer/src/*', - 'smtp-client/node_modules/nodemailer/src/*', - 'smtp-client/node_modules/nodemailer/node_modules/simplesmtp/src/*' + 'pgpmailer/src/*.js', + 'pgpmailer/node_modules/simplesmtp/src/*', + 'pgpmailer/node_modules/mailbuilder/src/*.js' ], dest: 'src/lib/' }, diff --git a/package.json b/package.json index 85beac5..1c3c174 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "crypto-lib": "https://github.com/whiteout-io/crypto-lib/tarball/master", "imap-client": "https://github.com/whiteout-io/imap-client/tarball/dev/attachments", - "smtp-client": "https://github.com/whiteout-io/smtp-client/tarball/master", + "pgpmailer": "https://github.com/whiteout-io/pgpmailer/tarball/master", "requirejs": "2.1.10" }, "devDependencies": { diff --git a/src/js/app-config.js b/src/js/app-config.js index be38b38..7d992df 100644 --- a/src/js/app-config.js +++ b/src/js/app-config.js @@ -54,7 +54,7 @@ define(function(require) { fallbackSubject: '(no subject)', invitationSubject: 'Invitation to a private conversation', invitationMessage: 'I would like to invite you to a private conversation!\n\nIn order to read my encrypted message please install the Whiteout Mail application. This application is used to read and write messages securely with strong encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io', - message: 'this is a private conversation. To read my encrypted message below, simply open it in Whiteout Mail.\n\nOpen Whiteout Mail: https://chrome.google.com/webstore/detail/jjgghafhamholjigjoghcfcekhkonijg', + message: 'Hi,\n\nthis is a private conversation. To read my encrypted message below, simply open it in Whiteout Mail.\n\nOpen Whiteout Mail: https://chrome.google.com/webstore/detail/jjgghafhamholjigjoghcfcekhkonijg', cryptPrefix: '-----BEGIN PGP MESSAGE-----', cryptSuffix: '-----END PGP MESSAGE-----', signature: 'Sent securely from Whiteout Mail', diff --git a/src/js/app-controller.js b/src/js/app-controller.js index 40f469c..c4940b0 100644 --- a/src/js/app-controller.js +++ b/src/js/app-controller.js @@ -6,7 +6,7 @@ define(function(require) { var $ = require('jquery'), ImapClient = require('imap-client'), - SmtpClient = require('smtp-client'), + PgpMailer = require('pgpmailer'), EmailDAO = require('js/dao/email-dao'), RestDAO = require('js/dao/rest-dao'), PublicKeyDAO = require('js/dao/publickey-dao'), @@ -89,7 +89,7 @@ define(function(require) { }); function initClients(oauth, certificate) { - var auth, imapOptions, imapClient, smtpOptions, smtpClient; + var auth, imapOptions, imapClient, smtpOptions, pgpMailer; auth = { XOAuth2: { @@ -106,15 +106,18 @@ define(function(require) { ca: [certificate] }; smtpOptions = { - secure: config.gmail.smtp.secure, + secureConnection: config.gmail.smtp.secure, port: config.gmail.smtp.port, host: config.gmail.smtp.host, auth: auth, - ca: [certificate] + tls: { + ca: [certificate] + }, + onError: console.error }; imapClient = new ImapClient(imapOptions); - smtpClient = new SmtpClient(smtpOptions); + pgpMailer = new PgpMailer(smtpOptions); imapClient.onError = function(err) { console.log('IMAP error.', err); @@ -126,7 +129,7 @@ define(function(require) { // connect to clients self._emailDao.onConnect({ imapClient: imapClient, - smtpClient: smtpClient + pgpMailer: pgpMailer }, callback); } }; diff --git a/src/js/controller/write.js b/src/js/controller/write.js index a870023..b570f21 100644 --- a/src/js/controller/write.js +++ b/src/js/controller/write.js @@ -79,7 +79,7 @@ define(function(require) { // only display non html mails in reply part if (!re.html) { - body += re.body.split('\n').join('\n> '); + body += re.body.trim().split('\n').join('\n> '); $scope.body = body; } } diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index 04c1def..f673f81 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -73,7 +73,11 @@ define(function(require) { var self = this; self._imapClient = options.imapClient; - self._smtpClient = options.smtpClient; + self._pgpMailer = options.pgpMailer; + // set private key + if (self._crypto && self._crypto._privateKey) { + self._pgpMailer._privateKey = self._crypto._privateKey; + } // delegation-esque pattern to mitigate between node-style events and plain js self._imapClient.onIncomingMessage = function(message) { @@ -116,7 +120,7 @@ define(function(require) { // set status to online this._account.online = false; this._imapClient = undefined; - this._smtpClient = undefined; + self._pgpMailer = undefined; callback(); }; @@ -131,6 +135,8 @@ define(function(require) { privateKeyArmored: options.keypair.privateKey.encryptedKey, publicKeyArmored: options.keypair.publicKey.publicKey }, callback); + // set decrypted privateKey to pgpMailer + self._pgpMailer._privateKey = self._crypto._privateKey; return; } @@ -913,17 +919,26 @@ define(function(require) { return; } - // public key found... encrypt and send - self._encrypt({ - email: email, - keys: email.receiverKeys // this Array is set in writer controller - }, function(err, email) { + // get own public key so send message can be read + self._crypto.exportKeys(function(err, ownKeys) { if (err) { callback(err); return; } - self._smtpClient.send(email, callback); + // add own public key to receiver list + email.receiverKeys.push(ownKeys.publicKeyArmored); + + // add whiteout tag to subject + email.subject = str.subjectPrefix + email.subject; + + // mime encode, sign, encrypt and send email via smtp + self._pgpMailer.send({ + encrypt: true, + cleartextMessage: str.message + '\n\n' + str.signature + '\n\n', + mail: email, + publicKeysArmored: email.receiverKeys + }, callback); }); }; @@ -936,7 +951,13 @@ define(function(require) { return; } - this._smtpClient.send(options.email, callback); + // add whiteout tag to subject + options.email.subject = str.subjectPrefix + options.email.subject; + + // mime encode, sign and send email via smtp + this._pgpMailer.send({ + mail: options.email + }, callback); }; // @@ -967,23 +988,12 @@ define(function(require) { return; } - // bundle encrypted email together for sending - frameEncryptedMessage(options.email, ct); + // replace plaintext body with pgp message + options.email.body = ct; + callback(null, options.email); }); }); - - function frameEncryptedMessage(email, ct) { - var greeting, - message = str.message + '\n\n\n', - signature = '\n\n' + str.signature + '\n\n'; - - greeting = 'Hi,\n\n'; - - // build encrypted text body - email.body = greeting + message + ct + signature; - email.subject = str.subjectPrefix + email.subject; - } }; // Local Storage API @@ -1237,8 +1247,6 @@ define(function(require) { }); mails.forEach(function(mail) { - mail.body = str.cryptPrefix + mail.body.split(str.cryptPrefix)[1].split(str.cryptSuffix)[0] + str.cryptSuffix; - mail.subject = mail.subject.split(str.subjectPrefix)[1]; self._crypto.decrypt(mail.body, ownKeys.publicKeyArmored, function(err, decrypted) { mail.body = err ? err.errMsg : decrypted; after();