diff --git a/.gitignore b/.gitignore
index d9c457d..0cfc0d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@ src/css/
dist/
release/
test/integration/src/
-src/lib/*.js
-src/js/crypto/aes-gcm.js
-src/js/crypto/util.js
.elasticbeanstalk/
+test/*/index.js
+**/*.browserified.js
+**/*.js.map
diff --git a/.jshintrc b/.jshintrc
index c6b8a83..6c4c255 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -18,31 +18,29 @@
"unused": true,
"predef": [
+ "self",
+ "importScripts",
"console",
- "Notification",
- "importScripts",
- "process",
- "Event",
- "QUnit",
- "test",
- "asyncTest",
- "ok",
- "equal",
- "deepEqual",
- "start",
+ "process",
"chrome",
- "requirejs",
- "define",
- "self",
+ "Notification",
+ "Event",
+ "sinon",
+ "mocha",
+ "chai",
+ "expect",
"describe",
"it",
- "chai",
- "sinon",
- "mocha",
"before",
"beforeEach",
"after",
- "afterEach"
+ "afterEach",
+ "FastClick",
+ "angular",
+ "forge",
+ "Lawnchair",
+ "_",
+ "openpgp"
],
"globals": {
diff --git a/Gruntfile.js b/Gruntfile.js
index fa57114..9e66d74 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,11 +1,22 @@
module.exports = function(grunt) {
'use strict';
+ require('time-grunt')(grunt);
+
var version = grunt.option('release'),
zipName = (version) ? version : 'DEV';
+ var browserifyOpt = {
+ exclude: ['openpgp', 'node-forge', 'net', 'tls', 'crypto'], // node apis not required at build time
+ ignore: ['buffer'], // node apis to be stubbed for runtime
+ browserifyOptions: {
+ debug: true
+ }
+ };
+
// Project configuration.
grunt.initConfig({
+
connect: {
dev: {
options: {
@@ -23,32 +34,27 @@ module.exports = function(grunt) {
},
jshint: {
- all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*.js', 'test/integration/*.js'],
+ all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*-test.js', 'test/integration/*-test.js'],
options: {
jshintrc: '.jshintrc'
}
},
- mocha: {
+ mocha_phantomjs: {
all: {
options: {
urls: [
'http://localhost:<%= connect.test.options.port %>/test/unit/index.html',
'http://localhost:<%= connect.test.options.port %>/test/integration/index.html'
- ],
- run: false,
- reporter: 'Spec',
- log: false,
-
- // phanotmjs is soooo slow
- timeout: 100000
+ ]
}
}
},
clean: {
- dist: ['dist', 'src/lib/*.js', 'test/lib', 'test/integration/src']
+ dist: ['dist', 'test/lib', 'test/integration/src']
},
+
sass: {
dist: {
files: {
@@ -57,6 +63,7 @@ module.exports = function(grunt) {
}
}
},
+
autoprefixer: {
options: {
browsers: ['last 2 versions']
@@ -68,9 +75,10 @@ module.exports = function(grunt) {
}
}
},
+
csso: {
options: {
- banner: '/*! Copyright © 2013, Whiteout Networks GmbH. All rights reserved.*/\n'
+ banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n'
},
dist: {
files: {
@@ -79,6 +87,7 @@ module.exports = function(grunt) {
}
}
},
+
watch: {
css: {
files: ['src/sass/**/*.scss'],
@@ -86,7 +95,7 @@ module.exports = function(grunt) {
},
js: {
files: ['src/js/**/*.js'],
- tasks: ['copy:js', 'copy:integration', 'manifest']
+ tasks: ['dist-js', 'copy:integration', 'manifest']
},
lib: {
files: ['src/lib/**/*.js'],
@@ -97,59 +106,234 @@ module.exports = function(grunt) {
tasks: ['copy:app', 'copy:ca', 'copy:tpl', 'copy:img', 'copy:font', 'manifest-dev', 'manifest']
}
},
+
+ browserify: {
+ app: {
+ files: {
+ 'dist/js/app.browserified.js': ['src/js/app.js']
+ },
+ options: browserifyOpt
+ },
+ pbkdf2Worker: {
+ files: {
+ 'dist/js/pbkdf2-worker.browserified.js': ['src/js/crypto/pbkdf2-worker.js']
+ },
+ options: browserifyOpt
+ },
+ mailreaderWorker: {
+ files: {
+ 'dist/js/mailreader-parser-worker.browserified.js': ['node_modules/mailreader/src/mailreader-parser-worker-browserify.js']
+ },
+ options: browserifyOpt
+ },
+ tlsWorker: {
+ files: {
+ 'dist/js/tcp-socket-tls-worker.browserified.js': ['node_modules/tcp-socket/src/tcp-socket-tls-worker.js']
+ },
+ options: browserifyOpt
+ },
+ unitTest: {
+ files: {
+ 'test/unit/index.browserified.js': [
+ 'test/unit/oauth-test.js',
+ 'test/unit/auth-test.js',
+ 'test/unit/email-dao-test.js',
+ 'test/unit/app-controller-test.js',
+ 'test/unit/pgp-test.js',
+ 'test/unit/crypto-test.js',
+ 'test/unit/backbutton-handler-test.js',
+ 'test/unit/rest-dao-test.js',
+ 'test/unit/admin-dao-test.js',
+ 'test/unit/publickey-dao-test.js',
+ 'test/unit/privatekey-dao-test.js',
+ 'test/unit/lawnchair-dao-test.js',
+ 'test/unit/keychain-dao-test.js',
+ 'test/unit/devicestorage-dao-test.js',
+ 'test/unit/dialog-ctrl-test.js',
+ 'test/unit/add-account-ctrl-test.js',
+ 'test/unit/account-ctrl-test.js',
+ 'test/unit/set-passphrase-ctrl-test.js',
+ 'test/unit/contacts-ctrl-test.js',
+ 'test/unit/login-existing-ctrl-test.js',
+ 'test/unit/login-initial-ctrl-test.js',
+ 'test/unit/login-new-device-ctrl-test.js',
+ 'test/unit/login-privatekey-download-ctrl-test.js',
+ 'test/unit/login-set-credentials-ctrl-test.js',
+ 'test/unit/privatekey-upload-ctrl-test.js',
+ 'test/unit/login-ctrl-test.js',
+ 'test/unit/read-ctrl-test.js',
+ 'test/unit/navigation-ctrl-test.js',
+ 'test/unit/mail-list-ctrl-test.js',
+ 'test/unit/write-ctrl-test.js',
+ 'test/unit/outbox-bo-test.js',
+ 'test/unit/invitation-dao-test.js',
+ 'test/unit/update-handler-test.js',
+ 'test/unit/connection-doctor-test.js',
+ 'test/main.js'
+ ]
+ },
+ options: browserifyOpt
+ },
+ integrationTest: {
+ files: {
+ 'test/integration/index.browserified.js': [
+ 'test/integration/email-dao-test.js',
+ 'test/main.js'
+ ]
+ },
+ options: browserifyOpt
+ }
+ },
+
+ exorcise: {
+ app: {
+ files: {
+ 'dist/js/app.browserified.js.map': ['dist/js/app.browserified.js'],
+ }
+ },
+ unitTest: {
+ files: {
+ 'test/unit/index.browserified.js.map': ['test/unit/index.browserified.js'],
+ }
+ },
+ integrationTest: {
+ files: {
+ 'test/integration/index.browserified.js.map': ['test/integration/index.browserified.js'],
+ }
+ }
+ },
+
+ uglify: {
+ app: {
+ files: {
+ 'dist/js/app.min.js': [
+ 'src/lib/underscore/underscore-min.js',
+ 'node_modules/jquery/dist/jquery.min.js',
+ 'src/lib/angular/angular.min.js',
+ 'src/lib/angular/angular-route.min.js',
+ 'src/lib/angular/angular-animate.min.js',
+ 'src/lib/ngtagsinput/ng-tags-input.min.js',
+ 'node_modules/ng-infinite-scroll/build/ng-infinite-scroll.min.js',
+ 'src/lib/fastclick/fastclick.js',
+ 'src/lib/lawnchair/lawnchair-git.js',
+ 'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js',
+ 'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js',
+ 'dist/js/app.browserified.js'
+ ]
+ },
+ options: {
+ mangle: false,
+ sourceMap: true,
+ sourceMapIn: 'dist/js/app.browserified.js.map',
+ sourceMapIncludeSources: true,
+ sourceMapName: 'dist/js/app.min.js.map'
+ }
+ },
+ readSandbox: {
+ files: {
+ 'dist/js/read-sandbox.min.js': [
+ 'node_modules/dompurify/purify.js',
+ 'src/js/controller/read-sandbox.js'
+ ]
+ },
+ options: {
+ sourceMap: true,
+ sourceMapName: 'dist/js/read-sandbox.min.js.map'
+ }
+ },
+ pbkdf2Worker: {
+ files: {
+ 'dist/js/pbkdf2-worker.min.js': ['dist/js/pbkdf2-worker.browserified.js']
+ }
+ },
+ mailreaderWorker: {
+ files: {
+ 'dist/js/mailreader-parser-worker.min.js': ['dist/js/mailreader-parser-worker.browserified.js']
+ },
+ options: {
+ sourceMap: true,
+ sourceMapName: 'dist/js/mailreader-parser-worker.min.js.map'
+ }
+ },
+ tlsWorker: {
+ files: {
+ 'dist/js/tcp-socket-tls-worker.min.js': ['dist/js/tcp-socket-tls-worker.browserified.js']
+ },
+ options: {
+ sourceMap: true,
+ sourceMapName: 'dist/js/tcp-socket-tls-worker.min.js.map'
+ }
+ },
+ unitTest: {
+ files: {
+ 'test/unit/index.js': [
+ 'src/lib/underscore/underscore-min.js',
+ 'node_modules/jquery/dist/jquery.min.js',
+ 'src/lib/angular/angular.min.js',
+ 'src/lib/angular/angular-route.min.js',
+ 'src/lib/angular/angular-animate.min.js',
+ 'node_modules/angularjs/src/ngMock/angular-mocks.js',
+ 'src/lib/lawnchair/lawnchair-git.js',
+ 'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js',
+ 'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js',
+ 'test/unit/index.browserified.js'
+ ]
+ },
+ options: {
+ mangle: false,
+ sourceMap: true,
+ sourceMapIn: 'test/unit/index.browserified.js.map',
+ sourceMapIncludeSources: true,
+ sourceMapName: 'test/unit/index.js.map'
+ }
+ },
+ integrationTest: {
+ files: {
+ 'test/integration/index.js': [
+ 'src/lib/underscore/underscore-min.js',
+ 'src/lib/lawnchair/lawnchair-git.js',
+ 'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js',
+ 'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js',
+ 'test/integration/index.browserified.js'
+ ]
+ },
+ options: {
+ mangle: false,
+ sourceMap: true,
+ sourceMapIn: 'test/integration/index.browserified.js.map',
+ sourceMapIncludeSources: true,
+ sourceMapName: 'test/integration/index.js.map'
+ }
+ },
+ options: {
+ banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n'
+ }
+ },
+
copy: {
- npm: {
+ npmDev: {
expand: true,
flatten: true,
- cwd: 'node_modules/',
+ cwd: './',
src: [
- 'requirejs/require.js',
- 'imap-client/src/*.js',
- 'imap-client/node_modules/browserbox/src/*.js',
- 'imap-client/node_modules/browserbox/node_modules/wo-imap-handler/src/*.js',
- 'imap-client/node_modules/browserbox/node_modules/mimefuncs/src/*.js',
- 'imap-client/node_modules/browserbox/node_modules/tcp-socket/src/*.js',
- 'imap-client/node_modules/browserbox/node_modules/wo-utf7/src/*.js',
- 'mailreader/src/*.js',
- 'mailreader/node_modules/mimeparser/src/*.js',
- 'mailreader/node_modules/mimeparser/node_modules/wo-addressparser/src/*.js',
- 'pgpbuilder/src/*.js',
- 'pgpbuilder/node_modules/mailbuild/src/*.js',
- 'pgpbuilder/node_modules/mailbuild/node_modules/mimetypes/src/*.js',
- 'pgpbuilder/node_modules/mailbuild/node_modules/punycode/punycode.min.js',
- 'pgpmailer/src/*.js',
- 'pgpmailer/node_modules/wo-smtpclient/src/*.js',
- 'pgpmailer/node_modules/wo-smtpclient/node_modules/wo-stringencoding/dist/stringencoding.js',
- 'axe-logger/axe.js',
- 'dompurify/purify.js',
- 'jquery/dist/jquery.min.js',
- 'ng-infinite-scroll/build/ng-infinite-scroll.min.js'
+ 'node_modules/mocha/mocha.css',
+ 'node_modules/mocha/mocha.js',
+ 'node_modules/chai/chai.js',
+ 'node_modules/sinon/pkg/sinon.js',
+ 'node_modules/browsercrow/src/*.js',
+ 'node_modules/browsersmtp/src/*.js',
+ 'src/lib/openpgp/openpgp.js',
+ 'src/lib/openpgp/openpgp.worker.js',
+ 'src/lib/forge/forge.min.js',
+ 'dist/js/pbkdf2-worker.min.js'
],
- dest: 'src/lib/'
- },
- npmDev: {
- expand: true,
- flatten: true,
- cwd: 'node_modules/',
- src: ['requirejs/require.js', 'mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'sinon/pkg/sinon.js', 'angularjs/src/ngMock/angular-mocks.js', 'browsercrow/src/*.js', 'browsersmtp/src/*.js'],
dest: 'test/lib/'
},
- cryptoLib: {
- expand: true,
- cwd: 'node_modules/crypto-lib/src/',
- src: ['*.js'],
- dest: 'src/js/crypto/'
- },
lib: {
expand: true,
+ flatten: true,
cwd: 'src/lib/',
- src: ['**'],
- dest: 'dist/lib/'
- },
- js: {
- expand: true,
- cwd: 'src/js/',
- src: ['**'],
+ src: ['openpgp/openpgp.js', 'openpgp/openpgp.worker.js', 'forge/forge.min.js'],
dest: 'dist/js/'
},
font: {
@@ -170,23 +354,11 @@ module.exports = function(grunt) {
src: ['*'],
dest: 'dist/tpl/'
},
- ca: {
- expand: true,
- cwd: 'src/ca/',
- src: ['*'],
- dest: 'dist/ca/'
- },
app: {
expand: true,
cwd: 'src/',
src: ['*.html', '*.js', '*.json', 'manifest.*'],
dest: 'dist/'
- },
- integration: {
- expand: true,
- cwd: 'src/',
- src: ['**'],
- dest: 'test/integration/src/'
}
},
@@ -200,16 +372,6 @@ module.exports = function(grunt) {
cwd: 'dist/',
src: ['**/*'],
dest: 'release/'
- },
- nodeWebkit: {
- options: {
- mode: 'zip',
- archive: 'release/whiteout-mail_' + zipName + '.nw'
- },
- expand: true,
- cwd: 'dist/',
- src: ['**/*'],
- dest: '/'
}
},
@@ -220,31 +382,30 @@ module.exports = function(grunt) {
timestamp: true,
hash: true,
cache: ['socket.io/socket.io.js'],
- exclude: ['appcache.manifest', 'manifest.webapp'],
+ exclude: [
+ 'appcache.manifest',
+ 'manifest.webapp',
+ 'js/app.min.js.map',
+ 'js/app.browserified.js',
+ 'js/app.browserified.js.map',
+ 'js/crypto/pbkdf2-worker.browserified.js',
+ 'js/pbkdf2-worker.browserified.js',
+ 'js/read-sandbox.min.js.map'
+ ],
master: ['index.html']
},
src: ['**/*.*'],
dest: 'dist/appcache.manifest'
}
- },
+ }
- nodewebkit: {
- options: {
- version: '0.9.2', // node-webkit version
- build_dir: './release/node-webkit/', // Where the build version of my node-webkit app is saved
- mac: true, // We want to build it for mac
- win: false, // We want to build it for win
- linux32: false, // We don't need linux32
- linux64: false, // We don't need linux64
- },
- src: ['./dist/**/*'] // Your node-webkit app
- },
});
// Load the plugin(s)
+ grunt.loadNpmTasks('grunt-browserify');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-jshint');
- grunt.loadNpmTasks('grunt-mocha');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-csso');
grunt.loadNpmTasks('grunt-contrib-sass');
@@ -252,18 +413,19 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-compress');
- grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.loadNpmTasks('grunt-manifest');
+ grunt.loadNpmTasks('grunt-mocha-phantomjs');
+ grunt.loadNpmTasks('grunt-exorcise');
// Build tasks
- grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
+ grunt.registerTask('dist-js', ['browserify', 'exorcise', 'uglify']);
grunt.registerTask('dist-copy', ['copy']);
- grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy', 'manifest']);
+ grunt.registerTask('dist', ['clean', 'dist-css', 'dist-js', 'dist-copy', 'manifest']);
// Test/Dev tasks
grunt.registerTask('dev', ['connect:dev']);
- grunt.registerTask('test', ['jshint', 'connect:test', 'mocha']);
+ grunt.registerTask('test', ['jshint', 'connect:test', 'mocha_phantomjs']);
grunt.registerTask('prod', ['connect:prod']);
//
@@ -335,4 +497,4 @@ module.exports = function(grunt) {
grunt.registerTask('release-stable', ['dist', 'manifest-stable', 'compress']);
grunt.registerTask('default', ['release-dev']);
-};
\ No newline at end of file
+};
diff --git a/package.json b/package.json
index 1ded9b2..9d8ca7f 100644
--- a/package.json
+++ b/package.json
@@ -24,25 +24,27 @@
},
"scripts": {
"test": "grunt && grunt test",
- "start": "node server.js"
+ "start": "node server.js",
+ "postinstall": "dir=$(pwd) && cd node_modules/mailreader/ && npm install --production && cd $dir"
},
"dependencies": {
"axe-logger": "~0.0.2",
"compression": "^1.0.11",
+ "config": "^1.0.2",
"crypto-lib": "~0.2.1",
"dompurify": "~0.4.2",
"express": "^4.8.3",
"imap-client": "~0.4.3",
"jquery": "~2.1.1",
- "mailreader": "~0.3.5",
+ "mailreader": "~0.4.0",
+ "morgan": "^1.2.3",
"ng-infinite-scroll": "~1.1.2",
+ "npmlog": "^0.1.1",
"pgpbuilder": "~0.4.0",
"pgpmailer": "~0.4.0",
- "requirejs": "~2.1.14",
- "config": "^1.0.2",
- "morgan": "^1.2.3",
- "npmlog": "^0.1.1",
- "socket.io": "^1.0.6"
+ "socket.io": "^1.0.6",
+ "tcp-socket": "~0.3.13",
+ "wo-smtpclient": "^0.3.8"
},
"devDependencies": {
"angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version",
@@ -50,19 +52,22 @@
"browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master",
"chai": "~1.7.2",
"grunt": "~0.4.1",
- "grunt-contrib-clean": "~0.5.0",
- "grunt-contrib-copy": "~0.4.1",
- "grunt-manifest": "^0.4.0",
"grunt-autoprefixer": "~0.7.2",
+ "grunt-browserify": "^3.0.1",
+ "grunt-contrib-clean": "~0.5.0",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-connect": "~0.5.0",
+ "grunt-contrib-copy": "~0.4.1",
"grunt-contrib-jshint": "~0.6.4",
"grunt-contrib-sass": "~0.7.3",
+ "grunt-contrib-uglify": "^0.6.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-csso": "~0.6.1",
- "grunt-mocha": "~0.4.1",
- "grunt-node-webkit-builder": "~0.1.17",
- "mocha": "~1.13.0",
- "sinon": "~1.7.3"
+ "grunt-exorcise": "^0.2.0",
+ "grunt-manifest": "^0.4.0",
+ "grunt-mocha-phantomjs": "^0.6.0",
+ "mocha": "^1.21.4",
+ "sinon": "~1.7.3",
+ "time-grunt": "^1.0.0"
}
}
diff --git a/src/index.html b/src/index.html
index d0a577f..7868cc7 100644
--- a/src/index.html
+++ b/src/index.html
@@ -26,9 +26,9 @@
-
-
-
+
+
+
diff --git a/src/js/app-config.js b/src/js/app-config.js
index b520f42..fe3e99e 100644
--- a/src/js/app-config.js
+++ b/src/js/app-config.js
@@ -1,223 +1,217 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var _ = require('underscore'),
- app = {},
- appVersion, cloudUrl, keychainUrl, clientId;
+var appVersion, cloudUrl, keychainUrl, clientId;
- // parse manifest to get configurations for current runtime
- try {
- var manifest = chrome.runtime.getManifest();
- // get key server base url
- cloudUrl = _.find(manifest.permissions, function(permission) {
- return typeof permission === 'string' && permission.indexOf('https://keys') === 0;
- });
- // remove last '/' from url due to required syntax in manifest
- cloudUrl = cloudUrl.substring(0, cloudUrl.length - 1);
- // get keychain server base url
- keychainUrl = _.find(manifest.permissions, function(permission) {
- return typeof permission === 'string' && permission.indexOf('https://keychain') === 0;
- });
- // remove last '/' from url due to required syntax in manifest
- keychainUrl = keychainUrl.substring(0, keychainUrl.length - 1);
- // get client ID for OAuth requests
- clientId = manifest.oauth2.client_id;
- // get the app version
- appVersion = manifest.version;
- } catch (e) {}
+// parse manifest to get configurations for current runtime
+try {
+ var manifest = chrome.runtime.getManifest();
+ // get key server base url
+ cloudUrl = _.find(manifest.permissions, function(permission) {
+ return typeof permission === 'string' && permission.indexOf('https://keys') === 0;
+ });
+ // remove last '/' from url due to required syntax in manifest
+ cloudUrl = cloudUrl.substring(0, cloudUrl.length - 1);
+ // get keychain server base url
+ keychainUrl = _.find(manifest.permissions, function(permission) {
+ return typeof permission === 'string' && permission.indexOf('https://keychain') === 0;
+ });
+ // remove last '/' from url due to required syntax in manifest
+ keychainUrl = keychainUrl.substring(0, keychainUrl.length - 1);
+ // get client ID for OAuth requests
+ clientId = manifest.oauth2.client_id;
+ // get the app version
+ appVersion = manifest.version;
+} catch (e) {}
- /**
- * Global app configurations
- */
- app.config = {
- cloudUrl: cloudUrl || 'https://keys.whiteout.io',
- privkeyServerUrl: keychainUrl || 'https://keychain.whiteout.io',
- adminUrl: 'https://admin-node.whiteout.io',
- wmailDomain: 'wmail.io',
- serverPrivateKeyId: 'EE342F0DDBB0F3BE',
- symKeySize: 256,
- symIvSize: 96,
- asymKeySize: 2048,
- workerPath: 'js',
- reconnectInterval: 10000,
- wmail: {
- imap: {
- host: 'imap.wmail.io',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIGiTCCBXGgAwIBAgIDAn03MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ\r\nTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0\r\nYWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg\r\nMiBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTQwOTIxMTQ0ODQ0\r\nWhcNMTYwOTIxMTE0MzIxWjCBmTEZMBcGA1UEDRMQQ1NIeEdsdlg4Z3lRQ2c3TzEL\r\nMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMRUw\r\nEwYDVQQKEwxUYW5rcmVkIEhhc2UxEzARBgNVBAMUCioud21haWwuaW8xITAfBgkq\r\nhkiG9w0BCQEWEndlYm1hc3RlckB3bWFpbC5pbzCCASIwDQYJKoZIhvcNAQEBBQAD\r\nggEPADCCAQoCggEBAMkbMzFfZLYqfWG8yw2HvuNiFs5ajBFMrjG3fobePE674mPd\r\niFtXqbl3ydQ+umTtbJ6bztgxB3KgrL3lhp6IkD4VxB8YQJoYGhU6YH7FhP4QMm8l\r\ncnFLUZXEbcpcCg1tjL6+vvoTMUWEbV/zNtF/oiJ4AIOKwf0zUMZkTu1FCNrOrvpj\r\n6SAkOdBGzLTOAP5vxP43PfpZPZ4dLL2Be7ENYKXqPs0jSlUWpdT9l4AZG8rHKa2d\r\nccWvRoAsCfvpzGDoMYEx9+a1F1XjNZfzo7yJQcHdaE3Mj1eNqbjZe0+Vmact1S/3\r\nsubdcDVkFSfUMsAB5rH0D5mEhy7sMpt1WWCvOF8CAwEAAaOCAuMwggLfMAkGA1Ud\r\nEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\r\nATAdBgNVHQ4EFgQUv+9x4PISm5Roq4pdNoaFJeIZFfUwHwYDVR0jBBgwFoAUEdsj\r\nRf1UzGpxb4SKA9e+9wEvJoYwHwYDVR0RBBgwFoIKKi53bWFpbC5pb4IId21haWwu\r\naW8wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgIwggE7BgsrBgEEAYG1NwECAzCC\r\nASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w\r\nZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0\r\naG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3Jk\r\naW5nIHRvIHRoZSBDbGFzcyAyIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRo\r\nZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRl\r\nbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkg\r\nb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRz\r\nc2wuY29tL2NydDItY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcw\r\nAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczIvc2VydmVyL2Nh\r\nMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIu\r\nY2xhc3MyLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFy\r\ndHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQDEDbCBvdfs/lEsEJk0xGB6OghO\r\ngUAHplmWJEXoHb0h7p2QAIcs/QKorMDi35bu/J2vbVRIP7i5wBTZLIHBaf03mqAR\r\nZxYFy/ymyROVmmKl1x1/ry1aumomfU86UN8hCkvJc+40V2KC1lCZcjqPWufECjpo\r\n37QXFA+te/rVyVgvoMhIq+zOBZEK0/2mYGCwlpEQo3HElCQIwV9upChOHnQ2jZyF\r\nCmoUyv0JNr8dkh6H7+KTV6FzWaC+b6Liier9bpfEq/zDAp41GR+L/pdbaliSDtRg\r\nfPhAyCZqwsXid6HgIyTBqxUpGDGRiuygqghmqlFfppZuAqz02wrNceDHH7Up\r\n-----END CERTIFICATE-----\r\n',
- pinned: true,
- ignoreTLS: false
+/**
+ * Global app configurations
+ */
+exports.config = {
+ cloudUrl: cloudUrl || 'https://keys.whiteout.io',
+ privkeyServerUrl: keychainUrl || 'https://keychain.whiteout.io',
+ adminUrl: 'https://admin-node.whiteout.io',
+ wmailDomain: 'wmail.io',
+ serverPrivateKeyId: 'EE342F0DDBB0F3BE',
+ symKeySize: 256,
+ symIvSize: 96,
+ asymKeySize: 2048,
+ workerPath: 'js',
+ reconnectInterval: 10000,
+ wmail: {
+ imap: {
+ host: 'imap.wmail.io',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIGiTCCBXGgAwIBAgIDAn03MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ\r\nTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0\r\nYWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg\r\nMiBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTQwOTIxMTQ0ODQ0\r\nWhcNMTYwOTIxMTE0MzIxWjCBmTEZMBcGA1UEDRMQQ1NIeEdsdlg4Z3lRQ2c3TzEL\r\nMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMRUw\r\nEwYDVQQKEwxUYW5rcmVkIEhhc2UxEzARBgNVBAMUCioud21haWwuaW8xITAfBgkq\r\nhkiG9w0BCQEWEndlYm1hc3RlckB3bWFpbC5pbzCCASIwDQYJKoZIhvcNAQEBBQAD\r\nggEPADCCAQoCggEBAMkbMzFfZLYqfWG8yw2HvuNiFs5ajBFMrjG3fobePE674mPd\r\niFtXqbl3ydQ+umTtbJ6bztgxB3KgrL3lhp6IkD4VxB8YQJoYGhU6YH7FhP4QMm8l\r\ncnFLUZXEbcpcCg1tjL6+vvoTMUWEbV/zNtF/oiJ4AIOKwf0zUMZkTu1FCNrOrvpj\r\n6SAkOdBGzLTOAP5vxP43PfpZPZ4dLL2Be7ENYKXqPs0jSlUWpdT9l4AZG8rHKa2d\r\nccWvRoAsCfvpzGDoMYEx9+a1F1XjNZfzo7yJQcHdaE3Mj1eNqbjZe0+Vmact1S/3\r\nsubdcDVkFSfUMsAB5rH0D5mEhy7sMpt1WWCvOF8CAwEAAaOCAuMwggLfMAkGA1Ud\r\nEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\r\nATAdBgNVHQ4EFgQUv+9x4PISm5Roq4pdNoaFJeIZFfUwHwYDVR0jBBgwFoAUEdsj\r\nRf1UzGpxb4SKA9e+9wEvJoYwHwYDVR0RBBgwFoIKKi53bWFpbC5pb4IId21haWwu\r\naW8wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgIwggE7BgsrBgEEAYG1NwECAzCC\r\nASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w\r\nZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0\r\naG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3Jk\r\naW5nIHRvIHRoZSBDbGFzcyAyIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRo\r\nZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRl\r\nbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkg\r\nb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRz\r\nc2wuY29tL2NydDItY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcw\r\nAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczIvc2VydmVyL2Nh\r\nMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIu\r\nY2xhc3MyLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFy\r\ndHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQDEDbCBvdfs/lEsEJk0xGB6OghO\r\ngUAHplmWJEXoHb0h7p2QAIcs/QKorMDi35bu/J2vbVRIP7i5wBTZLIHBaf03mqAR\r\nZxYFy/ymyROVmmKl1x1/ry1aumomfU86UN8hCkvJc+40V2KC1lCZcjqPWufECjpo\r\n37QXFA+te/rVyVgvoMhIq+zOBZEK0/2mYGCwlpEQo3HElCQIwV9upChOHnQ2jZyF\r\nCmoUyv0JNr8dkh6H7+KTV6FzWaC+b6Liier9bpfEq/zDAp41GR+L/pdbaliSDtRg\r\nfPhAyCZqwsXid6HgIyTBqxUpGDGRiuygqghmqlFfppZuAqz02wrNceDHH7Up\r\n-----END CERTIFICATE-----\r\n',
+ pinned: true,
+ ignoreTLS: false
- },
- smtp: {
- host: 'smtp.wmail.io',
- port: 465,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIGiTCCBXGgAwIBAgIDAn03MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ\r\nTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0\r\nYWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg\r\nMiBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTQwOTIxMTQ0ODQ0\r\nWhcNMTYwOTIxMTE0MzIxWjCBmTEZMBcGA1UEDRMQQ1NIeEdsdlg4Z3lRQ2c3TzEL\r\nMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMRUw\r\nEwYDVQQKEwxUYW5rcmVkIEhhc2UxEzARBgNVBAMUCioud21haWwuaW8xITAfBgkq\r\nhkiG9w0BCQEWEndlYm1hc3RlckB3bWFpbC5pbzCCASIwDQYJKoZIhvcNAQEBBQAD\r\nggEPADCCAQoCggEBAMkbMzFfZLYqfWG8yw2HvuNiFs5ajBFMrjG3fobePE674mPd\r\niFtXqbl3ydQ+umTtbJ6bztgxB3KgrL3lhp6IkD4VxB8YQJoYGhU6YH7FhP4QMm8l\r\ncnFLUZXEbcpcCg1tjL6+vvoTMUWEbV/zNtF/oiJ4AIOKwf0zUMZkTu1FCNrOrvpj\r\n6SAkOdBGzLTOAP5vxP43PfpZPZ4dLL2Be7ENYKXqPs0jSlUWpdT9l4AZG8rHKa2d\r\nccWvRoAsCfvpzGDoMYEx9+a1F1XjNZfzo7yJQcHdaE3Mj1eNqbjZe0+Vmact1S/3\r\nsubdcDVkFSfUMsAB5rH0D5mEhy7sMpt1WWCvOF8CAwEAAaOCAuMwggLfMAkGA1Ud\r\nEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\r\nATAdBgNVHQ4EFgQUv+9x4PISm5Roq4pdNoaFJeIZFfUwHwYDVR0jBBgwFoAUEdsj\r\nRf1UzGpxb4SKA9e+9wEvJoYwHwYDVR0RBBgwFoIKKi53bWFpbC5pb4IId21haWwu\r\naW8wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgIwggE7BgsrBgEEAYG1NwECAzCC\r\nASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w\r\nZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0\r\naG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3Jk\r\naW5nIHRvIHRoZSBDbGFzcyAyIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRo\r\nZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRl\r\nbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkg\r\nb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRz\r\nc2wuY29tL2NydDItY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcw\r\nAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczIvc2VydmVyL2Nh\r\nMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIu\r\nY2xhc3MyLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFy\r\ndHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQDEDbCBvdfs/lEsEJk0xGB6OghO\r\ngUAHplmWJEXoHb0h7p2QAIcs/QKorMDi35bu/J2vbVRIP7i5wBTZLIHBaf03mqAR\r\nZxYFy/ymyROVmmKl1x1/ry1aumomfU86UN8hCkvJc+40V2KC1lCZcjqPWufECjpo\r\n37QXFA+te/rVyVgvoMhIq+zOBZEK0/2mYGCwlpEQo3HElCQIwV9upChOHnQ2jZyF\r\nCmoUyv0JNr8dkh6H7+KTV6FzWaC+b6Liier9bpfEq/zDAp41GR+L/pdbaliSDtRg\r\nfPhAyCZqwsXid6HgIyTBqxUpGDGRiuygqghmqlFfppZuAqz02wrNceDHH7Up\r\n-----END CERTIFICATE-----\r\n',
- pinned: true,
- ignoreTLS: false
- }
},
- gmail: {
- clientId: clientId || '440907777130.apps.googleusercontent.com',
- imap: {
- host: 'imap.gmail.com',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r\nMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r\nYWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG\r\nEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy\r\nbmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\nAJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP\r\nVaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv\r\nh8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE\r\nahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ\r\nEASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC\r\nDTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7\r\nqwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD\r\nVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g\r\nK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI\r\nKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n\r\nZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB\r\nBQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY\r\n/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/\r\nzG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza\r\nHFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\r\nWHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\r\nyuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- smtp: {
- host: 'smtp.gmail.com',
- port: 465,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r\nMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r\nYWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG\r\nEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy\r\nbmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\nAJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP\r\nVaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv\r\nh8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE\r\nahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ\r\nEASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC\r\nDTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7\r\nqwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD\r\nVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g\r\nK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI\r\nKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n\r\nZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB\r\nBQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY\r\n/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/\r\nzG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza\r\nHFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\r\nWHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\r\nyuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- ignoreUploadOnSent: true
+ smtp: {
+ host: 'smtp.wmail.io',
+ port: 465,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIGiTCCBXGgAwIBAgIDAn03MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ\r\nTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0\r\nYWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg\r\nMiBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTQwOTIxMTQ0ODQ0\r\nWhcNMTYwOTIxMTE0MzIxWjCBmTEZMBcGA1UEDRMQQ1NIeEdsdlg4Z3lRQ2c3TzEL\r\nMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMRUw\r\nEwYDVQQKEwxUYW5rcmVkIEhhc2UxEzARBgNVBAMUCioud21haWwuaW8xITAfBgkq\r\nhkiG9w0BCQEWEndlYm1hc3RlckB3bWFpbC5pbzCCASIwDQYJKoZIhvcNAQEBBQAD\r\nggEPADCCAQoCggEBAMkbMzFfZLYqfWG8yw2HvuNiFs5ajBFMrjG3fobePE674mPd\r\niFtXqbl3ydQ+umTtbJ6bztgxB3KgrL3lhp6IkD4VxB8YQJoYGhU6YH7FhP4QMm8l\r\ncnFLUZXEbcpcCg1tjL6+vvoTMUWEbV/zNtF/oiJ4AIOKwf0zUMZkTu1FCNrOrvpj\r\n6SAkOdBGzLTOAP5vxP43PfpZPZ4dLL2Be7ENYKXqPs0jSlUWpdT9l4AZG8rHKa2d\r\nccWvRoAsCfvpzGDoMYEx9+a1F1XjNZfzo7yJQcHdaE3Mj1eNqbjZe0+Vmact1S/3\r\nsubdcDVkFSfUMsAB5rH0D5mEhy7sMpt1WWCvOF8CAwEAAaOCAuMwggLfMAkGA1Ud\r\nEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\r\nATAdBgNVHQ4EFgQUv+9x4PISm5Roq4pdNoaFJeIZFfUwHwYDVR0jBBgwFoAUEdsj\r\nRf1UzGpxb4SKA9e+9wEvJoYwHwYDVR0RBBgwFoIKKi53bWFpbC5pb4IId21haWwu\r\naW8wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgIwggE7BgsrBgEEAYG1NwECAzCC\r\nASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w\r\nZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0\r\naG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3Jk\r\naW5nIHRvIHRoZSBDbGFzcyAyIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRo\r\nZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRl\r\nbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkg\r\nb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRz\r\nc2wuY29tL2NydDItY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcw\r\nAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczIvc2VydmVyL2Nh\r\nMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIu\r\nY2xhc3MyLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFy\r\ndHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQDEDbCBvdfs/lEsEJk0xGB6OghO\r\ngUAHplmWJEXoHb0h7p2QAIcs/QKorMDi35bu/J2vbVRIP7i5wBTZLIHBaf03mqAR\r\nZxYFy/ymyROVmmKl1x1/ry1aumomfU86UN8hCkvJc+40V2KC1lCZcjqPWufECjpo\r\n37QXFA+te/rVyVgvoMhIq+zOBZEK0/2mYGCwlpEQo3HElCQIwV9upChOHnQ2jZyF\r\nCmoUyv0JNr8dkh6H7+KTV6FzWaC+b6Liier9bpfEq/zDAp41GR+L/pdbaliSDtRg\r\nfPhAyCZqwsXid6HgIyTBqxUpGDGRiuygqghmqlFfppZuAqz02wrNceDHH7Up\r\n-----END CERTIFICATE-----\r\n',
+ pinned: true,
+ ignoreTLS: false
+ }
+ },
+ gmail: {
+ clientId: clientId || '440907777130.apps.googleusercontent.com',
+ imap: {
+ host: 'imap.gmail.com',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r\nMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r\nYWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG\r\nEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy\r\nbmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\nAJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP\r\nVaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv\r\nh8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE\r\nahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ\r\nEASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC\r\nDTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7\r\nqwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD\r\nVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g\r\nK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI\r\nKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n\r\nZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB\r\nBQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY\r\n/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/\r\nzG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza\r\nHFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\r\nWHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\r\nyuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
},
- yahoo: {
- imap: {
- host: 'imap.mail.yahoo.com',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIFUjCCBDqgAwIBAgIQdThnkckQvgouzHOsQA7ctTANBgkqhkiG9w0BAQUFADCB\r\ntTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\r\nExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug\r\nYXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEvMC0GA1UEAxMm\r\nVmVyaVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzMwHhcNMTQwNDIy\r\nMDAwMDAwWhcNMTUwNDIzMjM1OTU5WjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\r\nCkNhbGlmb3JuaWExEjAQBgNVBAcUCVN1bm55dmFsZTETMBEGA1UEChQKWWFob28g\r\nSW5jLjEfMB0GA1UECxQWSW5mb3JtYXRpb24gVGVjaG5vbG9neTEeMBwGA1UEAxQV\r\nKi5pbWFwLm1haWwueWFob28uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\r\nCgKCAQEAw36HN2sgtMNQ0TZlqGgfqInK/UT6y3ZgqDdmFRU9D5D5675hfxcwJoS+\r\nb0hIn/UixbZDpSLhNkjAkOTAbFEFWar7628D2dU5WtCUlFMiwg2TA0Un8B9EbUi5\r\nwDrqzXDyABVnBVR5I2eKwr5cuB9ldjxAabcCyqQhVKdH0+IskRpUrvxAb84uQtJg\r\nJyNieOZAWdxg9fkubk1YKw/MgJHnaY8P4lUlYY8fIY39d6gW6My8oT0IersrH1X1\r\n/oCmqUIGM1PawXBvvpPKYdI4fCH75/UaEQ41BFSUn1NsinFYZUPlVcBCOvLFEOQi\r\nuU+4Tjybq3x7NNhd3uBxfm4jo4h5zQIDAQABo4IBgzCCAX8wNQYDVR0RBC4wLIIV\r\nKi5pbWFwLm1haWwueWFob28uY29tghNpbWFwLm1haWwueWFob28uY29tMAkGA1Ud\r\nEwQCMAAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\r\nBQcDAjBlBgNVHSAEXjBcMFoGCmCGSAGG+EUBBzYwTDAjBggrBgEFBQcCARYXaHR0\r\ncHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5\r\nbWNiLmNvbS9ycGEwHwYDVR0jBBgwFoAUDURcFlNEwYJ+HSCrJfQBY9i+eaUwKwYD\r\nVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NkLnN5bWNiLmNvbS9zZC5jcmwwVwYIKwYB\r\nBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc2Quc3ltY2QuY29tMCYGCCsG\r\nAQUFBzAChhpodHRwOi8vc2Quc3ltY2IuY29tL3NkLmNydDANBgkqhkiG9w0BAQUF\r\nAAOCAQEAVxsglXJTtBTCoTwOd6j0iJQ+P9cxFVqHcmbshEfEQBlPwr4Sp9tLJ4kj\r\nfVi0XorWU6e6e57dtYtxpcPz+6WNSNKT0B0IBOTUTIBwSLJMHxEZI6gSS/fo1agt\r\n81B06rB8Rhn4yHwyDO/9uRvXbNYiEgpa5e6gIpXY6h6p1HscQMcuROaUA9ETvGd8\r\nDKG4XSZE7QAF9iB9WSLa/IQUD4sGMDaMp2q4XkoWZTnyL1bEDKwUvw9Z17PxVmrF\r\n8c7S5HTNU+1kyZw2LJRu3SgtsYXSWA88WFiKUPuqU+EBXmbrwLAwLAJ6mVc2bGFC\r\ng5fLGbtTscaARBlb1u3Iee2Fd419jg==\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- smtp: {
- host: 'smtp.mail.yahoo.com',
- port: 465,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIHITCCBgmgAwIBAgIQBlVSvxlwsqw8Kc8eVV5EKTANBgkqhkiG9w0BAQUFADBm\r\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\nd3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\r\nZSBDQS0zMB4XDTE0MDYwNTAwMDAwMFoXDTE1MDYyMzEyMDAwMFowYjELMAkGA1UE\r\nBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxFDASBgNVBAoM\r\nC1lhaG9vISBJbmMuMRwwGgYDVQQDExNzbXRwLm1haWwueWFob28uY29tMIIBIjAN\r\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA339OSxTIuW6NVqKwYHFBbg4/tmEx\r\nMYpzohtObPaWgvLTsYdce+WlQFBU5rxaCMUtVsVAGJWs5uQRDVHXRLPnOWe+foqZ\r\n5ItgjYIQc1XeMv6BZEeaF3Bum5ehUyLB3y48cjbWxma1QlkZ8XAK0f9AS7ySWAen\r\no5OXJlMFAqXGtKMAhY46dzSY0wjgdrvgiomFRy0iQKV1DxGsXoXSMEszlUTQoNQ3\r\nWTsiA3O//cdWE06wWeA3/90cb7QkU3KflSoyfi878BQGpPR1L+rLNsqnc8QuucbD\r\nz4Q++rxGqgg4QYrOtmZfAn96TXhPWCwKld6FN+f3uV5ITOBFx44M5v1ILQIDAQAB\r\no4IDzTCCA8kwHwYDVR0jBBgwFoAUUOpzidsp+xCPnuUBINTeeZlIg/cwHQYDVR0O\r\nBBYEFEhOpSFQjO/QrSNfVwyInZUhyzhsMIICJAYDVR0RBIICGzCCAheCE3NtdHAu\r\nbWFpbC55YWhvby5jb22CFnNtdHAubWFpbC55YWhvby5jb20uYXKCFnNtdHAubWFp\r\nbC55YWhvby5jb20uYXWCFnNtdHAubWFpbC55YWhvby5jb20uYnKCFnNtdHAubWFp\r\nbC55YWhvby5jb20uY26CFnNtdHAubWFpbC55YWhvby5jb20uaGuCFnNtdHAubWFp\r\nbC55YWhvby5jb20ubXmCFnNtdHAubWFpbC55YWhvby5jb20ucGiCFnNtdHAubWFp\r\nbC55YWhvby5jb20uc2eCFnNtdHAubWFpbC55YWhvby5jb20udHeCFnNtdHAubWFp\r\nbC55YWhvby5jb20udm6CFXNtdHAubWFpbC55YWhvby5jby5pZIIVc210cC5tYWls\r\nLnlhaG9vLmNvLmlughVzbXRwLm1haWwueWFob28uY28ua3KCFXNtdHAubWFpbC55\r\nYWhvby5jby50aIIVc210cC5tYWlsLnlhaG9vLmNvLnVrghJzbXRwLm1haWwueWFo\r\nb28uY2GCEnNtdHAubWFpbC55YWhvby5jboISc210cC5tYWlsLnlhaG9vLmRlghJz\r\nbXRwLm1haWwueWFob28uZXOCEnNtdHAubWFpbC55YWhvby5mcoISc210cC5tYWls\r\nLnlhaG9vLml0gg9zbXRwLnk3bWFpbC5jb22CFHNtdHAuY29ycmVvLnlhaG9vLmVz\r\nMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\r\nYQYDVR0fBFowWDAqoCigJoYkaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL2NhMy1n\r\nMjguY3JsMCqgKKAmhiRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vY2EzLWcyOC5j\r\ncmwwQgYDVR0gBDswOTA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6\r\nLy93d3cuZGlnaWNlcnQuY29tL0NQUzB7BggrBgEFBQcBAQRvMG0wJAYIKwYBBQUH\r\nMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBFBggrBgEFBQcwAoY5aHR0cDov\r\nL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUNBLTMu\r\nY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEFBQADggEBABshjUND4hADHGfe\r\ncV9XGXcr9h3u7mT5kgdcgGFhcrFAlwkzt0NUCbuN0X8DWHE72Tpb3zRE25CmUUJe\r\nktBbq9PQb4b5/Wt1htAEw0qUs3BsUbqejK9OHJ/11Jn2ek4+SLJuYlijzc7KM3F/\r\nyz7ZTZtKR0PglkXfqbpvWYGabYpfL2FRLoJ7alTLsMJcFxbSLYcAIMxufj7RyTBJ\r\nbKgRJl4wmP4+Zc2Q1p59mENY0u5HqVAAOmWc0jNb0/31+tRr5f6EgXxK++7TQOpF\r\n0TOaFsXlzRlpKfmIbzVr2nfwghV5/bRZj96TK3g1OoOz4C8ksK4INHnUdTAqZ18M\r\nvHpnJw4=\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- }
+ smtp: {
+ host: 'smtp.gmail.com',
+ port: 465,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r\nMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r\nYWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG\r\nEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy\r\nbmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\nAJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP\r\nVaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv\r\nh8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE\r\nahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ\r\nEASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC\r\nDTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7\r\nqwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD\r\nVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g\r\nK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI\r\nKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n\r\nZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB\r\nBQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY\r\n/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/\r\nzG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza\r\nHFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\r\nWHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\r\nyuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
},
- tonline: {
- imap: {
- host: 'secureimap.t-online.de',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIGmzCCBYOgAwIBAgIIIbZ3foy9DqgwDQYJKoZIhvcNAQEFBQAwcTELMAkGA1UE\r\nBhMCREUxHDAaBgNVBAoTE0RldXRzY2hlIFRlbGVrb20gQUcxHzAdBgNVBAsTFlQt\r\nVGVsZVNlYyBUcnVzdCBDZW50ZXIxIzAhBgNVBAMTGkRldXRzY2hlIFRlbGVrb20g\r\nUm9vdCBDQSAyMB4XDTEzMDMwMTEzNTgyOVoXDTE5MDcwOTIzNTkwMFowgckxCzAJ\r\nBgNVBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJI\r\nMR8wHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcx\r\nDjAMBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRl\r\ncmUgSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNz\r\nIERFLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwg+9QiuYAxX9/\r\n4F9XRZrS1o0q+aa9L/5/K3vc+RqPpliiZ24vTkJc1JDpXrbWXS25uT3yzHukQrhI\r\nq0AbcRqNEAeFi5EhUiEM/vtb4BYGHdqfXQ3etgYYcCtJ43NAHaSgsyQ9kyGV2lmM\r\nwkeAX3qZ2CGE9/cR6w+bOogHArBdk2JaHG09myNZDytr6oUbWLjLd/qhC9YzyZSX\r\nbZgE/kh5L5Y6P9paw2pDdn7+Ni4pXzlmoj1k43uiz+h2ibe3DO9dKMZAaEKeyG1O\r\ng0f0r53M8O+8Bm2sXtWelrAgrfFlISgWzO1hkNs12rWpr4c5Ygde/behx9OQmPwp\r\nmS+e3WvTAgMBAAGjggLcMIIC2DAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFGJP\r\nE842Z4TNGfygTxmL7xVUATIcMB8GA1UdIwQYMBaAFDHDeRu69VPXF+CJei0XbAqz\r\nK50zMBIGA1UdEwEB/wQIMAYBAf8CAQAwWQYDVR0gBFIwUDBEBgkrBgEEAb1HDQIw\r\nNzA1BggrBgEFBQcCARYpaHR0cDovL3d3dy50ZWxlc2VjLmRlL3NlcnZlcnBhc3Mv\r\nY3BzLmh0bWwwCAYGZ4EMAQICMIHvBgNVHR8EgecwgeQwOqA4oDaGNGh0dHA6Ly9j\r\ncmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL0RUX1JPT1RfQ0FfMi5jcmwwgaWg\r\ngaKggZ+GgZxsZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvQ049RGV1\r\ndHNjaGUlMjBUZWxla29tJTIwUm9vdCUyMENBJTIwMixPVT1ULVRlbGVTZWMlMjBU\r\ncnVzdCUyMENlbnRlcixPPURldXRzY2hlJTIwVGVsZWtvbSUyMEFHLEM9REU/QXV0\r\naG9yaXR5UmV2b2NhdGlvbkxpc3QwggEjBggrBgEFBQcBAQSCARUwggERMCoGCCsG\r\nAQUFBzABhh5odHRwOi8vb2NzcDAyLnRlbGVzZWMuZGUvb2NzcHIwQQYIKwYBBQUH\r\nMAKGNWh0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NydC9EVF9ST09U\r\nX0NBXzIuY2VyMIGfBggrBgEFBQcwAoaBkmxkYXA6Ly9sZGFwLnNlcnZlcnBhc3Mu\r\ndGVsZXNlYy5kZS9DTj1EZXV0c2NoZSUyMFRlbGVrb20lMjBSb290JTIwQ0ElMjAy\r\nLE9VPVQtVGVsZVNlYyUyMFRydXN0JTIwQ2VudGVyLE89RGV1dHNjaGUlMjBUZWxl\r\na29tJTIwQUcsQz1ERT9jQUNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4IBAQBO\r\nE04qoEkEc9ad+WwSurVYfcDdjGvpqrtbI89woXDsWLQTMhA7D7jVuls90SJns0vc\r\nK9qoYkEGt0/ZlawLe2lyNWtueHfUf+dgleUunwHYLxuj3jQ2ERzQLVLrswjecRpX\r\nvGAGej89WpGQ9PMq27WGNC5WCmzVC9rk5naFgacsbwKwyjU0LoBArtAQnAAlpHDw\r\nPenv1Pe7MhUkCK0LqdTvkI/AHFzPYg/l5E3j8lQQ8hiKx8U6wf9xVKECLA2RlRqY\r\nUX2rpjQNxnvEq/mEQv3x3mLOEFJ3TAKI+soDgOOi0OG8+ywhm6S+7Z9lTlJ+BcD6\r\noy1MNKd4CQbltHLMTFUH\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- smtp: {
- host: 'securesmtp.t-online.de',
- port: 465,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIGmzCCBYOgAwIBAgIIIbZ3foy9DqgwDQYJKoZIhvcNAQEFBQAwcTELMAkGA1UE\r\nBhMCREUxHDAaBgNVBAoTE0RldXRzY2hlIFRlbGVrb20gQUcxHzAdBgNVBAsTFlQt\r\nVGVsZVNlYyBUcnVzdCBDZW50ZXIxIzAhBgNVBAMTGkRldXRzY2hlIFRlbGVrb20g\r\nUm9vdCBDQSAyMB4XDTEzMDMwMTEzNTgyOVoXDTE5MDcwOTIzNTkwMFowgckxCzAJ\r\nBgNVBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJI\r\nMR8wHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcx\r\nDjAMBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRl\r\ncmUgSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNz\r\nIERFLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwg+9QiuYAxX9/\r\n4F9XRZrS1o0q+aa9L/5/K3vc+RqPpliiZ24vTkJc1JDpXrbWXS25uT3yzHukQrhI\r\nq0AbcRqNEAeFi5EhUiEM/vtb4BYGHdqfXQ3etgYYcCtJ43NAHaSgsyQ9kyGV2lmM\r\nwkeAX3qZ2CGE9/cR6w+bOogHArBdk2JaHG09myNZDytr6oUbWLjLd/qhC9YzyZSX\r\nbZgE/kh5L5Y6P9paw2pDdn7+Ni4pXzlmoj1k43uiz+h2ibe3DO9dKMZAaEKeyG1O\r\ng0f0r53M8O+8Bm2sXtWelrAgrfFlISgWzO1hkNs12rWpr4c5Ygde/behx9OQmPwp\r\nmS+e3WvTAgMBAAGjggLcMIIC2DAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFGJP\r\nE842Z4TNGfygTxmL7xVUATIcMB8GA1UdIwQYMBaAFDHDeRu69VPXF+CJei0XbAqz\r\nK50zMBIGA1UdEwEB/wQIMAYBAf8CAQAwWQYDVR0gBFIwUDBEBgkrBgEEAb1HDQIw\r\nNzA1BggrBgEFBQcCARYpaHR0cDovL3d3dy50ZWxlc2VjLmRlL3NlcnZlcnBhc3Mv\r\nY3BzLmh0bWwwCAYGZ4EMAQICMIHvBgNVHR8EgecwgeQwOqA4oDaGNGh0dHA6Ly9j\r\ncmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL0RUX1JPT1RfQ0FfMi5jcmwwgaWg\r\ngaKggZ+GgZxsZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvQ049RGV1\r\ndHNjaGUlMjBUZWxla29tJTIwUm9vdCUyMENBJTIwMixPVT1ULVRlbGVTZWMlMjBU\r\ncnVzdCUyMENlbnRlcixPPURldXRzY2hlJTIwVGVsZWtvbSUyMEFHLEM9REU/QXV0\r\naG9yaXR5UmV2b2NhdGlvbkxpc3QwggEjBggrBgEFBQcBAQSCARUwggERMCoGCCsG\r\nAQUFBzABhh5odHRwOi8vb2NzcDAyLnRlbGVzZWMuZGUvb2NzcHIwQQYIKwYBBQUH\r\nMAKGNWh0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NydC9EVF9ST09U\r\nX0NBXzIuY2VyMIGfBggrBgEFBQcwAoaBkmxkYXA6Ly9sZGFwLnNlcnZlcnBhc3Mu\r\ndGVsZXNlYy5kZS9DTj1EZXV0c2NoZSUyMFRlbGVrb20lMjBSb290JTIwQ0ElMjAy\r\nLE9VPVQtVGVsZVNlYyUyMFRydXN0JTIwQ2VudGVyLE89RGV1dHNjaGUlMjBUZWxl\r\na29tJTIwQUcsQz1ERT9jQUNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4IBAQBO\r\nE04qoEkEc9ad+WwSurVYfcDdjGvpqrtbI89woXDsWLQTMhA7D7jVuls90SJns0vc\r\nK9qoYkEGt0/ZlawLe2lyNWtueHfUf+dgleUunwHYLxuj3jQ2ERzQLVLrswjecRpX\r\nvGAGej89WpGQ9PMq27WGNC5WCmzVC9rk5naFgacsbwKwyjU0LoBArtAQnAAlpHDw\r\nPenv1Pe7MhUkCK0LqdTvkI/AHFzPYg/l5E3j8lQQ8hiKx8U6wf9xVKECLA2RlRqY\r\nUX2rpjQNxnvEq/mEQv3x3mLOEFJ3TAKI+soDgOOi0OG8+ywhm6S+7Z9lTlJ+BcD6\r\noy1MNKd4CQbltHLMTFUH\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- }
+ ignoreUploadOnSent: true
+ },
+ yahoo: {
+ imap: {
+ host: 'imap.mail.yahoo.com',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIFUjCCBDqgAwIBAgIQdThnkckQvgouzHOsQA7ctTANBgkqhkiG9w0BAQUFADCB\r\ntTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\r\nExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug\r\nYXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEvMC0GA1UEAxMm\r\nVmVyaVNpZ24gQ2xhc3MgMyBTZWN1cmUgU2VydmVyIENBIC0gRzMwHhcNMTQwNDIy\r\nMDAwMDAwWhcNMTUwNDIzMjM1OTU5WjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\r\nCkNhbGlmb3JuaWExEjAQBgNVBAcUCVN1bm55dmFsZTETMBEGA1UEChQKWWFob28g\r\nSW5jLjEfMB0GA1UECxQWSW5mb3JtYXRpb24gVGVjaG5vbG9neTEeMBwGA1UEAxQV\r\nKi5pbWFwLm1haWwueWFob28uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\r\nCgKCAQEAw36HN2sgtMNQ0TZlqGgfqInK/UT6y3ZgqDdmFRU9D5D5675hfxcwJoS+\r\nb0hIn/UixbZDpSLhNkjAkOTAbFEFWar7628D2dU5WtCUlFMiwg2TA0Un8B9EbUi5\r\nwDrqzXDyABVnBVR5I2eKwr5cuB9ldjxAabcCyqQhVKdH0+IskRpUrvxAb84uQtJg\r\nJyNieOZAWdxg9fkubk1YKw/MgJHnaY8P4lUlYY8fIY39d6gW6My8oT0IersrH1X1\r\n/oCmqUIGM1PawXBvvpPKYdI4fCH75/UaEQ41BFSUn1NsinFYZUPlVcBCOvLFEOQi\r\nuU+4Tjybq3x7NNhd3uBxfm4jo4h5zQIDAQABo4IBgzCCAX8wNQYDVR0RBC4wLIIV\r\nKi5pbWFwLm1haWwueWFob28uY29tghNpbWFwLm1haWwueWFob28uY29tMAkGA1Ud\r\nEwQCMAAwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\r\nBQcDAjBlBgNVHSAEXjBcMFoGCmCGSAGG+EUBBzYwTDAjBggrBgEFBQcCARYXaHR0\r\ncHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5\r\nbWNiLmNvbS9ycGEwHwYDVR0jBBgwFoAUDURcFlNEwYJ+HSCrJfQBY9i+eaUwKwYD\r\nVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NkLnN5bWNiLmNvbS9zZC5jcmwwVwYIKwYB\r\nBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc2Quc3ltY2QuY29tMCYGCCsG\r\nAQUFBzAChhpodHRwOi8vc2Quc3ltY2IuY29tL3NkLmNydDANBgkqhkiG9w0BAQUF\r\nAAOCAQEAVxsglXJTtBTCoTwOd6j0iJQ+P9cxFVqHcmbshEfEQBlPwr4Sp9tLJ4kj\r\nfVi0XorWU6e6e57dtYtxpcPz+6WNSNKT0B0IBOTUTIBwSLJMHxEZI6gSS/fo1agt\r\n81B06rB8Rhn4yHwyDO/9uRvXbNYiEgpa5e6gIpXY6h6p1HscQMcuROaUA9ETvGd8\r\nDKG4XSZE7QAF9iB9WSLa/IQUD4sGMDaMp2q4XkoWZTnyL1bEDKwUvw9Z17PxVmrF\r\n8c7S5HTNU+1kyZw2LJRu3SgtsYXSWA88WFiKUPuqU+EBXmbrwLAwLAJ6mVc2bGFC\r\ng5fLGbtTscaARBlb1u3Iee2Fd419jg==\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
},
- outlook: {
- imap: {
- host: 'imap-mail.outlook.com',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIFQjCCBCqgAwIBAgISESHl0vjrML7zKmGlv42YL75vMA0GCSqGSIb3DQEBBQUA\r\nMF0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTMwMQYD\r\nVQQDEypHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gRzIw\r\nHhcNMTMwNDI0MjAzNTA5WhcNMTYwNDI0MjAzNTA5WjBsMQswCQYDVQQGEwJVUzET\r\nMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV\r\nTWljcm9zb2Z0IENvcnBvcmF0aW9uMRYwFAYDVQQDDA0qLmhvdG1haWwuY29tMIIB\r\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumSiBWrzHZf6WFP5a/j4+K7D\r\n1izLoYKj5Omll0pdxKvKcBRDf+iaIkCbSOPNpx2uWGZdwNwkabYCQavaBf2ebwmS\r\nS8i1CJpHflO+k0qYd5WUi7sSsZ3+6RaCMdLoDIPGyYMQuy7TFtVO7LSt5+qscyyi\r\nET8c3lE2aj/XW13UZvRrV65ZJvMjUtwaDnIcAxGeasYoebLsKdqHQ2uTr4PmNwCc\r\nviGVFSOzkGAoC0PfyqKB2xUWy3Kc5zRI2xvUW8Jb2b/9Ze3g55pIUzKsjpglkQTm\r\nedVPSYYPGNz6Kl/ZshBXdBAk398q1JkSmUaTMa2hJgBbcC+73ax40AJDGJlz+QID\r\nAQABo4IB6zCCAecwDgYDVR0PAQH/BAQDAgWgMEkGA1UdIARCMEAwPgYGZ4EMAQIC\r\nMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9z\r\naXRvcnkvMEAGA1UdEQQ5MDeCDSouaG90bWFpbC5jb22CCioubGl2ZS5jb22CDSou\r\nb3V0bG9vay5jb22CC2hvdG1haWwuY29tMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYI\r\nKwYBBQUHAwEGCCsGAQUFBwMCMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwu\r\nZ2xvYmFsc2lnbi5jb20vZ3MvZ3Nvcmdhbml6YXRpb252YWxnMi5jcmwwgZYGCCsG\r\nAQUFBwEBBIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNp\r\nZ24uY29tL2NhY2VydC9nc29yZ2FuaXphdGlvbnZhbGcyLmNydDA7BggrBgEFBQcw\r\nAYYvaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzb3JnYW5pemF0aW9udmFs\r\nZzIwHQYDVR0OBBYEFHbgHqTLsXDt7uMRyE62rnDEfLn9MB8GA1UdIwQYMBaAFF1G\r\nso3ES3Qcu+31c7Y6tziPdZ5+MA0GCSqGSIb3DQEBBQUAA4IBAQByy1+3N6ZRVooI\r\nxqw8Ng+UFz0g7UHkbPEnvTu1uxJ2AojFuP/P1PAk+/6uMRvpPlWg/5uqmOIWxKxJ\r\nLo6xSbkDf4LN+KYwes3XSuPyziZ4QbPnehHhZ0377iiA8fpRJADg9NWKCRHh5aAd\r\ne9QvJUW/GgYkBN+F4yYc2jIjR3Rehv4JYOKS3iXO9OoHsDS2CcCFaS2imgQVfYLg\r\nslBwT/A08PCOhW5huiluSmih7x5Qf7sFDv8jineu6ehKzi8pKnOq4k8G4QiWn38Y\r\nCeiBkkwFOwj7T3M/ITiiSS9DHDGeokj16eBi83Zx3YYiJ9YZvnQ+4GvqJ5eJJ6pR\r\nKKvemr+m\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- smtp: {
- host: 'smtp-mail.outlook.com',
- port: 587,
- secure: false,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIFQjCCBCqgAwIBAgISESHl0vjrML7zKmGlv42YL75vMA0GCSqGSIb3DQEBBQUA\r\nMF0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTMwMQYD\r\nVQQDEypHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gRzIw\r\nHhcNMTMwNDI0MjAzNTA5WhcNMTYwNDI0MjAzNTA5WjBsMQswCQYDVQQGEwJVUzET\r\nMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV\r\nTWljcm9zb2Z0IENvcnBvcmF0aW9uMRYwFAYDVQQDDA0qLmhvdG1haWwuY29tMIIB\r\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumSiBWrzHZf6WFP5a/j4+K7D\r\n1izLoYKj5Omll0pdxKvKcBRDf+iaIkCbSOPNpx2uWGZdwNwkabYCQavaBf2ebwmS\r\nS8i1CJpHflO+k0qYd5WUi7sSsZ3+6RaCMdLoDIPGyYMQuy7TFtVO7LSt5+qscyyi\r\nET8c3lE2aj/XW13UZvRrV65ZJvMjUtwaDnIcAxGeasYoebLsKdqHQ2uTr4PmNwCc\r\nviGVFSOzkGAoC0PfyqKB2xUWy3Kc5zRI2xvUW8Jb2b/9Ze3g55pIUzKsjpglkQTm\r\nedVPSYYPGNz6Kl/ZshBXdBAk398q1JkSmUaTMa2hJgBbcC+73ax40AJDGJlz+QID\r\nAQABo4IB6zCCAecwDgYDVR0PAQH/BAQDAgWgMEkGA1UdIARCMEAwPgYGZ4EMAQIC\r\nMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9z\r\naXRvcnkvMEAGA1UdEQQ5MDeCDSouaG90bWFpbC5jb22CCioubGl2ZS5jb22CDSou\r\nb3V0bG9vay5jb22CC2hvdG1haWwuY29tMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYI\r\nKwYBBQUHAwEGCCsGAQUFBwMCMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwu\r\nZ2xvYmFsc2lnbi5jb20vZ3MvZ3Nvcmdhbml6YXRpb252YWxnMi5jcmwwgZYGCCsG\r\nAQUFBwEBBIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNp\r\nZ24uY29tL2NhY2VydC9nc29yZ2FuaXphdGlvbnZhbGcyLmNydDA7BggrBgEFBQcw\r\nAYYvaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzb3JnYW5pemF0aW9udmFs\r\nZzIwHQYDVR0OBBYEFHbgHqTLsXDt7uMRyE62rnDEfLn9MB8GA1UdIwQYMBaAFF1G\r\nso3ES3Qcu+31c7Y6tziPdZ5+MA0GCSqGSIb3DQEBBQUAA4IBAQByy1+3N6ZRVooI\r\nxqw8Ng+UFz0g7UHkbPEnvTu1uxJ2AojFuP/P1PAk+/6uMRvpPlWg/5uqmOIWxKxJ\r\nLo6xSbkDf4LN+KYwes3XSuPyziZ4QbPnehHhZ0377iiA8fpRJADg9NWKCRHh5aAd\r\ne9QvJUW/GgYkBN+F4yYc2jIjR3Rehv4JYOKS3iXO9OoHsDS2CcCFaS2imgQVfYLg\r\nslBwT/A08PCOhW5huiluSmih7x5Qf7sFDv8jineu6ehKzi8pKnOq4k8G4QiWn38Y\r\nCeiBkkwFOwj7T3M/ITiiSS9DHDGeokj16eBi83Zx3YYiJ9YZvnQ+4GvqJ5eJJ6pR\r\nKKvemr+m\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- }
+ smtp: {
+ host: 'smtp.mail.yahoo.com',
+ port: 465,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIHITCCBgmgAwIBAgIQBlVSvxlwsqw8Kc8eVV5EKTANBgkqhkiG9w0BAQUFADBm\r\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\nd3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\r\nZSBDQS0zMB4XDTE0MDYwNTAwMDAwMFoXDTE1MDYyMzEyMDAwMFowYjELMAkGA1UE\r\nBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxFDASBgNVBAoM\r\nC1lhaG9vISBJbmMuMRwwGgYDVQQDExNzbXRwLm1haWwueWFob28uY29tMIIBIjAN\r\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA339OSxTIuW6NVqKwYHFBbg4/tmEx\r\nMYpzohtObPaWgvLTsYdce+WlQFBU5rxaCMUtVsVAGJWs5uQRDVHXRLPnOWe+foqZ\r\n5ItgjYIQc1XeMv6BZEeaF3Bum5ehUyLB3y48cjbWxma1QlkZ8XAK0f9AS7ySWAen\r\no5OXJlMFAqXGtKMAhY46dzSY0wjgdrvgiomFRy0iQKV1DxGsXoXSMEszlUTQoNQ3\r\nWTsiA3O//cdWE06wWeA3/90cb7QkU3KflSoyfi878BQGpPR1L+rLNsqnc8QuucbD\r\nz4Q++rxGqgg4QYrOtmZfAn96TXhPWCwKld6FN+f3uV5ITOBFx44M5v1ILQIDAQAB\r\no4IDzTCCA8kwHwYDVR0jBBgwFoAUUOpzidsp+xCPnuUBINTeeZlIg/cwHQYDVR0O\r\nBBYEFEhOpSFQjO/QrSNfVwyInZUhyzhsMIICJAYDVR0RBIICGzCCAheCE3NtdHAu\r\nbWFpbC55YWhvby5jb22CFnNtdHAubWFpbC55YWhvby5jb20uYXKCFnNtdHAubWFp\r\nbC55YWhvby5jb20uYXWCFnNtdHAubWFpbC55YWhvby5jb20uYnKCFnNtdHAubWFp\r\nbC55YWhvby5jb20uY26CFnNtdHAubWFpbC55YWhvby5jb20uaGuCFnNtdHAubWFp\r\nbC55YWhvby5jb20ubXmCFnNtdHAubWFpbC55YWhvby5jb20ucGiCFnNtdHAubWFp\r\nbC55YWhvby5jb20uc2eCFnNtdHAubWFpbC55YWhvby5jb20udHeCFnNtdHAubWFp\r\nbC55YWhvby5jb20udm6CFXNtdHAubWFpbC55YWhvby5jby5pZIIVc210cC5tYWls\r\nLnlhaG9vLmNvLmlughVzbXRwLm1haWwueWFob28uY28ua3KCFXNtdHAubWFpbC55\r\nYWhvby5jby50aIIVc210cC5tYWlsLnlhaG9vLmNvLnVrghJzbXRwLm1haWwueWFo\r\nb28uY2GCEnNtdHAubWFpbC55YWhvby5jboISc210cC5tYWlsLnlhaG9vLmRlghJz\r\nbXRwLm1haWwueWFob28uZXOCEnNtdHAubWFpbC55YWhvby5mcoISc210cC5tYWls\r\nLnlhaG9vLml0gg9zbXRwLnk3bWFpbC5jb22CFHNtdHAuY29ycmVvLnlhaG9vLmVz\r\nMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\r\nYQYDVR0fBFowWDAqoCigJoYkaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL2NhMy1n\r\nMjguY3JsMCqgKKAmhiRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vY2EzLWcyOC5j\r\ncmwwQgYDVR0gBDswOTA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6\r\nLy93d3cuZGlnaWNlcnQuY29tL0NQUzB7BggrBgEFBQcBAQRvMG0wJAYIKwYBBQUH\r\nMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBFBggrBgEFBQcwAoY5aHR0cDov\r\nL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUNBLTMu\r\nY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEFBQADggEBABshjUND4hADHGfe\r\ncV9XGXcr9h3u7mT5kgdcgGFhcrFAlwkzt0NUCbuN0X8DWHE72Tpb3zRE25CmUUJe\r\nktBbq9PQb4b5/Wt1htAEw0qUs3BsUbqejK9OHJ/11Jn2ek4+SLJuYlijzc7KM3F/\r\nyz7ZTZtKR0PglkXfqbpvWYGabYpfL2FRLoJ7alTLsMJcFxbSLYcAIMxufj7RyTBJ\r\nbKgRJl4wmP4+Zc2Q1p59mENY0u5HqVAAOmWc0jNb0/31+tRr5f6EgXxK++7TQOpF\r\n0TOaFsXlzRlpKfmIbzVr2nfwghV5/bRZj96TK3g1OoOz4C8ksK4INHnUdTAqZ18M\r\nvHpnJw4=\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
+ }
+ },
+ tonline: {
+ imap: {
+ host: 'secureimap.t-online.de',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIGmzCCBYOgAwIBAgIIIbZ3foy9DqgwDQYJKoZIhvcNAQEFBQAwcTELMAkGA1UE\r\nBhMCREUxHDAaBgNVBAoTE0RldXRzY2hlIFRlbGVrb20gQUcxHzAdBgNVBAsTFlQt\r\nVGVsZVNlYyBUcnVzdCBDZW50ZXIxIzAhBgNVBAMTGkRldXRzY2hlIFRlbGVrb20g\r\nUm9vdCBDQSAyMB4XDTEzMDMwMTEzNTgyOVoXDTE5MDcwOTIzNTkwMFowgckxCzAJ\r\nBgNVBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJI\r\nMR8wHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcx\r\nDjAMBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRl\r\ncmUgSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNz\r\nIERFLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwg+9QiuYAxX9/\r\n4F9XRZrS1o0q+aa9L/5/K3vc+RqPpliiZ24vTkJc1JDpXrbWXS25uT3yzHukQrhI\r\nq0AbcRqNEAeFi5EhUiEM/vtb4BYGHdqfXQ3etgYYcCtJ43NAHaSgsyQ9kyGV2lmM\r\nwkeAX3qZ2CGE9/cR6w+bOogHArBdk2JaHG09myNZDytr6oUbWLjLd/qhC9YzyZSX\r\nbZgE/kh5L5Y6P9paw2pDdn7+Ni4pXzlmoj1k43uiz+h2ibe3DO9dKMZAaEKeyG1O\r\ng0f0r53M8O+8Bm2sXtWelrAgrfFlISgWzO1hkNs12rWpr4c5Ygde/behx9OQmPwp\r\nmS+e3WvTAgMBAAGjggLcMIIC2DAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFGJP\r\nE842Z4TNGfygTxmL7xVUATIcMB8GA1UdIwQYMBaAFDHDeRu69VPXF+CJei0XbAqz\r\nK50zMBIGA1UdEwEB/wQIMAYBAf8CAQAwWQYDVR0gBFIwUDBEBgkrBgEEAb1HDQIw\r\nNzA1BggrBgEFBQcCARYpaHR0cDovL3d3dy50ZWxlc2VjLmRlL3NlcnZlcnBhc3Mv\r\nY3BzLmh0bWwwCAYGZ4EMAQICMIHvBgNVHR8EgecwgeQwOqA4oDaGNGh0dHA6Ly9j\r\ncmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL0RUX1JPT1RfQ0FfMi5jcmwwgaWg\r\ngaKggZ+GgZxsZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvQ049RGV1\r\ndHNjaGUlMjBUZWxla29tJTIwUm9vdCUyMENBJTIwMixPVT1ULVRlbGVTZWMlMjBU\r\ncnVzdCUyMENlbnRlcixPPURldXRzY2hlJTIwVGVsZWtvbSUyMEFHLEM9REU/QXV0\r\naG9yaXR5UmV2b2NhdGlvbkxpc3QwggEjBggrBgEFBQcBAQSCARUwggERMCoGCCsG\r\nAQUFBzABhh5odHRwOi8vb2NzcDAyLnRlbGVzZWMuZGUvb2NzcHIwQQYIKwYBBQUH\r\nMAKGNWh0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NydC9EVF9ST09U\r\nX0NBXzIuY2VyMIGfBggrBgEFBQcwAoaBkmxkYXA6Ly9sZGFwLnNlcnZlcnBhc3Mu\r\ndGVsZXNlYy5kZS9DTj1EZXV0c2NoZSUyMFRlbGVrb20lMjBSb290JTIwQ0ElMjAy\r\nLE9VPVQtVGVsZVNlYyUyMFRydXN0JTIwQ2VudGVyLE89RGV1dHNjaGUlMjBUZWxl\r\na29tJTIwQUcsQz1ERT9jQUNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4IBAQBO\r\nE04qoEkEc9ad+WwSurVYfcDdjGvpqrtbI89woXDsWLQTMhA7D7jVuls90SJns0vc\r\nK9qoYkEGt0/ZlawLe2lyNWtueHfUf+dgleUunwHYLxuj3jQ2ERzQLVLrswjecRpX\r\nvGAGej89WpGQ9PMq27WGNC5WCmzVC9rk5naFgacsbwKwyjU0LoBArtAQnAAlpHDw\r\nPenv1Pe7MhUkCK0LqdTvkI/AHFzPYg/l5E3j8lQQ8hiKx8U6wf9xVKECLA2RlRqY\r\nUX2rpjQNxnvEq/mEQv3x3mLOEFJ3TAKI+soDgOOi0OG8+ywhm6S+7Z9lTlJ+BcD6\r\noy1MNKd4CQbltHLMTFUH\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
},
- gmx: {
- imap: {
- host: 'imap.gmx.net',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIHUDCCBjigAwIBAgIIM52e2Oc5J8kwDQYJKoZIhvcNAQEFBQAwgckxCzAJBgNV\r\nBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJIMR8w\r\nHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcxDjAM\r\nBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRlcmUg\r\nSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNzIERF\r\nLTEwHhcNMTMxMTEyMTAxNzMxWhcNMTYxMTE3MjM1OTU5WjCBnTELMAkGA1UEBhMC\r\nREUxHjAcBgNVBAoMFTEmMSBNYWlsICYgTWVkaWEgR21iSDEdMBsGA1UECBMUUmhp\r\nbmVsYW5kLVBhbGF0aW5hdGUxEjAQBgNVBAcTCU1vbnRhYmF1cjEkMCIGCSqGSIb3\r\nDQEJARYVc2VydmVyLWNlcnRzQDF1bmQxLmRlMRUwEwYDVQQDEwxpbWFwLmdteC5u\r\nZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHP3QN1ztX5m8LaC9m\r\nt2nrcLBEfxb61FQCieXW4OV/D5HEy7vgQIAeS+pg2/9ClawprQFbLUa46owUcJuq\r\no2SaefsYqjRhIP/tPeyGRJQmfnyCRRoHIYno57/bz2qmHjzvkqEUMvNGVVej7BJv\r\nGukNKPXYicodkRodF3EicTPnGitGeXOsAxyPuCPIsBPAMuuuBzKenS7nj+yseSGe\r\nkM7/kjtNgbjDyBXi2BvoUS/U+Gm9p1lq0ymT9fhGj/k9/Qz312GHYxfZB1bhL0pk\r\nadF25P8fTIy5tKMWqJfgCF+eaOwgkYecxeCcrt2E3D8ThLvmkBRrXsTT51ZzD7sp\r\n7hPpAgMBAAGjggNkMIIDYDAfBgNVHSMEGDAWgBRiTxPONmeEzRn8oE8Zi+8VVAEy\r\nHDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB\r\nMB0GA1UdDgQWBBRfb2gYyD6V+oBN2Ii5WQj0AddemjBZBgNVHSAEUjBQMEQGCSsG\r\nAQQBvUcNAjA3MDUGCCsGAQUFBwIBFilodHRwOi8vd3d3LnRlbGVzZWMuZGUvc2Vy\r\ndmVycGFzcy9jcHMuaHRtbDAIBgZngQwBAgIwggEhBgNVHR8EggEYMIIBFDBFoEOg\r\nQYY/aHR0cDovL2NybC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvcmwvVGVsZVNlY19T\r\nZXJ2ZXJQYXNzX0RFLTEuY3JsMIHKoIHHoIHEhoHBbGRhcDovL2xkYXAuc2VydmVy\r\ncGFzcy50ZWxlc2VjLmRlL2NuPVRlbGVTZWMlMjBTZXJ2ZXJQYXNzJTIwREUtMSxv\r\ndT1ULVN5c3RlbXMlMjBUcnVzdCUyMENlbnRlcixvPVQtU3lzdGVtcyUyMEludGVy\r\nbmF0aW9uYWwlMjBHbWJILGM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9ubGlzdD9i\r\nYXNlP2NlcnRpZmljYXRlUmV2b2NhdGlvbmxpc3Q9KjCCATkGCCsGAQUFBwEBBIIB\r\nKzCCAScwMwYIKwYBBQUHMAGGJ2h0dHA6Ly9vY3NwLnNlcnZlcnBhc3MudGVsZXNl\r\nYy5kZS9vY3NwcjBMBggrBgEFBQcwAoZAaHR0cDovL2NybC5zZXJ2ZXJwYXNzLnRl\r\nbGVzZWMuZGUvY3J0L1RlbGVTZWNfU2VydmVyUGFzc19ERS0xLmNlcjCBoQYIKwYB\r\nBQUHMAKGgZRsZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvY249VGVs\r\nZVNlYyUyMFNlcnZlclBhc3MlMjBERS0xLG91PVQtU3lzdGVtcyUyMFRydXN0JTIw\r\nQ2VudGVyLG89VC1TeXN0ZW1zJTIwSW50ZXJuYXRpb25hbCUyMEdtYkgsYz1kZT9j\r\nQUNlcnRpZmljYXRlMAwGA1UdEwEB/wQCMAAwJAYDVR0RBB0wG4IMaW1hcC5nbXgu\r\nbmV0ggtpbWFwLmdteC5kZTANBgkqhkiG9w0BAQUFAAOCAQEADl442s2ouynDNEzl\r\nBPzhCxjp47TmKzgzrCGh1AH3+UOkw54mYU65UaY9cJ51jgOu+pjNB4KxVfcqyG5O\r\nJcowS09ZtZ+khb1OkzXAAbEqNj0oyH/1K550d5Ir5VbXF0ZdVKVTzEFRyjvUt5NJ\r\n/b6Q2bbY/sPm8QiK9SPaYkO5/3J1KB0u7PkqqfOhZ9UJE6mIN66T2bpFmAwle3zL\r\n6+L/VwYSgUNs/w2l6xWlYP3pFFaT12TO43Q057I3vP7yCt3QE/VLDpdQOQ3H0oy2\r\nJQGPJLFby9MPYNkmEmwjh4e95TAY4ZkZMe08ix0J1Smy8DwjTz6SXqYC+EC/PQlh\r\nE0UHxA==\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- smtp: {
- host: 'mail.gmx.net',
- port: 587,
- secure: false,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIHbDCCBlSgAwIBAgIJAJ74Ek9UaA0TMA0GCSqGSIb3DQEBBQUAMIHJMQswCQYD\r\nVQQGEwJERTElMCMGA1UEChMcVC1TeXN0ZW1zIEludGVybmF0aW9uYWwgR21iSDEf\r\nMB0GA1UECxMWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEMMAoGA1UECBMDTlJXMQ4w\r\nDAYDVQQREwU1NzI1MDEQMA4GA1UEBxMHTmV0cGhlbjEgMB4GA1UECRMXVW50ZXJl\r\nIEluZHVzdHJpZXN0ci4gMjAxIDAeBgNVBAMTF1RlbGVTZWMgU2VydmVyUGFzcyBE\r\nRS0xMB4XDTEzMTExMjEwMTY0N1oXDTE2MTExNzIzNTk1OVowgZ0xCzAJBgNVBAYT\r\nAkRFMR4wHAYDVQQKDBUxJjEgTWFpbCAmIE1lZGlhIEdtYkgxHTAbBgNVBAgTFFJo\r\naW5lbGFuZC1QYWxhdGluYXRlMRIwEAYDVQQHEwlNb250YWJhdXIxJDAiBgkqhkiG\r\n9w0BCQEWFXNlcnZlci1jZXJ0c0AxdW5kMS5kZTEVMBMGA1UEAxMMbWFpbC5nbXgu\r\nbmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsEUYppbJXUpQELIL\r\nETAFUwreDfSmbyi9gJPUqquogROHEoRV+bBFZ2YCiHgLU8AggcLmM74HAQMFt8F5\r\neS2OyuEar3E3tNW5XFiI1QblTtY3B7o1coKyq/i+tV3b1jGq4+1aJeeD3UpcraBm\r\nk2XuQgQ6WAeY+XCYyI/OzZ56ZjQ17LHMMI0ayu7SSV+VBpG9loC9E5A82iVtZsqo\r\nSaUZpZf/xICpUgNJ+RlalSsoE6FdCywE/gEEmkpAUh+Mv0WvHITk6aqtMFWex8tE\r\n8cwJGQbmJGt9x8BExbhMY6uQ+HsnsDCPCMVh5JGKx7/e+qyxtHYGChOeI16m2+MT\r\nz47jSQIDAQABo4IDfzCCA3swHwYDVR0jBBgwFoAUYk8TzjZnhM0Z/KBPGYvvFVQB\r\nMhwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\r\nATAdBgNVHQ4EFgQUH8mLfxsd5FEh9M+3t3rP6qLiFTEwWQYDVR0gBFIwUDBEBgkr\r\nBgEEAb1HDQIwNzA1BggrBgEFBQcCARYpaHR0cDovL3d3dy50ZWxlc2VjLmRlL3Nl\r\ncnZlcnBhc3MvY3BzLmh0bWwwCAYGZ4EMAQICMIIBIQYDVR0fBIIBGDCCARQwRaBD\r\noEGGP2h0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL1RlbGVTZWNf\r\nU2VydmVyUGFzc19ERS0xLmNybDCByqCBx6CBxIaBwWxkYXA6Ly9sZGFwLnNlcnZl\r\ncnBhc3MudGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2VydmVyUGFzcyUyMERFLTEs\r\nb3U9VC1TeXN0ZW1zJTIwVHJ1c3QlMjBDZW50ZXIsbz1ULVN5c3RlbXMlMjBJbnRl\r\ncm5hdGlvbmFsJTIwR21iSCxjPWRlP2NlcnRpZmljYXRlUmV2b2NhdGlvbmxpc3Q/\r\nYmFzZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25saXN0PSowggE5BggrBgEFBQcBAQSC\r\nASswggEnMDMGCCsGAQUFBzABhidodHRwOi8vb2NzcC5zZXJ2ZXJwYXNzLnRlbGVz\r\nZWMuZGUvb2NzcHIwTAYIKwYBBQUHMAKGQGh0dHA6Ly9jcmwuc2VydmVycGFzcy50\r\nZWxlc2VjLmRlL2NydC9UZWxlU2VjX1NlcnZlclBhc3NfREUtMS5jZXIwgaEGCCsG\r\nAQUFBzAChoGUbGRhcDovL2xkYXAuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NuPVRl\r\nbGVTZWMlMjBTZXJ2ZXJQYXNzJTIwREUtMSxvdT1ULVN5c3RlbXMlMjBUcnVzdCUy\r\nMENlbnRlcixvPVQtU3lzdGVtcyUyMEludGVybmF0aW9uYWwlMjBHbWJILGM9ZGU/\r\nY0FDZXJ0aWZpY2F0ZTAMBgNVHRMBAf8EAjAAMD8GA1UdEQQ4MDaCDG1haWwuZ214\r\nLm5ldIILbWFpbC5nbXguZGWCDHNtdHAuZ214Lm5ldIILc210cC5nbXguZGUwDQYJ\r\nKoZIhvcNAQEFBQADggEBAJ5SKsBXoOTO0ztsFh8RVd/iu6sijEMpKVF+/cs74TZN\r\nK1QWIz8Ay1f3SUPWXTvkmvayUXWGtxZfYoRIrx3feWBdUozJxe0wz1O3tDQOQgRX\r\nnkcwk7nibTUmW2rk5AIwV0jzOHtIbAGjSdc6my0543e7dVkhcuoCOC+g2NmD+pHF\r\ni1KpmqTLecDlFvprIZUJ23AT1uTnuXYg/tFHeDn3ga00Gce82xZQJelRirJs01SR\r\nDGEBaPXBjJVJNoAP/qEy3jQNRWo5TbSgwn3DTR81FJvltmf0c+zlt4fmcpjpr5ni\r\nFvK7L0rZQL5MOGHPpgRIukEBZCowYr3OYpZYBEaB94I=\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- }
+ smtp: {
+ host: 'securesmtp.t-online.de',
+ port: 465,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIGmzCCBYOgAwIBAgIIIbZ3foy9DqgwDQYJKoZIhvcNAQEFBQAwcTELMAkGA1UE\r\nBhMCREUxHDAaBgNVBAoTE0RldXRzY2hlIFRlbGVrb20gQUcxHzAdBgNVBAsTFlQt\r\nVGVsZVNlYyBUcnVzdCBDZW50ZXIxIzAhBgNVBAMTGkRldXRzY2hlIFRlbGVrb20g\r\nUm9vdCBDQSAyMB4XDTEzMDMwMTEzNTgyOVoXDTE5MDcwOTIzNTkwMFowgckxCzAJ\r\nBgNVBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJI\r\nMR8wHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcx\r\nDjAMBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRl\r\ncmUgSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNz\r\nIERFLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwg+9QiuYAxX9/\r\n4F9XRZrS1o0q+aa9L/5/K3vc+RqPpliiZ24vTkJc1JDpXrbWXS25uT3yzHukQrhI\r\nq0AbcRqNEAeFi5EhUiEM/vtb4BYGHdqfXQ3etgYYcCtJ43NAHaSgsyQ9kyGV2lmM\r\nwkeAX3qZ2CGE9/cR6w+bOogHArBdk2JaHG09myNZDytr6oUbWLjLd/qhC9YzyZSX\r\nbZgE/kh5L5Y6P9paw2pDdn7+Ni4pXzlmoj1k43uiz+h2ibe3DO9dKMZAaEKeyG1O\r\ng0f0r53M8O+8Bm2sXtWelrAgrfFlISgWzO1hkNs12rWpr4c5Ygde/behx9OQmPwp\r\nmS+e3WvTAgMBAAGjggLcMIIC2DAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFGJP\r\nE842Z4TNGfygTxmL7xVUATIcMB8GA1UdIwQYMBaAFDHDeRu69VPXF+CJei0XbAqz\r\nK50zMBIGA1UdEwEB/wQIMAYBAf8CAQAwWQYDVR0gBFIwUDBEBgkrBgEEAb1HDQIw\r\nNzA1BggrBgEFBQcCARYpaHR0cDovL3d3dy50ZWxlc2VjLmRlL3NlcnZlcnBhc3Mv\r\nY3BzLmh0bWwwCAYGZ4EMAQICMIHvBgNVHR8EgecwgeQwOqA4oDaGNGh0dHA6Ly9j\r\ncmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL0RUX1JPT1RfQ0FfMi5jcmwwgaWg\r\ngaKggZ+GgZxsZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvQ049RGV1\r\ndHNjaGUlMjBUZWxla29tJTIwUm9vdCUyMENBJTIwMixPVT1ULVRlbGVTZWMlMjBU\r\ncnVzdCUyMENlbnRlcixPPURldXRzY2hlJTIwVGVsZWtvbSUyMEFHLEM9REU/QXV0\r\naG9yaXR5UmV2b2NhdGlvbkxpc3QwggEjBggrBgEFBQcBAQSCARUwggERMCoGCCsG\r\nAQUFBzABhh5odHRwOi8vb2NzcDAyLnRlbGVzZWMuZGUvb2NzcHIwQQYIKwYBBQUH\r\nMAKGNWh0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NydC9EVF9ST09U\r\nX0NBXzIuY2VyMIGfBggrBgEFBQcwAoaBkmxkYXA6Ly9sZGFwLnNlcnZlcnBhc3Mu\r\ndGVsZXNlYy5kZS9DTj1EZXV0c2NoZSUyMFRlbGVrb20lMjBSb290JTIwQ0ElMjAy\r\nLE9VPVQtVGVsZVNlYyUyMFRydXN0JTIwQ2VudGVyLE89RGV1dHNjaGUlMjBUZWxl\r\na29tJTIwQUcsQz1ERT9jQUNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4IBAQBO\r\nE04qoEkEc9ad+WwSurVYfcDdjGvpqrtbI89woXDsWLQTMhA7D7jVuls90SJns0vc\r\nK9qoYkEGt0/ZlawLe2lyNWtueHfUf+dgleUunwHYLxuj3jQ2ERzQLVLrswjecRpX\r\nvGAGej89WpGQ9PMq27WGNC5WCmzVC9rk5naFgacsbwKwyjU0LoBArtAQnAAlpHDw\r\nPenv1Pe7MhUkCK0LqdTvkI/AHFzPYg/l5E3j8lQQ8hiKx8U6wf9xVKECLA2RlRqY\r\nUX2rpjQNxnvEq/mEQv3x3mLOEFJ3TAKI+soDgOOi0OG8+ywhm6S+7Z9lTlJ+BcD6\r\noy1MNKd4CQbltHLMTFUH\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
+ }
+ },
+ outlook: {
+ imap: {
+ host: 'imap-mail.outlook.com',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIFQjCCBCqgAwIBAgISESHl0vjrML7zKmGlv42YL75vMA0GCSqGSIb3DQEBBQUA\r\nMF0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTMwMQYD\r\nVQQDEypHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gRzIw\r\nHhcNMTMwNDI0MjAzNTA5WhcNMTYwNDI0MjAzNTA5WjBsMQswCQYDVQQGEwJVUzET\r\nMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV\r\nTWljcm9zb2Z0IENvcnBvcmF0aW9uMRYwFAYDVQQDDA0qLmhvdG1haWwuY29tMIIB\r\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumSiBWrzHZf6WFP5a/j4+K7D\r\n1izLoYKj5Omll0pdxKvKcBRDf+iaIkCbSOPNpx2uWGZdwNwkabYCQavaBf2ebwmS\r\nS8i1CJpHflO+k0qYd5WUi7sSsZ3+6RaCMdLoDIPGyYMQuy7TFtVO7LSt5+qscyyi\r\nET8c3lE2aj/XW13UZvRrV65ZJvMjUtwaDnIcAxGeasYoebLsKdqHQ2uTr4PmNwCc\r\nviGVFSOzkGAoC0PfyqKB2xUWy3Kc5zRI2xvUW8Jb2b/9Ze3g55pIUzKsjpglkQTm\r\nedVPSYYPGNz6Kl/ZshBXdBAk398q1JkSmUaTMa2hJgBbcC+73ax40AJDGJlz+QID\r\nAQABo4IB6zCCAecwDgYDVR0PAQH/BAQDAgWgMEkGA1UdIARCMEAwPgYGZ4EMAQIC\r\nMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9z\r\naXRvcnkvMEAGA1UdEQQ5MDeCDSouaG90bWFpbC5jb22CCioubGl2ZS5jb22CDSou\r\nb3V0bG9vay5jb22CC2hvdG1haWwuY29tMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYI\r\nKwYBBQUHAwEGCCsGAQUFBwMCMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwu\r\nZ2xvYmFsc2lnbi5jb20vZ3MvZ3Nvcmdhbml6YXRpb252YWxnMi5jcmwwgZYGCCsG\r\nAQUFBwEBBIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNp\r\nZ24uY29tL2NhY2VydC9nc29yZ2FuaXphdGlvbnZhbGcyLmNydDA7BggrBgEFBQcw\r\nAYYvaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzb3JnYW5pemF0aW9udmFs\r\nZzIwHQYDVR0OBBYEFHbgHqTLsXDt7uMRyE62rnDEfLn9MB8GA1UdIwQYMBaAFF1G\r\nso3ES3Qcu+31c7Y6tziPdZ5+MA0GCSqGSIb3DQEBBQUAA4IBAQByy1+3N6ZRVooI\r\nxqw8Ng+UFz0g7UHkbPEnvTu1uxJ2AojFuP/P1PAk+/6uMRvpPlWg/5uqmOIWxKxJ\r\nLo6xSbkDf4LN+KYwes3XSuPyziZ4QbPnehHhZ0377iiA8fpRJADg9NWKCRHh5aAd\r\ne9QvJUW/GgYkBN+F4yYc2jIjR3Rehv4JYOKS3iXO9OoHsDS2CcCFaS2imgQVfYLg\r\nslBwT/A08PCOhW5huiluSmih7x5Qf7sFDv8jineu6ehKzi8pKnOq4k8G4QiWn38Y\r\nCeiBkkwFOwj7T3M/ITiiSS9DHDGeokj16eBi83Zx3YYiJ9YZvnQ+4GvqJ5eJJ6pR\r\nKKvemr+m\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
},
- webde: {
- imap: {
- host: 'imap.web.de',
- port: 993,
- secure: true,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIHUjCCBjqgAwIBAgIIHvqUOScyxYUwDQYJKoZIhvcNAQEFBQAwgckxCzAJBgNV\r\nBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJIMR8w\r\nHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcxDjAM\r\nBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRlcmUg\r\nSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNzIERF\r\nLTEwHhcNMTMwODIxMDgzMTE2WhcNMTYwODI2MjM1OTU5WjCBrTELMAkGA1UEBhMC\r\nREUxHjAcBgNVBAoMFTEmMSBNYWlsICYgTWVkaWEgR21iSDEPMA0GA1UECxMGV0VC\r\nLkRFMR0wGwYDVQQIExRSaGluZWxhbmQtUGFsYXRpbmF0ZTESMBAGA1UEBxMJTW9u\r\ndGFiYXVyMSQwIgYJKoZIhvcNAQkBFhVzZXJ2ZXItY2VydHNAMXVuZDEuZGUxFDAS\r\nBgNVBAMTC2ltYXAud2ViLmRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\r\nAQEA5dvpcnYczFs9GANTYN5N3mP6ATFVm7P4nYhRIQMj/YssSjmbrOPIEbe12JNC\r\nRO9CI7Z4Dnk42BM5TiH+QKGpcfnitofOv4gKPjwCMcPDHfY152/+YDaiyU/md2Hg\r\n/WrZ/50KwC8Sw1tZkYDXWB0zeJkfPdS2r4ATNrpMR0fYcG08+elz5T2SWNg+c1xL\r\nKFdCh33wZLkijOfW0HA164QjXaLPBjxa+GyZFY19ywOQ85KdFVVLmGUrLz8n4ZLc\r\n7K6KUuzYttnUuVxctFauQ4DRHE/CfUvvNHHgn5d+A2XS7jNUgmUb0gjzy3OtlTP3\r\ngM4ostVufmnlS7qqFDR7A3v4lQIDAQABo4IDVjCCA1IwHwYDVR0jBBgwFoAUYk8T\r\nzjZnhM0Z/KBPGYvvFVQBMhwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsG\r\nAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4EFgQUDH66P/Y4NlKGphPniIzmutEI9ocw\r\nWQYDVR0gBFIwUDBEBgkrBgEEAb1HDQIwNzA1BggrBgEFBQcCARYpaHR0cDovL3d3\r\ndy50ZWxlc2VjLmRlL3NlcnZlcnBhc3MvY3BzLmh0bWwwCAYGZ4EMAQICMIIBIQYD\r\nVR0fBIIBGDCCARQwRaBDoEGGP2h0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2Vj\r\nLmRlL3JsL1RlbGVTZWNfU2VydmVyUGFzc19ERS0xLmNybDCByqCBx6CBxIaBwWxk\r\nYXA6Ly9sZGFwLnNlcnZlcnBhc3MudGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2Vy\r\ndmVyUGFzcyUyMERFLTEsb3U9VC1TeXN0ZW1zJTIwVHJ1c3QlMjBDZW50ZXIsbz1U\r\nLVN5c3RlbXMlMjBJbnRlcm5hdGlvbmFsJTIwR21iSCxjPWRlP2NlcnRpZmljYXRl\r\nUmV2b2NhdGlvbmxpc3Q/YmFzZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25saXN0PSow\r\nggE5BggrBgEFBQcBAQSCASswggEnMDMGCCsGAQUFBzABhidodHRwOi8vb2NzcC5z\r\nZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvb2NzcHIwTAYIKwYBBQUHMAKGQGh0dHA6Ly9j\r\ncmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NydC9UZWxlU2VjX1NlcnZlclBhc3Nf\r\nREUtMS5jZXIwgaEGCCsGAQUFBzAChoGUbGRhcDovL2xkYXAuc2VydmVycGFzcy50\r\nZWxlc2VjLmRlL2NuPVRlbGVTZWMlMjBTZXJ2ZXJQYXNzJTIwREUtMSxvdT1ULVN5\r\nc3RlbXMlMjBUcnVzdCUyMENlbnRlcixvPVQtU3lzdGVtcyUyMEludGVybmF0aW9u\r\nYWwlMjBHbWJILGM9ZGU/Y0FDZXJ0aWZpY2F0ZTAMBgNVHRMBAf8EAjAAMBYGA1Ud\r\nEQQPMA2CC2ltYXAud2ViLmRlMA0GCSqGSIb3DQEBBQUAA4IBAQAp7MQjjOWQ0M7N\r\n21GrPDfWSMR3eJnuMs37I9G2t9i99w7xKtmoVBPyYMORL1zRHn/DEguo4j5ua7CH\r\nrKLh9Sd1wDKqVWGFxvmP4f/mvEx5YVI68mg+M2VQf/h58IXTTZRbUcsv3HVeruI6\r\npgQNUsEQqRVJmrgT/iPd98RhhzBqef6Wfrt3Ns6N835egphxUVcVj/v/PqBCZKQb\r\nNl5QsoaHDqh3XC+Og2awOGvWHUzxUKEqkP5nsMs2YjfOtcQRtxdislQAfRktuUBA\r\nWMZAlvoVF/CIyFvcUH11KNur7HfK5PptvtdvLQaF2c+lN+LGP6D+nbTLqAo1v09o\r\nnZpHbQOt\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- },
- smtp: {
- host: 'smtp.web.de',
- port: 587,
- secure: false,
- ca: '-----BEGIN CERTIFICATE-----\r\nMIIHUzCCBjugAwIBAgIJAKaEwtMgQ2s5MA0GCSqGSIb3DQEBBQUAMIHJMQswCQYD\r\nVQQGEwJERTElMCMGA1UEChMcVC1TeXN0ZW1zIEludGVybmF0aW9uYWwgR21iSDEf\r\nMB0GA1UECxMWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEMMAoGA1UECBMDTlJXMQ4w\r\nDAYDVQQREwU1NzI1MDEQMA4GA1UEBxMHTmV0cGhlbjEgMB4GA1UECRMXVW50ZXJl\r\nIEluZHVzdHJpZXN0ci4gMjAxIDAeBgNVBAMTF1RlbGVTZWMgU2VydmVyUGFzcyBE\r\nRS0xMB4XDTEzMDgyMTA4MzU1MVoXDTE2MDgyNjIzNTk1OVowga0xCzAJBgNVBAYT\r\nAkRFMR4wHAYDVQQKDBUxJjEgTWFpbCAmIE1lZGlhIEdtYkgxDzANBgNVBAsTBldF\r\nQi5ERTEdMBsGA1UECBMUUmhpbmVsYW5kLVBhbGF0aW5hdGUxEjAQBgNVBAcTCU1v\r\nbnRhYmF1cjEkMCIGCSqGSIb3DQEJARYVc2VydmVyLWNlcnRzQDF1bmQxLmRlMRQw\r\nEgYDVQQDEwtzbXRwLndlYi5kZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\r\nggEBAL1WfyFqmifaEr6h9yntJKs33fnEVu0pQqS5RV9rnQU0E/cJYJ9RJOoTjhpE\r\nkT1LW8DyTM5vUzpgtFHQM0BOO6jOeZXUYNUaopK3yO4l/cpiitigtk9ZnWfKzbU3\r\n9hlhf+YwUUvoqjUA8I6fSu+VNPNlOBvamo18oHljXAPltL9oiwAxvTLNktBMy4T9\r\njxU1DeGoPbJKGwV7zIBQ2qUHuLkMvy5/H39t79Tih+zfzgfY/xIUfdmPNY9dK8ZY\r\nAtyF/RiUS199pd9dV4Vwh6JLvtNlWchBnKVhragLCGbkjnvUXmS1BPrclLR23s1v\r\nMehgOD2WhXl8PoqrOPb6y+lgMlECAwEAAaOCA1YwggNSMB8GA1UdIwQYMBaAFGJP\r\nE842Z4TNGfygTxmL7xVUATIcMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggr\r\nBgEFBQcDAgYIKwYBBQUHAwEwHQYDVR0OBBYEFAUuppozNCv2UzMV5p6CTpkEhsRS\r\nMFkGA1UdIARSMFAwRAYJKwYBBAG9Rw0CMDcwNQYIKwYBBQUHAgEWKWh0dHA6Ly93\r\nd3cudGVsZXNlYy5kZS9zZXJ2ZXJwYXNzL2Nwcy5odG1sMAgGBmeBDAECAjCCASEG\r\nA1UdHwSCARgwggEUMEWgQ6BBhj9odHRwOi8vY3JsLnNlcnZlcnBhc3MudGVsZXNl\r\nYy5kZS9ybC9UZWxlU2VjX1NlcnZlclBhc3NfREUtMS5jcmwwgcqggceggcSGgcFs\r\nZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvY249VGVsZVNlYyUyMFNl\r\ncnZlclBhc3MlMjBERS0xLG91PVQtU3lzdGVtcyUyMFRydXN0JTIwQ2VudGVyLG89\r\nVC1TeXN0ZW1zJTIwSW50ZXJuYXRpb25hbCUyMEdtYkgsYz1kZT9jZXJ0aWZpY2F0\r\nZVJldm9jYXRpb25saXN0P2Jhc2U/Y2VydGlmaWNhdGVSZXZvY2F0aW9ubGlzdD0q\r\nMIIBOQYIKwYBBQUHAQEEggErMIIBJzAzBggrBgEFBQcwAYYnaHR0cDovL29jc3Au\r\nc2VydmVycGFzcy50ZWxlc2VjLmRlL29jc3ByMEwGCCsGAQUFBzAChkBodHRwOi8v\r\nY3JsLnNlcnZlcnBhc3MudGVsZXNlYy5kZS9jcnQvVGVsZVNlY19TZXJ2ZXJQYXNz\r\nX0RFLTEuY2VyMIGhBggrBgEFBQcwAoaBlGxkYXA6Ly9sZGFwLnNlcnZlcnBhc3Mu\r\ndGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2VydmVyUGFzcyUyMERFLTEsb3U9VC1T\r\neXN0ZW1zJTIwVHJ1c3QlMjBDZW50ZXIsbz1ULVN5c3RlbXMlMjBJbnRlcm5hdGlv\r\nbmFsJTIwR21iSCxjPWRlP2NBQ2VydGlmaWNhdGUwDAYDVR0TAQH/BAIwADAWBgNV\r\nHREEDzANggtzbXRwLndlYi5kZTANBgkqhkiG9w0BAQUFAAOCAQEAGFtJxVxWrURy\r\nFfR4UfmW+N1cZZx9sfC5jolV8LGje87DgbWdqu5TRL9FoQ1pwOTbM9mc3yWSoIbU\r\nx6E+rziJK+SFGMIy+Lt13P9M9Oc8JzVHoVEAgqlEeO6OYxrGE6SaSjZODJxPaEtU\r\nzEAKf0HVJQoGaU6fD+/8l3yhksAlsF/L85nP+KcZtoancOkJWE0GQMZp7pdLU0Ou\r\nFUQoAcqMIyHQfDqJ5iwvx/9C7jmy3Nvw9tXdPrdn2O7ywrnFeJuT2xiorZzg6ezn\r\nUlc/sMvd/LPX0f60pSQr9tkZgU4f8Jvx9EvPUCFTRXlXqkBIhgJhgCadZC+wKB1P\r\neQMS8rksXw==\r\n-----END CERTIFICATE-----',
- pinned: true,
- ignoreTLS: false
- }
+ smtp: {
+ host: 'smtp-mail.outlook.com',
+ port: 587,
+ secure: false,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIFQjCCBCqgAwIBAgISESHl0vjrML7zKmGlv42YL75vMA0GCSqGSIb3DQEBBQUA\r\nMF0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMTMwMQYD\r\nVQQDEypHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBWYWxpZGF0aW9uIENBIC0gRzIw\r\nHhcNMTMwNDI0MjAzNTA5WhcNMTYwNDI0MjAzNTA5WjBsMQswCQYDVQQGEwJVUzET\r\nMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV\r\nTWljcm9zb2Z0IENvcnBvcmF0aW9uMRYwFAYDVQQDDA0qLmhvdG1haWwuY29tMIIB\r\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumSiBWrzHZf6WFP5a/j4+K7D\r\n1izLoYKj5Omll0pdxKvKcBRDf+iaIkCbSOPNpx2uWGZdwNwkabYCQavaBf2ebwmS\r\nS8i1CJpHflO+k0qYd5WUi7sSsZ3+6RaCMdLoDIPGyYMQuy7TFtVO7LSt5+qscyyi\r\nET8c3lE2aj/XW13UZvRrV65ZJvMjUtwaDnIcAxGeasYoebLsKdqHQ2uTr4PmNwCc\r\nviGVFSOzkGAoC0PfyqKB2xUWy3Kc5zRI2xvUW8Jb2b/9Ze3g55pIUzKsjpglkQTm\r\nedVPSYYPGNz6Kl/ZshBXdBAk398q1JkSmUaTMa2hJgBbcC+73ax40AJDGJlz+QID\r\nAQABo4IB6zCCAecwDgYDVR0PAQH/BAQDAgWgMEkGA1UdIARCMEAwPgYGZ4EMAQIC\r\nMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9z\r\naXRvcnkvMEAGA1UdEQQ5MDeCDSouaG90bWFpbC5jb22CCioubGl2ZS5jb22CDSou\r\nb3V0bG9vay5jb22CC2hvdG1haWwuY29tMAkGA1UdEwQCMAAwHQYDVR0lBBYwFAYI\r\nKwYBBQUHAwEGCCsGAQUFBwMCMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwu\r\nZ2xvYmFsc2lnbi5jb20vZ3MvZ3Nvcmdhbml6YXRpb252YWxnMi5jcmwwgZYGCCsG\r\nAQUFBwEBBIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNp\r\nZ24uY29tL2NhY2VydC9nc29yZ2FuaXphdGlvbnZhbGcyLmNydDA7BggrBgEFBQcw\r\nAYYvaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzb3JnYW5pemF0aW9udmFs\r\nZzIwHQYDVR0OBBYEFHbgHqTLsXDt7uMRyE62rnDEfLn9MB8GA1UdIwQYMBaAFF1G\r\nso3ES3Qcu+31c7Y6tziPdZ5+MA0GCSqGSIb3DQEBBQUAA4IBAQByy1+3N6ZRVooI\r\nxqw8Ng+UFz0g7UHkbPEnvTu1uxJ2AojFuP/P1PAk+/6uMRvpPlWg/5uqmOIWxKxJ\r\nLo6xSbkDf4LN+KYwes3XSuPyziZ4QbPnehHhZ0377iiA8fpRJADg9NWKCRHh5aAd\r\ne9QvJUW/GgYkBN+F4yYc2jIjR3Rehv4JYOKS3iXO9OoHsDS2CcCFaS2imgQVfYLg\r\nslBwT/A08PCOhW5huiluSmih7x5Qf7sFDv8jineu6ehKzi8pKnOq4k8G4QiWn38Y\r\nCeiBkkwFOwj7T3M/ITiiSS9DHDGeokj16eBi83Zx3YYiJ9YZvnQ+4GvqJ5eJJ6pR\r\nKKvemr+m\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
+ }
+ },
+ gmx: {
+ imap: {
+ host: 'imap.gmx.net',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIHUDCCBjigAwIBAgIIM52e2Oc5J8kwDQYJKoZIhvcNAQEFBQAwgckxCzAJBgNV\r\nBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJIMR8w\r\nHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcxDjAM\r\nBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRlcmUg\r\nSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNzIERF\r\nLTEwHhcNMTMxMTEyMTAxNzMxWhcNMTYxMTE3MjM1OTU5WjCBnTELMAkGA1UEBhMC\r\nREUxHjAcBgNVBAoMFTEmMSBNYWlsICYgTWVkaWEgR21iSDEdMBsGA1UECBMUUmhp\r\nbmVsYW5kLVBhbGF0aW5hdGUxEjAQBgNVBAcTCU1vbnRhYmF1cjEkMCIGCSqGSIb3\r\nDQEJARYVc2VydmVyLWNlcnRzQDF1bmQxLmRlMRUwEwYDVQQDEwxpbWFwLmdteC5u\r\nZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHP3QN1ztX5m8LaC9m\r\nt2nrcLBEfxb61FQCieXW4OV/D5HEy7vgQIAeS+pg2/9ClawprQFbLUa46owUcJuq\r\no2SaefsYqjRhIP/tPeyGRJQmfnyCRRoHIYno57/bz2qmHjzvkqEUMvNGVVej7BJv\r\nGukNKPXYicodkRodF3EicTPnGitGeXOsAxyPuCPIsBPAMuuuBzKenS7nj+yseSGe\r\nkM7/kjtNgbjDyBXi2BvoUS/U+Gm9p1lq0ymT9fhGj/k9/Qz312GHYxfZB1bhL0pk\r\nadF25P8fTIy5tKMWqJfgCF+eaOwgkYecxeCcrt2E3D8ThLvmkBRrXsTT51ZzD7sp\r\n7hPpAgMBAAGjggNkMIIDYDAfBgNVHSMEGDAWgBRiTxPONmeEzRn8oE8Zi+8VVAEy\r\nHDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB\r\nMB0GA1UdDgQWBBRfb2gYyD6V+oBN2Ii5WQj0AddemjBZBgNVHSAEUjBQMEQGCSsG\r\nAQQBvUcNAjA3MDUGCCsGAQUFBwIBFilodHRwOi8vd3d3LnRlbGVzZWMuZGUvc2Vy\r\ndmVycGFzcy9jcHMuaHRtbDAIBgZngQwBAgIwggEhBgNVHR8EggEYMIIBFDBFoEOg\r\nQYY/aHR0cDovL2NybC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvcmwvVGVsZVNlY19T\r\nZXJ2ZXJQYXNzX0RFLTEuY3JsMIHKoIHHoIHEhoHBbGRhcDovL2xkYXAuc2VydmVy\r\ncGFzcy50ZWxlc2VjLmRlL2NuPVRlbGVTZWMlMjBTZXJ2ZXJQYXNzJTIwREUtMSxv\r\ndT1ULVN5c3RlbXMlMjBUcnVzdCUyMENlbnRlcixvPVQtU3lzdGVtcyUyMEludGVy\r\nbmF0aW9uYWwlMjBHbWJILGM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9ubGlzdD9i\r\nYXNlP2NlcnRpZmljYXRlUmV2b2NhdGlvbmxpc3Q9KjCCATkGCCsGAQUFBwEBBIIB\r\nKzCCAScwMwYIKwYBBQUHMAGGJ2h0dHA6Ly9vY3NwLnNlcnZlcnBhc3MudGVsZXNl\r\nYy5kZS9vY3NwcjBMBggrBgEFBQcwAoZAaHR0cDovL2NybC5zZXJ2ZXJwYXNzLnRl\r\nbGVzZWMuZGUvY3J0L1RlbGVTZWNfU2VydmVyUGFzc19ERS0xLmNlcjCBoQYIKwYB\r\nBQUHMAKGgZRsZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvY249VGVs\r\nZVNlYyUyMFNlcnZlclBhc3MlMjBERS0xLG91PVQtU3lzdGVtcyUyMFRydXN0JTIw\r\nQ2VudGVyLG89VC1TeXN0ZW1zJTIwSW50ZXJuYXRpb25hbCUyMEdtYkgsYz1kZT9j\r\nQUNlcnRpZmljYXRlMAwGA1UdEwEB/wQCMAAwJAYDVR0RBB0wG4IMaW1hcC5nbXgu\r\nbmV0ggtpbWFwLmdteC5kZTANBgkqhkiG9w0BAQUFAAOCAQEADl442s2ouynDNEzl\r\nBPzhCxjp47TmKzgzrCGh1AH3+UOkw54mYU65UaY9cJ51jgOu+pjNB4KxVfcqyG5O\r\nJcowS09ZtZ+khb1OkzXAAbEqNj0oyH/1K550d5Ir5VbXF0ZdVKVTzEFRyjvUt5NJ\r\n/b6Q2bbY/sPm8QiK9SPaYkO5/3J1KB0u7PkqqfOhZ9UJE6mIN66T2bpFmAwle3zL\r\n6+L/VwYSgUNs/w2l6xWlYP3pFFaT12TO43Q057I3vP7yCt3QE/VLDpdQOQ3H0oy2\r\nJQGPJLFby9MPYNkmEmwjh4e95TAY4ZkZMe08ix0J1Smy8DwjTz6SXqYC+EC/PQlh\r\nE0UHxA==\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
},
- checkOutboxInterval: 5000,
- iconPath: '/img/icon-128-chrome.png',
- verificationUrl: '/verify/',
- verificationUuidLength: 36,
- dbVersion: 5,
- appVersion: appVersion,
- outboxMailboxPath: 'OUTBOX',
- outboxMailboxName: 'Outbox',
- outboxMailboxType: 'Outbox',
- connDocTimeout: 5000,
- imapUpdateBatchSize: 25
- };
-
- /**
- * Strings are maintained here
- */
- app.string = {
- fallbackSubject: '(no subject)',
- invitationSubject: 'Invitation to a private conversation',
- invitationMessage: 'Hi,\n\nI use Whiteout Mail to send and receive encrypted email. I would like to exchange encrypted messages with you as well.\n\nPlease install the Whiteout Mail application. This application makes it easy to read and write messages securely with PGP encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io\n\n',
- signature: '\n\n\n--\nSent from Whiteout Mail - https://whiteout.io\n\nMy PGP key: ',
- webSite: 'http://whiteout.io',
- verificationSubject: '[whiteout] New public key uploaded',
- sendBtnClear: 'Send',
- sendBtnSecure: 'Send securely',
- updatePublicKeyTitle: 'Public Key Updated',
- updatePublicKeyMsgNewKey: '{0} updated his key and may not be able to read encrypted messages sent with his old key. Update the key?',
- updatePublicKeyMsgRemovedKey: '{0} revoked his key and may no longer be able to read encrypted messages. Remove the key?',
- updatePublicKeyPosBtn: 'Yes',
- updatePublicKeyNegBtn: 'No',
- outdatedCertificateTitle: 'Warning',
- outdatedCertificateMessage: 'The SSL certificate for the mail server {0} changed, the connection was refused.',
- updateCertificateTitle: 'Warning',
- updateCertificateMessage: 'The SSL certificate for the mail server {0} changed. Do you want to proceed?',
- updateCertificatePosBtn: 'Yes',
- updateCertificateNegBtn: 'No',
- certificateFaqLink: 'https://github.com/whiteout-io/mail-html5/wiki/FAQ#what-does-the-ssl-certificate-for-the-mail-server--changed-mean',
- bugReportTitle: 'Report a bug',
- bugReportSubject: '[Bug] I want to report a bug',
- bugReportBody: 'Steps to reproduce\n1. \n2. \n3. \n\nWhat happens?\n\n\nWhat do you expect to happen instead?\n\n\n\n== PLEASE DONT PUT ANY KEYS HERE! ==\n\n\n## Log\n\nBelow is the log. It includes your interactions with your email provider in an anonymized way from the point where you started the app for the last time. Any information provided by you will be used for the porpose of locating and fixing the bug you reported. It will be deleted subsequently. However, you can edit this log and/or remove log data in the event that something would show up.\n\n',
- supportAddress: 'mail.support@whiteout.io',
- connDocOffline: 'It appears that you are offline. Please retry when you are online.',
- connDocTlsWrongCert: 'A connection to {0} was rejected because the TLS certificate is invalid. Please have a look at the FAQ for information on how to fix this error.',
- connDocHostUnreachable: 'We could not establish a connection to {0}. Please check the server settings!',
- connDocHostTimeout: 'We could not establish a connection to {0} within {1} ms. Please check the server settings and encryption mode!',
- connDocAuthRejected: 'Your credentials for {0} were rejected. Please check your username and password!',
- connDocNoInbox: 'We could not detect an IMAP inbox folder on {0}. Please have a look at the FAQ for information on how to fix this error.',
- connDocGenericError: 'There was an error connecting to {0}: {1}'
- };
+ smtp: {
+ host: 'mail.gmx.net',
+ port: 587,
+ secure: false,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIHbDCCBlSgAwIBAgIJAJ74Ek9UaA0TMA0GCSqGSIb3DQEBBQUAMIHJMQswCQYD\r\nVQQGEwJERTElMCMGA1UEChMcVC1TeXN0ZW1zIEludGVybmF0aW9uYWwgR21iSDEf\r\nMB0GA1UECxMWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEMMAoGA1UECBMDTlJXMQ4w\r\nDAYDVQQREwU1NzI1MDEQMA4GA1UEBxMHTmV0cGhlbjEgMB4GA1UECRMXVW50ZXJl\r\nIEluZHVzdHJpZXN0ci4gMjAxIDAeBgNVBAMTF1RlbGVTZWMgU2VydmVyUGFzcyBE\r\nRS0xMB4XDTEzMTExMjEwMTY0N1oXDTE2MTExNzIzNTk1OVowgZ0xCzAJBgNVBAYT\r\nAkRFMR4wHAYDVQQKDBUxJjEgTWFpbCAmIE1lZGlhIEdtYkgxHTAbBgNVBAgTFFJo\r\naW5lbGFuZC1QYWxhdGluYXRlMRIwEAYDVQQHEwlNb250YWJhdXIxJDAiBgkqhkiG\r\n9w0BCQEWFXNlcnZlci1jZXJ0c0AxdW5kMS5kZTEVMBMGA1UEAxMMbWFpbC5nbXgu\r\nbmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsEUYppbJXUpQELIL\r\nETAFUwreDfSmbyi9gJPUqquogROHEoRV+bBFZ2YCiHgLU8AggcLmM74HAQMFt8F5\r\neS2OyuEar3E3tNW5XFiI1QblTtY3B7o1coKyq/i+tV3b1jGq4+1aJeeD3UpcraBm\r\nk2XuQgQ6WAeY+XCYyI/OzZ56ZjQ17LHMMI0ayu7SSV+VBpG9loC9E5A82iVtZsqo\r\nSaUZpZf/xICpUgNJ+RlalSsoE6FdCywE/gEEmkpAUh+Mv0WvHITk6aqtMFWex8tE\r\n8cwJGQbmJGt9x8BExbhMY6uQ+HsnsDCPCMVh5JGKx7/e+qyxtHYGChOeI16m2+MT\r\nz47jSQIDAQABo4IDfzCCA3swHwYDVR0jBBgwFoAUYk8TzjZnhM0Z/KBPGYvvFVQB\r\nMhwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\r\nATAdBgNVHQ4EFgQUH8mLfxsd5FEh9M+3t3rP6qLiFTEwWQYDVR0gBFIwUDBEBgkr\r\nBgEEAb1HDQIwNzA1BggrBgEFBQcCARYpaHR0cDovL3d3dy50ZWxlc2VjLmRlL3Nl\r\ncnZlcnBhc3MvY3BzLmh0bWwwCAYGZ4EMAQICMIIBIQYDVR0fBIIBGDCCARQwRaBD\r\noEGGP2h0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL1RlbGVTZWNf\r\nU2VydmVyUGFzc19ERS0xLmNybDCByqCBx6CBxIaBwWxkYXA6Ly9sZGFwLnNlcnZl\r\ncnBhc3MudGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2VydmVyUGFzcyUyMERFLTEs\r\nb3U9VC1TeXN0ZW1zJTIwVHJ1c3QlMjBDZW50ZXIsbz1ULVN5c3RlbXMlMjBJbnRl\r\ncm5hdGlvbmFsJTIwR21iSCxjPWRlP2NlcnRpZmljYXRlUmV2b2NhdGlvbmxpc3Q/\r\nYmFzZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25saXN0PSowggE5BggrBgEFBQcBAQSC\r\nASswggEnMDMGCCsGAQUFBzABhidodHRwOi8vb2NzcC5zZXJ2ZXJwYXNzLnRlbGVz\r\nZWMuZGUvb2NzcHIwTAYIKwYBBQUHMAKGQGh0dHA6Ly9jcmwuc2VydmVycGFzcy50\r\nZWxlc2VjLmRlL2NydC9UZWxlU2VjX1NlcnZlclBhc3NfREUtMS5jZXIwgaEGCCsG\r\nAQUFBzAChoGUbGRhcDovL2xkYXAuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NuPVRl\r\nbGVTZWMlMjBTZXJ2ZXJQYXNzJTIwREUtMSxvdT1ULVN5c3RlbXMlMjBUcnVzdCUy\r\nMENlbnRlcixvPVQtU3lzdGVtcyUyMEludGVybmF0aW9uYWwlMjBHbWJILGM9ZGU/\r\nY0FDZXJ0aWZpY2F0ZTAMBgNVHRMBAf8EAjAAMD8GA1UdEQQ4MDaCDG1haWwuZ214\r\nLm5ldIILbWFpbC5nbXguZGWCDHNtdHAuZ214Lm5ldIILc210cC5nbXguZGUwDQYJ\r\nKoZIhvcNAQEFBQADggEBAJ5SKsBXoOTO0ztsFh8RVd/iu6sijEMpKVF+/cs74TZN\r\nK1QWIz8Ay1f3SUPWXTvkmvayUXWGtxZfYoRIrx3feWBdUozJxe0wz1O3tDQOQgRX\r\nnkcwk7nibTUmW2rk5AIwV0jzOHtIbAGjSdc6my0543e7dVkhcuoCOC+g2NmD+pHF\r\ni1KpmqTLecDlFvprIZUJ23AT1uTnuXYg/tFHeDn3ga00Gce82xZQJelRirJs01SR\r\nDGEBaPXBjJVJNoAP/qEy3jQNRWo5TbSgwn3DTR81FJvltmf0c+zlt4fmcpjpr5ni\r\nFvK7L0rZQL5MOGHPpgRIukEBZCowYr3OYpZYBEaB94I=\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
+ }
+ },
+ webde: {
+ imap: {
+ host: 'imap.web.de',
+ port: 993,
+ secure: true,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIHUjCCBjqgAwIBAgIIHvqUOScyxYUwDQYJKoZIhvcNAQEFBQAwgckxCzAJBgNV\r\nBAYTAkRFMSUwIwYDVQQKExxULVN5c3RlbXMgSW50ZXJuYXRpb25hbCBHbWJIMR8w\r\nHQYDVQQLExZULVN5c3RlbXMgVHJ1c3QgQ2VudGVyMQwwCgYDVQQIEwNOUlcxDjAM\r\nBgNVBBETBTU3MjUwMRAwDgYDVQQHEwdOZXRwaGVuMSAwHgYDVQQJExdVbnRlcmUg\r\nSW5kdXN0cmllc3RyLiAyMDEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNzIERF\r\nLTEwHhcNMTMwODIxMDgzMTE2WhcNMTYwODI2MjM1OTU5WjCBrTELMAkGA1UEBhMC\r\nREUxHjAcBgNVBAoMFTEmMSBNYWlsICYgTWVkaWEgR21iSDEPMA0GA1UECxMGV0VC\r\nLkRFMR0wGwYDVQQIExRSaGluZWxhbmQtUGFsYXRpbmF0ZTESMBAGA1UEBxMJTW9u\r\ndGFiYXVyMSQwIgYJKoZIhvcNAQkBFhVzZXJ2ZXItY2VydHNAMXVuZDEuZGUxFDAS\r\nBgNVBAMTC2ltYXAud2ViLmRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\r\nAQEA5dvpcnYczFs9GANTYN5N3mP6ATFVm7P4nYhRIQMj/YssSjmbrOPIEbe12JNC\r\nRO9CI7Z4Dnk42BM5TiH+QKGpcfnitofOv4gKPjwCMcPDHfY152/+YDaiyU/md2Hg\r\n/WrZ/50KwC8Sw1tZkYDXWB0zeJkfPdS2r4ATNrpMR0fYcG08+elz5T2SWNg+c1xL\r\nKFdCh33wZLkijOfW0HA164QjXaLPBjxa+GyZFY19ywOQ85KdFVVLmGUrLz8n4ZLc\r\n7K6KUuzYttnUuVxctFauQ4DRHE/CfUvvNHHgn5d+A2XS7jNUgmUb0gjzy3OtlTP3\r\ngM4ostVufmnlS7qqFDR7A3v4lQIDAQABo4IDVjCCA1IwHwYDVR0jBBgwFoAUYk8T\r\nzjZnhM0Z/KBPGYvvFVQBMhwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsG\r\nAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4EFgQUDH66P/Y4NlKGphPniIzmutEI9ocw\r\nWQYDVR0gBFIwUDBEBgkrBgEEAb1HDQIwNzA1BggrBgEFBQcCARYpaHR0cDovL3d3\r\ndy50ZWxlc2VjLmRlL3NlcnZlcnBhc3MvY3BzLmh0bWwwCAYGZ4EMAQICMIIBIQYD\r\nVR0fBIIBGDCCARQwRaBDoEGGP2h0dHA6Ly9jcmwuc2VydmVycGFzcy50ZWxlc2Vj\r\nLmRlL3JsL1RlbGVTZWNfU2VydmVyUGFzc19ERS0xLmNybDCByqCBx6CBxIaBwWxk\r\nYXA6Ly9sZGFwLnNlcnZlcnBhc3MudGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2Vy\r\ndmVyUGFzcyUyMERFLTEsb3U9VC1TeXN0ZW1zJTIwVHJ1c3QlMjBDZW50ZXIsbz1U\r\nLVN5c3RlbXMlMjBJbnRlcm5hdGlvbmFsJTIwR21iSCxjPWRlP2NlcnRpZmljYXRl\r\nUmV2b2NhdGlvbmxpc3Q/YmFzZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25saXN0PSow\r\nggE5BggrBgEFBQcBAQSCASswggEnMDMGCCsGAQUFBzABhidodHRwOi8vb2NzcC5z\r\nZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvb2NzcHIwTAYIKwYBBQUHMAKGQGh0dHA6Ly9j\r\ncmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL2NydC9UZWxlU2VjX1NlcnZlclBhc3Nf\r\nREUtMS5jZXIwgaEGCCsGAQUFBzAChoGUbGRhcDovL2xkYXAuc2VydmVycGFzcy50\r\nZWxlc2VjLmRlL2NuPVRlbGVTZWMlMjBTZXJ2ZXJQYXNzJTIwREUtMSxvdT1ULVN5\r\nc3RlbXMlMjBUcnVzdCUyMENlbnRlcixvPVQtU3lzdGVtcyUyMEludGVybmF0aW9u\r\nYWwlMjBHbWJILGM9ZGU/Y0FDZXJ0aWZpY2F0ZTAMBgNVHRMBAf8EAjAAMBYGA1Ud\r\nEQQPMA2CC2ltYXAud2ViLmRlMA0GCSqGSIb3DQEBBQUAA4IBAQAp7MQjjOWQ0M7N\r\n21GrPDfWSMR3eJnuMs37I9G2t9i99w7xKtmoVBPyYMORL1zRHn/DEguo4j5ua7CH\r\nrKLh9Sd1wDKqVWGFxvmP4f/mvEx5YVI68mg+M2VQf/h58IXTTZRbUcsv3HVeruI6\r\npgQNUsEQqRVJmrgT/iPd98RhhzBqef6Wfrt3Ns6N835egphxUVcVj/v/PqBCZKQb\r\nNl5QsoaHDqh3XC+Og2awOGvWHUzxUKEqkP5nsMs2YjfOtcQRtxdislQAfRktuUBA\r\nWMZAlvoVF/CIyFvcUH11KNur7HfK5PptvtdvLQaF2c+lN+LGP6D+nbTLqAo1v09o\r\nnZpHbQOt\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
+ },
+ smtp: {
+ host: 'smtp.web.de',
+ port: 587,
+ secure: false,
+ ca: '-----BEGIN CERTIFICATE-----\r\nMIIHUzCCBjugAwIBAgIJAKaEwtMgQ2s5MA0GCSqGSIb3DQEBBQUAMIHJMQswCQYD\r\nVQQGEwJERTElMCMGA1UEChMcVC1TeXN0ZW1zIEludGVybmF0aW9uYWwgR21iSDEf\r\nMB0GA1UECxMWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEMMAoGA1UECBMDTlJXMQ4w\r\nDAYDVQQREwU1NzI1MDEQMA4GA1UEBxMHTmV0cGhlbjEgMB4GA1UECRMXVW50ZXJl\r\nIEluZHVzdHJpZXN0ci4gMjAxIDAeBgNVBAMTF1RlbGVTZWMgU2VydmVyUGFzcyBE\r\nRS0xMB4XDTEzMDgyMTA4MzU1MVoXDTE2MDgyNjIzNTk1OVowga0xCzAJBgNVBAYT\r\nAkRFMR4wHAYDVQQKDBUxJjEgTWFpbCAmIE1lZGlhIEdtYkgxDzANBgNVBAsTBldF\r\nQi5ERTEdMBsGA1UECBMUUmhpbmVsYW5kLVBhbGF0aW5hdGUxEjAQBgNVBAcTCU1v\r\nbnRhYmF1cjEkMCIGCSqGSIb3DQEJARYVc2VydmVyLWNlcnRzQDF1bmQxLmRlMRQw\r\nEgYDVQQDEwtzbXRwLndlYi5kZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\r\nggEBAL1WfyFqmifaEr6h9yntJKs33fnEVu0pQqS5RV9rnQU0E/cJYJ9RJOoTjhpE\r\nkT1LW8DyTM5vUzpgtFHQM0BOO6jOeZXUYNUaopK3yO4l/cpiitigtk9ZnWfKzbU3\r\n9hlhf+YwUUvoqjUA8I6fSu+VNPNlOBvamo18oHljXAPltL9oiwAxvTLNktBMy4T9\r\njxU1DeGoPbJKGwV7zIBQ2qUHuLkMvy5/H39t79Tih+zfzgfY/xIUfdmPNY9dK8ZY\r\nAtyF/RiUS199pd9dV4Vwh6JLvtNlWchBnKVhragLCGbkjnvUXmS1BPrclLR23s1v\r\nMehgOD2WhXl8PoqrOPb6y+lgMlECAwEAAaOCA1YwggNSMB8GA1UdIwQYMBaAFGJP\r\nE842Z4TNGfygTxmL7xVUATIcMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggr\r\nBgEFBQcDAgYIKwYBBQUHAwEwHQYDVR0OBBYEFAUuppozNCv2UzMV5p6CTpkEhsRS\r\nMFkGA1UdIARSMFAwRAYJKwYBBAG9Rw0CMDcwNQYIKwYBBQUHAgEWKWh0dHA6Ly93\r\nd3cudGVsZXNlYy5kZS9zZXJ2ZXJwYXNzL2Nwcy5odG1sMAgGBmeBDAECAjCCASEG\r\nA1UdHwSCARgwggEUMEWgQ6BBhj9odHRwOi8vY3JsLnNlcnZlcnBhc3MudGVsZXNl\r\nYy5kZS9ybC9UZWxlU2VjX1NlcnZlclBhc3NfREUtMS5jcmwwgcqggceggcSGgcFs\r\nZGFwOi8vbGRhcC5zZXJ2ZXJwYXNzLnRlbGVzZWMuZGUvY249VGVsZVNlYyUyMFNl\r\ncnZlclBhc3MlMjBERS0xLG91PVQtU3lzdGVtcyUyMFRydXN0JTIwQ2VudGVyLG89\r\nVC1TeXN0ZW1zJTIwSW50ZXJuYXRpb25hbCUyMEdtYkgsYz1kZT9jZXJ0aWZpY2F0\r\nZVJldm9jYXRpb25saXN0P2Jhc2U/Y2VydGlmaWNhdGVSZXZvY2F0aW9ubGlzdD0q\r\nMIIBOQYIKwYBBQUHAQEEggErMIIBJzAzBggrBgEFBQcwAYYnaHR0cDovL29jc3Au\r\nc2VydmVycGFzcy50ZWxlc2VjLmRlL29jc3ByMEwGCCsGAQUFBzAChkBodHRwOi8v\r\nY3JsLnNlcnZlcnBhc3MudGVsZXNlYy5kZS9jcnQvVGVsZVNlY19TZXJ2ZXJQYXNz\r\nX0RFLTEuY2VyMIGhBggrBgEFBQcwAoaBlGxkYXA6Ly9sZGFwLnNlcnZlcnBhc3Mu\r\ndGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2VydmVyUGFzcyUyMERFLTEsb3U9VC1T\r\neXN0ZW1zJTIwVHJ1c3QlMjBDZW50ZXIsbz1ULVN5c3RlbXMlMjBJbnRlcm5hdGlv\r\nbmFsJTIwR21iSCxjPWRlP2NBQ2VydGlmaWNhdGUwDAYDVR0TAQH/BAIwADAWBgNV\r\nHREEDzANggtzbXRwLndlYi5kZTANBgkqhkiG9w0BAQUFAAOCAQEAGFtJxVxWrURy\r\nFfR4UfmW+N1cZZx9sfC5jolV8LGje87DgbWdqu5TRL9FoQ1pwOTbM9mc3yWSoIbU\r\nx6E+rziJK+SFGMIy+Lt13P9M9Oc8JzVHoVEAgqlEeO6OYxrGE6SaSjZODJxPaEtU\r\nzEAKf0HVJQoGaU6fD+/8l3yhksAlsF/L85nP+KcZtoancOkJWE0GQMZp7pdLU0Ou\r\nFUQoAcqMIyHQfDqJ5iwvx/9C7jmy3Nvw9tXdPrdn2O7ywrnFeJuT2xiorZzg6ezn\r\nUlc/sMvd/LPX0f60pSQr9tkZgU4f8Jvx9EvPUCFTRXlXqkBIhgJhgCadZC+wKB1P\r\neQMS8rksXw==\r\n-----END CERTIFICATE-----',
+ pinned: true,
+ ignoreTLS: false
+ }
+ },
+ checkOutboxInterval: 5000,
+ iconPath: '/img/icon-128-chrome.png',
+ verificationUrl: '/verify/',
+ verificationUuidLength: 36,
+ dbVersion: 5,
+ appVersion: appVersion,
+ outboxMailboxPath: 'OUTBOX',
+ outboxMailboxName: 'Outbox',
+ outboxMailboxType: 'Outbox',
+ connDocTimeout: 5000,
+ imapUpdateBatchSize: 25
+};
- return app;
-});
\ No newline at end of file
+/**
+ * Strings are maintained here
+ */
+exports.string = {
+ fallbackSubject: '(no subject)',
+ invitationSubject: 'Invitation to a private conversation',
+ invitationMessage: 'Hi,\n\nI use Whiteout Mail to send and receive encrypted email. I would like to exchange encrypted messages with you as well.\n\nPlease install the Whiteout Mail application. This application makes it easy to read and write messages securely with PGP encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io\n\n',
+ signature: '\n\n\n--\nSent from Whiteout Mail - https://whiteout.io\n\nMy PGP key: ',
+ webSite: 'http://whiteout.io',
+ verificationSubject: '[whiteout] New public key uploaded',
+ sendBtnClear: 'Send',
+ sendBtnSecure: 'Send securely',
+ updatePublicKeyTitle: 'Public Key Updated',
+ updatePublicKeyMsgNewKey: '{0} updated his key and may not be able to read encrypted messages sent with his old key. Update the key?',
+ updatePublicKeyMsgRemovedKey: '{0} revoked his key and may no longer be able to read encrypted messages. Remove the key?',
+ updatePublicKeyPosBtn: 'Yes',
+ updatePublicKeyNegBtn: 'No',
+ outdatedCertificateTitle: 'Warning',
+ outdatedCertificateMessage: 'The SSL certificate for the mail server {0} changed, the connection was refused.',
+ updateCertificateTitle: 'Warning',
+ updateCertificateMessage: 'The SSL certificate for the mail server {0} changed. Do you want to proceed?',
+ updateCertificatePosBtn: 'Yes',
+ updateCertificateNegBtn: 'No',
+ certificateFaqLink: 'https://github.com/whiteout-io/mail-html5/wiki/FAQ#what-does-the-ssl-certificate-for-the-mail-server--changed-mean',
+ bugReportTitle: 'Report a bug',
+ bugReportSubject: '[Bug] I want to report a bug',
+ bugReportBody: 'Steps to reproduce\n1. \n2. \n3. \n\nWhat happens?\n\n\nWhat do you expect to happen instead?\n\n\n\n== PLEASE DONT PUT ANY KEYS HERE! ==\n\n\n## Log\n\nBelow is the log. It includes your interactions with your email provider in an anonymized way from the point where you started the app for the last time. Any information provided by you will be used for the porpose of locating and fixing the bug you reported. It will be deleted subsequently. However, you can edit this log and/or remove log data in the event that something would show up.\n\n',
+ supportAddress: 'mail.support@whiteout.io',
+ connDocOffline: 'It appears that you are offline. Please retry when you are online.',
+ connDocTlsWrongCert: 'A connection to {0} was rejected because the TLS certificate is invalid. Please have a look at the FAQ for information on how to fix this error.',
+ connDocHostUnreachable: 'We could not establish a connection to {0}. Please check the server settings!',
+ connDocHostTimeout: 'We could not establish a connection to {0} within {1} ms. Please check the server settings and encryption mode!',
+ connDocAuthRejected: 'Your credentials for {0} were rejected. Please check your username and password!',
+ connDocNoInbox: 'We could not detect an IMAP inbox folder on {0}. Please have a look at the FAQ for information on how to fix this error.',
+ connDocGenericError: 'There was an error connecting to {0}: {1}'
+};
\ No newline at end of file
diff --git a/src/js/app-controller.js b/src/js/app-controller.js
index ba358e0..96bf770 100644
--- a/src/js/app-controller.js
+++ b/src/js/app-controller.js
@@ -1,271 +1,271 @@
/**
* The main application controller
*/
-define(function(require) {
- 'use strict';
-
- var axe = require('axe'),
- Auth = require('js/bo/auth'),
- PGP = require('js/crypto/pgp'),
- PgpMailer = require('pgpmailer'),
- OAuth = require('js/util/oauth'),
- PgpBuilder = require('pgpbuilder'),
- OutboxBO = require('js/bo/outbox'),
- mailreader = require('mailreader'),
- ImapClient = require('imap-client'),
- Crypto = require('js/crypto/crypto'),
- RestDAO = require('js/dao/rest-dao'),
- appConfig = require('js/app-config'),
- EmailDAO = require('js/dao/email-dao'),
- AdminDao = require('js/dao/admin-dao'),
- KeychainDAO = require('js/dao/keychain-dao'),
- PublicKeyDAO = require('js/dao/publickey-dao'),
- LawnchairDAO = require('js/dao/lawnchair-dao'),
- PrivateKeyDAO = require('js/dao/privatekey-dao'),
- InvitationDAO = require('js/dao/invitation-dao'),
- DeviceStorageDAO = require('js/dao/devicestorage-dao'),
- ConnectionDoctor = require('js/util/connection-doctor'),
- UpdateHandler = require('js/util/update/update-handler'),
- config = appConfig.config,
- str = appConfig.string;
-
- var self = {};
-
- /**
- * Start the application.
- */
- self.start = function(options, callback) {
- if (self.started) {
- return callback();
- }
- self.started = true;
- self.onError = options.onError;
-
- // are we running in a cordova app or in a browser environment?
- if (window.cordova) {
- // wait for 'deviceready' event to make sure plugins are loaded
- axe.debug('Assuming Cordova environment...');
- document.addEventListener("deviceready", onDeviceReady, false);
- } else {
- // No need to wait on events... just start the app
- axe.debug('Assuming Browser environment...');
- onDeviceReady();
- }
+'use strict';
+
+var axe = require('axe-logger'),
+ Auth = require('./bo/auth'),
+ PGP = require('./crypto/pgp'),
+ PgpMailer = require('pgpmailer'),
+ OAuth = require('./util/oauth'),
+ PgpBuilder = require('pgpbuilder'),
+ OutboxBO = require('./bo/outbox'),
+ mailreader = require('mailreader'),
+ ImapClient = require('imap-client'),
+ Crypto = require('./crypto/crypto'),
+ RestDAO = require('./dao/rest-dao'),
+ appConfig = require('./app-config'),
+ EmailDAO = require('./dao/email-dao'),
+ AdminDao = require('./dao/admin-dao'),
+ KeychainDAO = require('./dao/keychain-dao'),
+ PublicKeyDAO = require('./dao/publickey-dao'),
+ LawnchairDAO = require('./dao/lawnchair-dao'),
+ PrivateKeyDAO = require('./dao/privatekey-dao'),
+ InvitationDAO = require('./dao/invitation-dao'),
+ DeviceStorageDAO = require('./dao/devicestorage-dao'),
+ ConnectionDoctor = require('./util/connection-doctor'),
+ UpdateHandler = require('./util/update/update-handler'),
+ config = appConfig.config,
+ str = appConfig.string;
+
+var ctrl = {};
+
+/**
+ * Start the application.
+ */
+ctrl.start = function(options, callback) {
+ if (ctrl.started) {
+ return callback();
+ }
+
+ ctrl.started = true;
+ ctrl.onError = options.onError;
+
+ // are we running in a cordova app or in a browser environment?
+ if (window.cordova) {
+ // wait for 'deviceready' event to make sure plugins are loaded
+ axe.debug('Assuming Cordova environment...');
+ document.addEventListener("deviceready", onDeviceReady, false);
+ } else {
+ // No need to wait on events... just start the app
+ axe.debug('Assuming Browser environment...');
+ onDeviceReady();
+ }
+
+ function onDeviceReady() {
+ axe.debug('Starting app.');
+
+ ctrl.buildModules();
+
+ // Handle offline and online gracefully
+ window.addEventListener('online', ctrl.onConnect.bind(ctrl, ctrl.onError));
+ window.addEventListener('offline', ctrl.onDisconnect.bind(ctrl));
+
+ ctrl._appConfigStore.init('app-config', callback);
+ }
+};
+
+/**
+ * Initialize the dependency tree.
+ */
+ctrl.buildModules = function() {
+ var lawnchairDao, restDao, pubkeyDao, privkeyDao, crypto, emailDao, keychain, pgp, userStorage, pgpbuilder, oauth, appConfigStore, auth;
+
+ // start the mailreader's worker thread
+ mailreader.startWorker(config.workerPath + '/mailreader-parser-worker.min.js');
+
+ // init objects and inject dependencies
+ restDao = new RestDAO();
+ lawnchairDao = new LawnchairDAO();
+ pubkeyDao = new PublicKeyDAO(restDao);
+ privkeyDao = new PrivateKeyDAO(new RestDAO(config.privkeyServerUrl));
+ oauth = new OAuth(new RestDAO('https://www.googleapis.com'));
+
+ crypto = new Crypto();
+ ctrl._pgp = pgp = new PGP();
+ ctrl._keychain = keychain = new KeychainDAO(lawnchairDao, pubkeyDao, privkeyDao, crypto, pgp);
+ keychain.requestPermissionForKeyUpdate = function(params, callback) {
+ var message = params.newKey ? str.updatePublicKeyMsgNewKey : str.updatePublicKeyMsgRemovedKey;
+ message = message.replace('{0}', params.userId);
+
+ ctrl.onError({
+ title: str.updatePublicKeyTitle,
+ message: message,
+ positiveBtnStr: str.updatePublicKeyPosBtn,
+ negativeBtnStr: str.updatePublicKeyNegBtn,
+ showNegativeBtn: true,
+ callback: callback
+ });
+ };
- function onDeviceReady() {
- axe.debug('Starting app.');
+ ctrl._appConfigStore = appConfigStore = new DeviceStorageDAO(new LawnchairDAO());
+ ctrl._auth = auth = new Auth(appConfigStore, oauth, pgp);
+ ctrl._userStorage = userStorage = new DeviceStorageDAO(lawnchairDao);
+ ctrl._invitationDao = new InvitationDAO(restDao);
+ ctrl._pgpbuilder = pgpbuilder = new PgpBuilder();
+ ctrl._emailDao = emailDao = new EmailDAO(keychain, pgp, userStorage, pgpbuilder, mailreader);
+ ctrl._outboxBo = new OutboxBO(emailDao, keychain, userStorage);
+ ctrl._updateHandler = new UpdateHandler(appConfigStore, userStorage, auth);
+ ctrl._adminDao = new AdminDao(new RestDAO(config.adminUrl));
+ ctrl._doctor = new ConnectionDoctor();
- self.buildModules();
+ emailDao.onError = ctrl.onError;
+};
- // Handle offline and online gracefully
- window.addEventListener('online', self.onConnect.bind(self, self.onError));
- window.addEventListener('offline', self.onDisconnect.bind(self));
+/**
+ * Calls runtime hooks to check if an app update is available.
+ */
+ctrl.checkForUpdate = function() {
+ ctrl._updateHandler.checkForUpdate(ctrl.onError);
+};
- self._appConfigStore.init('app-config', callback);
+/**
+ * Instanciate the mail email data access object and its dependencies. Login to imap on init.
+ */
+ctrl.init = function(options, callback) {
+ // init user's local database
+ ctrl._userStorage.init(options.emailAddress, function(err) {
+ if (err) {
+ callback(err);
+ return;
}
- };
- /**
- * Initialize the dependency tree.
- */
- self.buildModules = function() {
- var lawnchairDao, restDao, pubkeyDao, privkeyDao, crypto, emailDao, keychain, pgp, userStorage, pgpbuilder, oauth, appConfigStore, auth;
-
- // start the mailreader's worker thread
- mailreader.startWorker(config.workerPath + '/../lib/mailreader-parser-worker.js');
-
- // init objects and inject dependencies
- restDao = new RestDAO();
- lawnchairDao = new LawnchairDAO();
- pubkeyDao = new PublicKeyDAO(restDao);
- privkeyDao = new PrivateKeyDAO(new RestDAO(config.privkeyServerUrl));
- oauth = new OAuth(new RestDAO('https://www.googleapis.com'));
-
- crypto = new Crypto();
- self._pgp = pgp = new PGP();
- self._keychain = keychain = new KeychainDAO(lawnchairDao, pubkeyDao, privkeyDao, crypto, pgp);
- keychain.requestPermissionForKeyUpdate = function(params, callback) {
- var message = params.newKey ? str.updatePublicKeyMsgNewKey : str.updatePublicKeyMsgRemovedKey;
- message = message.replace('{0}', params.userId);
-
- self.onError({
- title: str.updatePublicKeyTitle,
- message: message,
- positiveBtnStr: str.updatePublicKeyPosBtn,
- negativeBtnStr: str.updatePublicKeyNegBtn,
- showNegativeBtn: true,
- callback: callback
- });
- };
+ // Migrate the databases if necessary
+ ctrl._updateHandler.update(onUpdate);
+ });
- self._appConfigStore = appConfigStore = new DeviceStorageDAO(new LawnchairDAO());
- self._auth = auth = new Auth(appConfigStore, oauth, pgp);
- self._userStorage = userStorage = new DeviceStorageDAO(lawnchairDao);
- self._invitationDao = new InvitationDAO(restDao);
- self._pgpbuilder = pgpbuilder = new PgpBuilder();
- self._emailDao = emailDao = new EmailDAO(keychain, pgp, userStorage, pgpbuilder, mailreader);
- self._outboxBo = new OutboxBO(emailDao, keychain, userStorage);
- self._updateHandler = new UpdateHandler(appConfigStore, userStorage, auth);
- self._adminDao = new AdminDao(new RestDAO(config.adminUrl));
- self._doctor = new ConnectionDoctor();
-
- emailDao.onError = self.onError;
- };
+ function onUpdate(err) {
+ if (err) {
+ callback({
+ errMsg: 'Update failed, please reinstall the app.',
+ err: err
+ });
+ return;
+ }
- /**
- * Calls runtime hooks to check if an app update is available.
- */
- self.checkForUpdate = function() {
- self._updateHandler.checkForUpdate(self.onError);
- };
+ // account information for the email dao
+ var account = {
+ realname: options.realname,
+ emailAddress: options.emailAddress,
+ asymKeySize: config.asymKeySize
+ };
- /**
- * Instanciate the mail email data access object and its dependencies. Login to imap on init.
- */
- self.init = function(options, callback) {
- // init user's local database
- self._userStorage.init(options.emailAddress, function(err) {
+ // init email dao
+ ctrl._emailDao.init({
+ account: account
+ }, function(err, keypair) {
if (err) {
callback(err);
return;
}
- // Migrate the databases if necessary
- self._updateHandler.update(onUpdate);
+ callback(null, keypair);
});
+ }
+};
- function onUpdate(err) {
- if (err) {
- callback({
- errMsg: 'Update failed, please reinstall the app.',
- err: err
- });
- return;
- }
+/**
+ * Check if the user agent is online.
+ */
+ctrl.isOnline = function() {
+ return navigator.onLine;
+};
- // account information for the email dao
- var account = {
- realname: options.realname,
- emailAddress: options.emailAddress,
- asymKeySize: config.asymKeySize
- };
-
- // init email dao
- self._emailDao.init({
- account: account
- }, function(err, keypair) {
- if (err) {
- callback(err);
- return;
- }
+/**
+ * Event handler that is called when the user agent goes offline.
+ */
+ctrl.onDisconnect = function() {
+ ctrl._emailDao.onDisconnect();
+};
- callback(null, keypair);
- });
+/**
+ * Log the current user out by clear the app config store and deleting instances of imap-client and pgp-mailer.
+ */
+ctrl.logout = function() {
+ // clear app config store
+ ctrl._auth.logout(function(err) {
+ if (err) {
+ ctrl.onError(err);
+ return;
}
- };
-
- /**
- * Check if the user agent is online.
- */
- self.isOnline = function() {
- return navigator.onLine;
- };
-
- /**
- * Event handler that is called when the user agent goes offline.
- */
- self.onDisconnect = function() {
- self._emailDao.onDisconnect();
- };
-
- /**
- * Log the current user out by clear the app config store and deleting instances of imap-client and pgp-mailer.
- */
- self.logout = function() {
- var self = this;
- // clear app config store
- self._auth.logout(function(err) {
+ // delete instance of imap-client and pgp-mailer
+ ctrl._emailDao.onDisconnect(function(err) {
if (err) {
- self.onError(err);
+ ctrl.onError(err);
return;
}
- // delete instance of imap-client and pgp-mailer
- self._emailDao.onDisconnect(function(err) {
- if (err) {
- self.onError(err);
- return;
- }
-
- // navigate to login
- window.location.href = '/';
- });
+ // navigate to login
+ window.location.href = '/';
});
- };
+ });
+};
- /**
- * Event that is called when the user agent goes online. This create new instances of the imap-client and pgp-mailer and connects to the mail server.
- */
- self.onConnect = function(callback) {
- if (!self.isOnline() || !self._emailDao || !self._emailDao._account) {
- // prevent connection infinite loop
- callback();
+/**
+ * Event that is called when the user agent goes online. This create new instances of the imap-client and pgp-mailer and connects to the mail server.
+ */
+ctrl.onConnect = function(callback) {
+ if (!ctrl.isOnline() || !ctrl._emailDao || !ctrl._emailDao._account) {
+ // prevent connection infinite loop
+ callback();
+ return;
+ }
+
+ ctrl._auth.getCredentials(function(err, credentials) {
+ if (err) {
+ callback(err);
return;
}
- self._auth.getCredentials(function(err, credentials) {
- if (err) {
- callback(err);
- return;
- }
+ initClients(credentials);
+ });
- initClients(credentials);
- });
+ function initClients(credentials) {
+ // add the maximum update batch size for imap folders to the imap configuration
+ credentials.imap.maxUpdateSize = config.imapUpdateBatchSize;
- function initClients(credentials) {
- // add the maximum update batch size for imap folders to the imap configuration
- credentials.imap.maxUpdateSize = config.imapUpdateBatchSize;
-
- var pgpMailer = new PgpMailer(credentials.smtp, self._pgpbuilder);
- var imapClient = new ImapClient(credentials.imap);
- imapClient.onError = onConnectionError;
- pgpMailer.onError = onConnectionError;
-
- // certificate update handling
- imapClient.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'imap', self.onConnect, self.onError);
- pgpMailer.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'smtp', self.onConnect, self.onError);
-
- // after-setup configuration depending on the provider:
- // gmail does not require you to upload to the sent items folder
- // after successful sending, whereas most other providers do
- self._emailDao.ignoreUploadOnSent = !!(config[self._auth.provider] && config[self._auth.provider].ignoreUploadOnSent);
-
- // connect to clients
- self._emailDao.onConnect({
- imapClient: imapClient,
- pgpMailer: pgpMailer
- }, callback);
- }
+ // tls socket worker path for multithreaded tls in non-native tls environments
+ credentials.imap.tlsWorkerPath = credentials.smtp.tlsWorkerPath = config.workerPath + '/tcp-socket-tls-worker.min.js';
- function onConnectionError(error) {
- axe.debug('Connection error. Attempting reconnect in ' + config.reconnectInterval + ' ms. Error: ' + (error.errMsg || error.message) + (error.stack ? ('\n' + error.stack) : ''));
-
- setTimeout(function() {
- axe.debug('Reconnecting...');
- // re-init client modules on error
- self.onConnect(function(err) {
- if (err) {
- axe.error('Reconnect attempt failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : ''));
- return;
- }
-
- axe.debug('Reconnect attempt complete.');
- });
- }, config.reconnectInterval);
- }
- };
+ var pgpMailer = new PgpMailer(credentials.smtp, ctrl._pgpbuilder);
+ var imapClient = new ImapClient(credentials.imap);
+ imapClient.onError = onConnectionError;
+ pgpMailer.onError = onConnectionError;
+
+ // certificate update handling
+ imapClient.onCert = ctrl._auth.handleCertificateUpdate.bind(ctrl._auth, 'imap', ctrl.onConnect, ctrl.onError);
+ pgpMailer.onCert = ctrl._auth.handleCertificateUpdate.bind(ctrl._auth, 'smtp', ctrl.onConnect, ctrl.onError);
+
+ // after-setup configuration depending on the provider:
+ // gmail does not require you to upload to the sent items folder
+ // after successful sending, whereas most other providers do
+ ctrl._emailDao.ignoreUploadOnSent = !!(config[ctrl._auth.provider] && config[ctrl._auth.provider].ignoreUploadOnSent);
+
+ // connect to clients
+ ctrl._emailDao.onConnect({
+ imapClient: imapClient,
+ pgpMailer: pgpMailer
+ }, callback);
+ }
+
+ function onConnectionError(error) {
+ axe.debug('Connection error. Attempting reconnect in ' + config.reconnectInterval + ' ms. Error: ' + (error.errMsg || error.message) + (error.stack ? ('\n' + error.stack) : ''));
+
+ setTimeout(function() {
+ axe.debug('Reconnecting...');
+ // re-init client modules on error
+ ctrl.onConnect(function(err) {
+ if (err) {
+ axe.error('Reconnect attempt failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : ''));
+ return;
+ }
+
+ axe.debug('Reconnect attempt complete.');
+ });
+ }, config.reconnectInterval);
+ }
+};
- return self;
-});
\ No newline at end of file
+module.exports = ctrl;
diff --git a/src/js/app.js b/src/js/app.js
index cfb3fd9..9b13e26 100644
--- a/src/js/app.js
+++ b/src/js/app.js
@@ -14,148 +14,104 @@ if (typeof window.applicationCache !== 'undefined') {
};
}
-// hey Angular, we're bootstrapping manually!
-window.name = 'NG_DEFER_BOOTSTRAP!';
+var DialogCtrl = require('./controller/dialog'),
+ PopoverCtrl = require('./controller/popover'),
+ AddAccountCtrl = require('./controller/add-account'),
+ AccountCtrl = require('./controller/account'),
+ SetPassphraseCtrl = require('./controller/set-passphrase'),
+ PrivateKeyUploadCtrl = require('./controller/privatekey-upload'),
+ ContactsCtrl = require('./controller/contacts'),
+ AboutCtrl = require('./controller/about'),
+ LoginCtrl = require('./controller/login'),
+ LoginInitialCtrl = require('./controller/login-initial'),
+ LoginNewDeviceCtrl = require('./controller/login-new-device'),
+ LoginExistingCtrl = require('./controller/login-existing'),
+ LoginPrivateKeyDownloadCtrl = require('./controller/login-privatekey-download'),
+ LoginSetCredentialsCtrl = require('./controller/login-set-credentials'),
+ MailListCtrl = require('./controller/mail-list'),
+ ReadCtrl = require('./controller/read'),
+ WriteCtrl = require('./controller/write'),
+ NavigationCtrl = require('./controller/navigation'),
+ errorUtil = require('./util/error'),
+ backButtonUtil = require('./util/backbutton-handler');
-requirejs([
- 'angular',
- 'js/controller/dialog',
- 'js/controller/popover',
- 'js/controller/add-account',
- 'js/controller/account',
- 'js/controller/set-passphrase',
- 'js/controller/privatekey-upload',
- 'js/controller/contacts',
- 'js/controller/about',
- 'js/controller/login',
- 'js/controller/login-initial',
- 'js/controller/login-new-device',
- 'js/controller/login-existing',
- 'js/controller/login-privatekey-download',
- 'js/controller/login-set-credentials',
- 'js/controller/mail-list',
- 'js/controller/read',
- 'js/controller/write',
- 'js/controller/navigation',
- 'js/crypto/util',
- 'js/util/error',
- 'js/util/backbutton-handler',
- 'fastclick',
- 'angularRoute',
- 'angularAnimate',
- 'ngInfiniteScroll',
+// init main angular module including dependencies
+var app = angular.module('mail', [
+ 'ngRoute',
+ 'ngAnimate',
+ 'navigation',
+ 'mail-list',
+ 'write',
+ 'read',
+ 'contacts',
+ 'login-new-device',
+ 'privatekey-upload',
+ 'popover',
+ 'infinite-scroll',
'ngTagsInput'
-], function(
- angular,
- DialogCtrl,
- PopoverCtrl,
- AddAccountCtrl,
- AccountCtrl,
- SetPassphraseCtrl,
- PrivateKeyUploadCtrl,
- ContactsCtrl,
- AboutCtrl,
- LoginCtrl,
- LoginInitialCtrl,
- LoginNewDeviceCtrl,
- LoginExistingCtrl,
- LoginPrivateKeyDownloadCtrl,
- LoginSetCredentialsCtrl,
- MailListCtrl,
- ReadCtrl,
- WriteCtrl,
- NavigationCtrl,
- util,
- errorUtil,
- backButtonUtil,
- FastClick
-) {
- // reset window.name
- window.name = util.UUID();
+]);
- // init main angular module including dependencies
- var app = angular.module('mail', [
- 'ngRoute',
- 'ngAnimate',
- 'navigation',
- 'mail-list',
- 'write',
- 'read',
- 'contacts',
- 'login-new-device',
- 'privatekey-upload',
- 'popover',
- 'infinite-scroll',
- 'ngTagsInput'
- ]);
-
- // set router paths
- app.config(function($routeProvider) {
- $routeProvider.when('/add-account', {
- templateUrl: 'tpl/add-account.html',
- controller: AddAccountCtrl
- });
- $routeProvider.when('/login', {
- templateUrl: 'tpl/login.html',
- controller: LoginCtrl
- });
- $routeProvider.when('/login-set-credentials', {
- templateUrl: 'tpl/login-set-credentials.html',
- controller: LoginSetCredentialsCtrl
- });
- $routeProvider.when('/login-existing', {
- templateUrl: 'tpl/login-existing.html',
- controller: LoginExistingCtrl
- });
- $routeProvider.when('/login-initial', {
- templateUrl: 'tpl/login-initial.html',
- controller: LoginInitialCtrl
- });
- $routeProvider.when('/login-new-device', {
- templateUrl: 'tpl/login-new-device.html',
- controller: LoginNewDeviceCtrl
- });
- $routeProvider.when('/login-privatekey-download', {
- templateUrl: 'tpl/login-privatekey-download.html',
- controller: LoginPrivateKeyDownloadCtrl
- });
- $routeProvider.when('/desktop', {
- templateUrl: 'tpl/desktop.html',
- controller: NavigationCtrl
- });
- $routeProvider.otherwise({
- redirectTo: '/login'
- });
+// set router paths
+app.config(function($routeProvider) {
+ $routeProvider.when('/add-account', {
+ templateUrl: 'tpl/add-account.html',
+ controller: AddAccountCtrl
});
+ $routeProvider.when('/login', {
+ templateUrl: 'tpl/login.html',
+ controller: LoginCtrl
+ });
+ $routeProvider.when('/login-set-credentials', {
+ templateUrl: 'tpl/login-set-credentials.html',
+ controller: LoginSetCredentialsCtrl
+ });
+ $routeProvider.when('/login-existing', {
+ templateUrl: 'tpl/login-existing.html',
+ controller: LoginExistingCtrl
+ });
+ $routeProvider.when('/login-initial', {
+ templateUrl: 'tpl/login-initial.html',
+ controller: LoginInitialCtrl
+ });
+ $routeProvider.when('/login-new-device', {
+ templateUrl: 'tpl/login-new-device.html',
+ controller: LoginNewDeviceCtrl
+ });
+ $routeProvider.when('/login-privatekey-download', {
+ templateUrl: 'tpl/login-privatekey-download.html',
+ controller: LoginPrivateKeyDownloadCtrl
+ });
+ $routeProvider.when('/desktop', {
+ templateUrl: 'tpl/desktop.html',
+ controller: NavigationCtrl
+ });
+ $routeProvider.otherwise({
+ redirectTo: '/login'
+ });
+});
- app.run(function($rootScope) {
- // global state... inherited to all child scopes
- $rootScope.state = {};
-
- // attach global error handler
- errorUtil.attachHandler($rootScope);
+app.run(function($rootScope) {
+ // global state... inherited to all child scopes
+ $rootScope.state = {};
- // attach the back button handler to the root scope
- backButtonUtil.attachHandler($rootScope);
+ // attach global error handler
+ errorUtil.attachHandler($rootScope);
- // attach fastclick
- FastClick.attach(document.body);
- });
+ // attach the back button handler to the root scope
+ backButtonUtil.attachHandler($rootScope);
- // inject controllers from ng-included view templates
- app.controller('ReadCtrl', ReadCtrl);
- app.controller('WriteCtrl', WriteCtrl);
- app.controller('MailListCtrl', MailListCtrl);
- app.controller('AccountCtrl', AccountCtrl);
- app.controller('SetPassphraseCtrl', SetPassphraseCtrl);
- app.controller('PrivateKeyUploadCtrl', PrivateKeyUploadCtrl);
- app.controller('ContactsCtrl', ContactsCtrl);
- app.controller('AboutCtrl', AboutCtrl);
- app.controller('DialogCtrl', DialogCtrl);
- app.controller('PopoverCtrl', PopoverCtrl);
+ // attach fastclick
+ FastClick.attach(document.body);
+});
- // manually bootstrap angular due to require.js
- angular.element().ready(function() {
- angular.bootstrap(document, ['mail']);
- });
-});
\ No newline at end of file
+// inject controllers from ng-included view templates
+app.controller('ReadCtrl', ReadCtrl);
+app.controller('WriteCtrl', WriteCtrl);
+app.controller('MailListCtrl', MailListCtrl);
+app.controller('AccountCtrl', AccountCtrl);
+app.controller('SetPassphraseCtrl', SetPassphraseCtrl);
+app.controller('PrivateKeyUploadCtrl', PrivateKeyUploadCtrl);
+app.controller('ContactsCtrl', ContactsCtrl);
+app.controller('AboutCtrl', AboutCtrl);
+app.controller('DialogCtrl', DialogCtrl);
+app.controller('PopoverCtrl', PopoverCtrl);
\ No newline at end of file
diff --git a/src/js/bo/auth.js b/src/js/bo/auth.js
index be7d46d..3916842 100644
--- a/src/js/bo/auth.js
+++ b/src/js/bo/auth.js
@@ -1,213 +1,211 @@
-define(function(require) {
- 'use strict';
-
- var axe = require('axe'),
- str = require('js/app-config').string;
-
- var EMAIL_ADDR_DB_KEY = 'emailaddress';
- var USERNAME_DB_KEY = 'username';
- var REALNAME_DB_KEY = 'realname';
- var PASSWD_DB_KEY = 'password';
- var PROVIDER_DB_KEY = 'provider';
- var IMAP_DB_KEY = 'imap';
- var SMTP_DB_KEY = 'smtp';
-
- /**
- * The Auth BO handles the rough edges and gaps between user/password authentication
- * and OAuth via Chrome Identity API.
- * Typical usage:
- * var auth = new Auth(...);
- * auth.setCredentials(...); // during the account setup
- * auth.getEmailAddress(...); // called from the login controller to determine if there is already a user present on the device
- * auth.getCredentials(...); // called to gather all the information to connect to IMAP/SMTP, e.g. pinned intermediate certificates,
- * username, password / oauth token, IMAP/SMTP server host names, ...
- */
- var Auth = function(appConfigStore, oauth, pgp) {
- this._appConfigStore = appConfigStore;
- this._oauth = oauth;
- this._pgp = pgp;
- };
-
- /**
- * Retrieves credentials and IMAP/SMTP settings:
- * 1) Fetches the credentials from disk, then...
- * 2 a) ... in an oauth setting, retrieves a fresh oauth token from the Chrome Identity API.
- * 2 b) ... in a user/passwd setting, does not need to do additional work.
- * 3) Loads the intermediate certs from the configuration.
- *
- * @param {Function} callback(err, credentials)
- */
- Auth.prototype.getCredentials = function(callback) {
- var self = this;
-
- if (!self.provider || !self.emailAddress) {
- // we're not yet initialized, so let's load our stuff from disk
- self._loadCredentials(function(err) {
+'use strict';
+
+var axe = require('axe-logger'),
+ str = require('../app-config').string;
+
+var EMAIL_ADDR_DB_KEY = 'emailaddress';
+var USERNAME_DB_KEY = 'username';
+var REALNAME_DB_KEY = 'realname';
+var PASSWD_DB_KEY = 'password';
+var PROVIDER_DB_KEY = 'provider';
+var IMAP_DB_KEY = 'imap';
+var SMTP_DB_KEY = 'smtp';
+
+/**
+ * The Auth BO handles the rough edges and gaps between user/password authentication
+ * and OAuth via Chrome Identity API.
+ * Typical usage:
+ * var auth = new Auth(...);
+ * auth.setCredentials(...); // during the account setup
+ * auth.getEmailAddress(...); // called from the login controller to determine if there is already a user present on the device
+ * auth.getCredentials(...); // called to gather all the information to connect to IMAP/SMTP, e.g. pinned intermediate certificates,
+ * username, password / oauth token, IMAP/SMTP server host names, ...
+ */
+var Auth = function(appConfigStore, oauth, pgp) {
+ this._appConfigStore = appConfigStore;
+ this._oauth = oauth;
+ this._pgp = pgp;
+};
+
+/**
+ * Retrieves credentials and IMAP/SMTP settings:
+ * 1) Fetches the credentials from disk, then...
+ * 2 a) ... in an oauth setting, retrieves a fresh oauth token from the Chrome Identity API.
+ * 2 b) ... in a user/passwd setting, does not need to do additional work.
+ * 3) Loads the intermediate certs from the configuration.
+ *
+ * @param {Function} callback(err, credentials)
+ */
+Auth.prototype.getCredentials = function(callback) {
+ var self = this;
+
+ if (!self.provider || !self.emailAddress) {
+ // we're not yet initialized, so let's load our stuff from disk
+ self._loadCredentials(function(err) {
+ if (err) {
+ return callback(err);
+ }
+
+ chooseLogin();
+ });
+ return;
+ }
+
+ chooseLogin();
+
+ function chooseLogin() {
+ if (self.provider === 'gmail' && !self.password) {
+ // oauth login for gmail
+ self.getOAuthToken(function(err) {
if (err) {
return callback(err);
}
- chooseLogin();
+ done();
});
return;
}
- chooseLogin();
-
- function chooseLogin() {
- if (self.provider === 'gmail' && !self.password) {
- // oauth login for gmail
- self.getOAuthToken(function(err) {
- if (err) {
- return callback(err);
- }
-
- done();
- });
- return;
- }
-
- if (self.passwordNeedsDecryption) {
- // decrypt password
- self._pgp.decrypt(self.password, undefined, function(err, cleartext) {
- if (err) {
- return callback(err);
- }
-
- self.passwordNeedsDecryption = false;
- self.password = cleartext;
+ if (self.passwordNeedsDecryption) {
+ // decrypt password
+ self._pgp.decrypt(self.password, undefined, function(err, cleartext) {
+ if (err) {
+ return callback(err);
+ }
- done();
- });
- return;
- }
+ self.passwordNeedsDecryption = false;
+ self.password = cleartext;
- done();
+ done();
+ });
+ return;
}
- function done() {
- var credentials = {
- imap: {
- secure: self.imap.secure,
- port: self.imap.port,
- host: self.imap.host,
- ca: self.imap.ca,
- pinned: self.imap.pinned,
- auth: {
- user: self.username,
- xoauth2: self.oauthToken, // password or oauthToken is undefined
- pass: self.password
- }
- },
- smtp: {
- secure: self.smtp.secure,
- port: self.smtp.port,
- host: self.smtp.host,
- ca: self.smtp.ca,
- pinned: self.smtp.pinned,
- auth: {
- user: self.username,
- xoauth2: self.oauthToken,
- pass: self.password // password or oauthToken is undefined
- }
+ done();
+ }
+
+ function done() {
+ var credentials = {
+ imap: {
+ secure: self.imap.secure,
+ port: self.imap.port,
+ host: self.imap.host,
+ ca: self.imap.ca,
+ pinned: self.imap.pinned,
+ auth: {
+ user: self.username,
+ xoauth2: self.oauthToken, // password or oauthToken is undefined
+ pass: self.password
}
- };
-
- callback(null, credentials);
- }
- };
-
- /**
- * Set the credentials
- *
- * @param {String} options.provider The service provider, e.g. 'gmail', 'yahoo', 'tonline'. Matches the entry in the app-config.
- * @param {String} options.emailAddress The email address
- * @param {String} options.username The user name
- * @param {String} options.realname The user's real name
- * @param {String} options.password The password, only in user/passwd setting
- * @param {String} options.smtp The smtp settings (host, port, secure)
- * @param {String} options.imap The imap settings (host, port, secure)
- */
- Auth.prototype.setCredentials = function(options) {
- this.credentialsDirty = true;
- this.provider = options.provider;
- this.emailAddress = options.emailAddress;
- this.username = options.username;
- this.realname = options.realname ? options.realname : '';
- this.password = options.password;
- this.smtp = options.smtp; // host, port, secure, ca, pinned
- this.imap = options.imap; // host, port, secure, ca, pinned
- };
-
- Auth.prototype.storeCredentials = function(callback) {
- var self = this;
-
- if (!self.credentialsDirty) {
- return callback();
+ },
+ smtp: {
+ secure: self.smtp.secure,
+ port: self.smtp.port,
+ host: self.smtp.host,
+ ca: self.smtp.ca,
+ pinned: self.smtp.pinned,
+ auth: {
+ user: self.username,
+ xoauth2: self.oauthToken,
+ pass: self.password // password or oauthToken is undefined
+ }
+ }
+ };
+
+ callback(null, credentials);
+ }
+};
+
+/**
+ * Set the credentials
+ *
+ * @param {String} options.provider The service provider, e.g. 'gmail', 'yahoo', 'tonline'. Matches the entry in the app-config.
+ * @param {String} options.emailAddress The email address
+ * @param {String} options.username The user name
+ * @param {String} options.realname The user's real name
+ * @param {String} options.password The password, only in user/passwd setting
+ * @param {String} options.smtp The smtp settings (host, port, secure)
+ * @param {String} options.imap The imap settings (host, port, secure)
+ */
+Auth.prototype.setCredentials = function(options) {
+ this.credentialsDirty = true;
+ this.provider = options.provider;
+ this.emailAddress = options.emailAddress;
+ this.username = options.username;
+ this.realname = options.realname ? options.realname : '';
+ this.password = options.password;
+ this.smtp = options.smtp; // host, port, secure, ca, pinned
+ this.imap = options.imap; // host, port, secure, ca, pinned
+};
+
+Auth.prototype.storeCredentials = function(callback) {
+ var self = this;
+
+ if (!self.credentialsDirty) {
+ return callback();
+ }
+
+ // persist the provider
+ self._appConfigStore.storeList([self.smtp], SMTP_DB_KEY, function(err) {
+ if (err) {
+ return callback(err);
}
- // persist the provider
- self._appConfigStore.storeList([self.smtp], SMTP_DB_KEY, function(err) {
+ self._appConfigStore.storeList([self.imap], IMAP_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- self._appConfigStore.storeList([self.imap], IMAP_DB_KEY, function(err) {
+ self._appConfigStore.storeList([self.provider], PROVIDER_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- self._appConfigStore.storeList([self.provider], PROVIDER_DB_KEY, function(err) {
+ self._appConfigStore.storeList([self.emailAddress], EMAIL_ADDR_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- self._appConfigStore.storeList([self.emailAddress], EMAIL_ADDR_DB_KEY, function(err) {
+ self._appConfigStore.storeList([self.username], USERNAME_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- self._appConfigStore.storeList([self.username], USERNAME_DB_KEY, function(err) {
+ self._appConfigStore.storeList([self.realname], REALNAME_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- self._appConfigStore.storeList([self.realname], REALNAME_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
+ if (!self.password) {
+ self.credentialsDirty = false;
+ return callback();
+ }
+
+ if (self.passwordNeedsDecryption) {
+ // password is not decrypted yet, so no need to re-encrypt it before storing...
+ self._appConfigStore.storeList([self.password], PASSWD_DB_KEY, function(err) {
+ if (err) {
+ return callback(err);
+ }
- if (!self.password) {
self.credentialsDirty = false;
- return callback();
- }
+ callback();
+ });
+ return;
+ }
- if (self.passwordNeedsDecryption) {
- // password is not decrypted yet, so no need to re-encrypt it before storing...
- self._appConfigStore.storeList([self.password], PASSWD_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
-
- self.credentialsDirty = false;
- callback();
- });
- return;
+ self._pgp.encrypt(self.password, undefined, function(err, ciphertext) {
+ if (err) {
+ return callback(err);
}
- self._pgp.encrypt(self.password, undefined, function(err, ciphertext) {
+ self._appConfigStore.storeList([ciphertext], PASSWD_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- self._appConfigStore.storeList([ciphertext], PASSWD_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
-
- self.credentialsDirty = false;
- callback();
- });
+ self.credentialsDirty = false;
+ callback();
});
});
});
@@ -215,239 +213,239 @@ define(function(require) {
});
});
});
- };
-
- /**
- * Returns the email address. Loads it from disk, if necessary
- */
- Auth.prototype.getEmailAddress = function(callback) {
- var self = this;
+ });
+};
+
+/**
+ * Returns the email address. Loads it from disk, if necessary
+ */
+Auth.prototype.getEmailAddress = function(callback) {
+ var self = this;
+
+ if (self.emailAddress) {
+ return callback(null, {
+ emailAddress: self.emailAddress,
+ realname: self.realname
+ });
+ }
- if (self.emailAddress) {
- return callback(null, {
- emailAddress: self.emailAddress,
- realname: self.realname
- });
+ self._loadCredentials(function(err) {
+ if (err) {
+ return callback(err);
}
- self._loadCredentials(function(err) {
- if (err) {
- return callback(err);
- }
-
- callback(null, {
- emailAddress: self.emailAddress,
- realname: self.realname
- });
+ callback(null, {
+ emailAddress: self.emailAddress,
+ realname: self.realname
});
- };
-
- /**
- * READ FIRST b/c usage of the oauth api is weird.
- * the chrome identity api will let you query an oauth token for an email account without knowing
- * the corresponding email address. also, android has multiple accounts whereas desktop chrome only
- * has one user logged in.
- * 1) try to read the email address from the configuration (see above)
- * 2) fetch the oauth token. if we already HAVE an email address at this point, we can spare
- * popping up the account picker on android! if not, the account picker will pop up. this
- * is android only, since the desktop chrome will query the user that is logged into chrome
- * 3) fetch the email address for the oauth token from the chrome identity api
- */
- Auth.prototype.getOAuthToken = function(callback) {
- var self = this;
-
- if (self.oauthToken) {
- // removed cached token and get a new one
- self._oauth.refreshToken({
- emailAddress: self.emailAddress,
- oldToken: self.oauthToken
- }, onToken);
- } else {
- // get a fresh oauth token
- self._oauth.getOAuthToken(self.emailAddress, onToken);
+ });
+};
+
+/**
+ * READ FIRST b/c usage of the oauth api is weird.
+ * the chrome identity api will let you query an oauth token for an email account without knowing
+ * the corresponding email address. also, android has multiple accounts whereas desktop chrome only
+ * has one user logged in.
+ * 1) try to read the email address from the configuration (see above)
+ * 2) fetch the oauth token. if we already HAVE an email address at this point, we can spare
+ * popping up the account picker on android! if not, the account picker will pop up. this
+ * is android only, since the desktop chrome will query the user that is logged into chrome
+ * 3) fetch the email address for the oauth token from the chrome identity api
+ */
+Auth.prototype.getOAuthToken = function(callback) {
+ var self = this;
+
+ if (self.oauthToken) {
+ // removed cached token and get a new one
+ self._oauth.refreshToken({
+ emailAddress: self.emailAddress,
+ oldToken: self.oauthToken
+ }, onToken);
+ } else {
+ // get a fresh oauth token
+ self._oauth.getOAuthToken(self.emailAddress, onToken);
+ }
+
+ function onToken(err, oauthToken) {
+ if (err) {
+ return callback(err);
}
- function onToken(err, oauthToken) {
+ // shortcut if the email address is already known
+ if (self.emailAddress) {
+ self.oauthToken = oauthToken;
+ return callback();
+ }
+
+ // query the email address
+ self._oauth.queryEmailAddress(oauthToken, function(err, emailAddress) {
if (err) {
return callback(err);
}
- // shortcut if the email address is already known
- if (self.emailAddress) {
- self.oauthToken = oauthToken;
- return callback();
- }
-
- // query the email address
- self._oauth.queryEmailAddress(oauthToken, function(err, emailAddress) {
- if (err) {
- return callback(err);
- }
-
- self.oauthToken = oauthToken;
- self.emailAddress = emailAddress;
- callback();
- });
- }
- };
-
- /**
- * Loads email address, password, provider, ... from disk and sets them on `this`
- */
- Auth.prototype._loadCredentials = function(callback) {
- var self = this;
-
- if (self.initialized) {
+ self.oauthToken = oauthToken;
+ self.emailAddress = emailAddress;
callback();
+ });
+ }
+};
+
+/**
+ * Loads email address, password, provider, ... from disk and sets them on `this`
+ */
+Auth.prototype._loadCredentials = function(callback) {
+ var self = this;
+
+ if (self.initialized) {
+ callback();
+ }
+
+ loadFromDB(SMTP_DB_KEY, function(err, smtp) {
+ if (err) {
+ return callback(err);
}
- loadFromDB(SMTP_DB_KEY, function(err, smtp) {
+
+ loadFromDB(IMAP_DB_KEY, function(err, imap) {
if (err) {
return callback(err);
}
- loadFromDB(IMAP_DB_KEY, function(err, imap) {
+ loadFromDB(USERNAME_DB_KEY, function(err, username) {
if (err) {
return callback(err);
}
- loadFromDB(USERNAME_DB_KEY, function(err, username) {
+ loadFromDB(REALNAME_DB_KEY, function(err, realname) {
if (err) {
return callback(err);
}
- loadFromDB(REALNAME_DB_KEY, function(err, realname) {
+ loadFromDB(EMAIL_ADDR_DB_KEY, function(err, emailAddress) {
if (err) {
return callback(err);
}
-
- loadFromDB(EMAIL_ADDR_DB_KEY, function(err, emailAddress) {
+ loadFromDB(PASSWD_DB_KEY, function(err, password) {
if (err) {
return callback(err);
}
- loadFromDB(PASSWD_DB_KEY, function(err, password) {
+ loadFromDB(PROVIDER_DB_KEY, function(err, provider) {
if (err) {
return callback(err);
}
- loadFromDB(PROVIDER_DB_KEY, function(err, provider) {
- if (err) {
- return callback(err);
- }
-
- self.emailAddress = emailAddress;
- self.password = password;
- self.passwordNeedsDecryption = !!password;
- self.provider = provider;
- self.username = username;
- self.realname = realname;
- self.smtp = smtp;
- self.imap = imap;
- self.initialized = true;
-
- callback();
- });
+ self.emailAddress = emailAddress;
+ self.password = password;
+ self.passwordNeedsDecryption = !!password;
+ self.provider = provider;
+ self.username = username;
+ self.realname = realname;
+ self.smtp = smtp;
+ self.imap = imap;
+ self.initialized = true;
+
+ callback();
});
});
});
});
});
});
+ });
- function loadFromDB(key, callback) {
- self._appConfigStore.listItems(key, 0, null, function(err, cachedItems) {
- callback(err, (!err && cachedItems && cachedItems[0]));
- });
- }
- };
-
- /**
- * Handles certificate updates and errors by notifying the user.
- * @param {String} component Either imap or smtp
- * @param {Function} callback The error handler
- * @param {[type]} pemEncodedCert The PEM encoded SSL certificate
- */
- Auth.prototype.handleCertificateUpdate = function(component, onConnect, callback, pemEncodedCert) {
- var self = this;
-
- axe.debug('new ssl certificate received: ' + pemEncodedCert);
+ function loadFromDB(key, callback) {
+ self._appConfigStore.listItems(key, 0, null, function(err, cachedItems) {
+ callback(err, (!err && cachedItems && cachedItems[0]));
+ });
+ }
+};
+
+/**
+ * Handles certificate updates and errors by notifying the user.
+ * @param {String} component Either imap or smtp
+ * @param {Function} callback The error handler
+ * @param {[type]} pemEncodedCert The PEM encoded SSL certificate
+ */
+Auth.prototype.handleCertificateUpdate = function(component, onConnect, callback, pemEncodedCert) {
+ var self = this;
+
+ axe.debug('new ssl certificate received: ' + pemEncodedCert);
+
+ if (!self[component].ca) {
+ // no previous ssl cert, trust on first use
+ self[component].ca = pemEncodedCert;
+ self.credentialsDirty = true;
+ self.storeCredentials(callback);
+ return;
+ }
+
+ if (self[component].ca === pemEncodedCert) {
+ // ignore multiple successive tls handshakes, e.g. for gmail
+ return;
+ }
+
+ if (self[component].ca && self[component].pinned) {
+ // do not update the pinned certificates!
+ callback({
+ title: str.outdatedCertificateTitle,
+ message: str.outdatedCertificateMessage.replace('{0}', self[component].host),
+ faqLink: str.certificateFaqLink,
+ });
+ return;
+ }
+
+ // previous ssl cert known, does not match: query user and certificate
+ callback({
+ title: str.updateCertificateTitle,
+ message: str.updateCertificateMessage.replace('{0}', self[component].host),
+ positiveBtnStr: str.updateCertificatePosBtn,
+ negativeBtnStr: str.updateCertificateNegBtn,
+ showNegativeBtn: true,
+ faqLink: str.certificateFaqLink,
+ callback: function(granted) {
+ if (!granted) {
+ return;
+ }
- if (!self[component].ca) {
- // no previous ssl cert, trust on first use
self[component].ca = pemEncodedCert;
- self.credentialsDirty = true;
- self.storeCredentials(callback);
- return;
- }
-
- if (self[component].ca === pemEncodedCert) {
- // ignore multiple successive tls handshakes, e.g. for gmail
- return;
- }
+ self.storeCredentials(function(err) {
+ if (err) {
+ callback(err);
+ return;
+ }
- if (self[component].ca && self[component].pinned) {
- // do not update the pinned certificates!
- callback({
- title: str.outdatedCertificateTitle,
- message: str.outdatedCertificateMessage.replace('{0}', self[component].host),
- faqLink: str.certificateFaqLink,
+ onConnect(callback);
});
+ }
+ });
+};
+
+/**
+ * Logout of the app by clearing the app config store and in memory credentials
+ */
+Auth.prototype.logout = function(callback) {
+ var self = this;
+
+ // clear app config db
+ self._appConfigStore.clear(function(err) {
+ if (err) {
+ callback(err);
return;
}
- // previous ssl cert known, does not match: query user and certificate
- callback({
- title: str.updateCertificateTitle,
- message: str.updateCertificateMessage.replace('{0}', self[component].host),
- positiveBtnStr: str.updateCertificatePosBtn,
- negativeBtnStr: str.updateCertificateNegBtn,
- showNegativeBtn: true,
- faqLink: str.certificateFaqLink,
- callback: function(granted) {
- if (!granted) {
- return;
- }
+ // clear in memory cache
+ self.setCredentials({});
+ self.initialized = undefined;
+ self.credentialsDirty = undefined;
+ self.passwordNeedsDecryption = undefined;
- self[component].ca = pemEncodedCert;
- self.storeCredentials(function(err) {
- if (err) {
- callback(err);
- return;
- }
-
- onConnect(callback);
- });
- }
- });
- };
-
- /**
- * Logout of the app by clearing the app config store and in memory credentials
- */
- Auth.prototype.logout = function(callback) {
- var self = this;
-
- // clear app config db
- self._appConfigStore.clear(function(err) {
- if (err) {
- callback(err);
- return;
- }
-
- // clear in memory cache
- self.setCredentials({});
- self.initialized = undefined;
- self.credentialsDirty = undefined;
- self.passwordNeedsDecryption = undefined;
-
- callback();
- });
- };
+ callback();
+ });
+};
- return Auth;
-});
\ No newline at end of file
+module.exports = Auth;
\ No newline at end of file
diff --git a/src/js/bo/outbox.js b/src/js/bo/outbox.js
index 8a09cfb..12ccc50 100644
--- a/src/js/bo/outbox.js
+++ b/src/js/bo/outbox.js
@@ -1,232 +1,229 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var _ = require('underscore'),
- util = require('js/crypto/util'),
- config = require('js/app-config').config,
- outboxDb = 'email_OUTBOX';
+var util = require('crypto-lib').util,
+ config = require('../app-config').config,
+ outboxDb = 'email_OUTBOX';
- /**
- * 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, keychain, devicestorage) {
- /** @private */
- this._emailDao = emailDao;
-
- /** @private */
- this._keychain = keychain;
-
- /** @private */
- this._devicestorage = devicestorage;
-
- /**
- * Semaphore-esque flag to avoid 'concurrent' calls to _processOutbox when the timeout fires, but a call is still in process.
- * @private */
- this._outboxBusy = false;
- };
+/**
+ * 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, keychain, devicestorage) {
+ /** @private */
+ this._emailDao = emailDao;
- /**
- * This function activates the periodic checking of the local device storage for pending mails.
- * @param {Function} callback(error, pendingMailsCount) Callback that informs you about the count of pending mails.
- */
- OutboxBO.prototype.startChecking = function(callback) {
- // remember global callback
- this._onUpdate = callback;
- // start periodic checking of outbox
- this._intervalId = setInterval(this._processOutbox.bind(this, this._onUpdate), config.checkOutboxInterval);
- };
+ /** @private */
+ this._keychain = keychain;
- /**
- * Outbox stops the periodic checking of the local device storage for pending mails.
- */
- OutboxBO.prototype.stopChecking = function() {
- if (!this._intervalId) {
- return;
- }
-
- clearInterval(this._intervalId);
- delete this._intervalId;
- };
+ /** @private */
+ this._devicestorage = devicestorage;
/**
- * Put a email dto in the outbox for sending when ready
- * @param {Object} mail The Email DTO
- * @param {Function} callback Invoked when the object was encrypted and persisted to disk
- */
- OutboxBO.prototype.put = function(mail, callback) {
- var self = this,
- allReaders = mail.from.concat(mail.to.concat(mail.cc.concat(mail.bcc))); // all the users that should be able to read the mail
-
- mail.publicKeysArmored = []; // gather the public keys
- mail.uid = mail.id = util.UUID(); // the mail needs a random id & uid for storage in the database
-
- // do not encrypt mails with a bcc recipient, due to a possible privacy leak
- if (mail.bcc.length > 0) {
- storeAndForward(mail);
- return;
- }
-
- checkRecipients(allReaders);
-
- // check if there are unregistered recipients
- function checkRecipients(recipients) {
- var after = _.after(recipients.length, function() {
- checkEncrypt();
- });
-
- // find out if there are unregistered users
- recipients.forEach(function(recipient) {
- self._keychain.getReceiverPublicKey(recipient.address, function(err, key) {
- if (err) {
- callback(err);
- return;
- }
-
- // if a public key is available, add the recipient's key to the armored public keys,
- // otherwise remember the recipient as unregistered for later sending
- if (key) {
- mail.publicKeysArmored.push(key.publicKey);
- }
-
- after();
- });
- });
- }
-
- function checkEncrypt() {
- // only encrypt if all recipients have public keys
- if (mail.publicKeysArmored.length < allReaders.length) {
- storeAndForward(mail);
- return;
- }
+ * Semaphore-esque flag to avoid 'concurrent' calls to _processOutbox when the timeout fires, but a call is still in process.
+ * @private */
+ this._outboxBusy = false;
+};
+
+/**
+ * This function activates the periodic checking of the local device storage for pending mails.
+ * @param {Function} callback(error, pendingMailsCount) Callback that informs you about the count of pending mails.
+ */
+OutboxBO.prototype.startChecking = function(callback) {
+ // remember global callback
+ this._onUpdate = callback;
+ // start periodic checking of outbox
+ this._intervalId = setInterval(this._processOutbox.bind(this, this._onUpdate), config.checkOutboxInterval);
+};
+
+/**
+ * Outbox stops the periodic checking of the local device storage for pending mails.
+ */
+OutboxBO.prototype.stopChecking = function() {
+ if (!this._intervalId) {
+ return;
+ }
+
+ clearInterval(this._intervalId);
+ delete this._intervalId;
+};
+
+/**
+ * Put a email dto in the outbox for sending when ready
+ * @param {Object} mail The Email DTO
+ * @param {Function} callback Invoked when the object was encrypted and persisted to disk
+ */
+OutboxBO.prototype.put = function(mail, callback) {
+ var self = this,
+ allReaders = mail.from.concat(mail.to.concat(mail.cc.concat(mail.bcc))); // all the users that should be able to read the mail
+
+ mail.publicKeysArmored = []; // gather the public keys
+ mail.uid = mail.id = util.UUID(); // the mail needs a random id & uid for storage in the database
+
+ // do not encrypt mails with a bcc recipient, due to a possible privacy leak
+ if (mail.bcc.length > 0) {
+ storeAndForward(mail);
+ return;
+ }
+
+ checkRecipients(allReaders);
+
+ // check if there are unregistered recipients
+ function checkRecipients(recipients) {
+ var after = _.after(recipients.length, function() {
+ checkEncrypt();
+ });
- // encrypts the body and attachments and persists the mail object
- self._emailDao.encrypt({
- mail: mail,
- publicKeysArmored: mail.publicKeysArmored
- }, function(err) {
+ // find out if there are unregistered users
+ recipients.forEach(function(recipient) {
+ self._keychain.getReceiverPublicKey(recipient.address, function(err, key) {
if (err) {
callback(err);
return;
}
- storeAndForward(mail);
- });
- }
-
- function storeAndForward(mail) {
- // store in outbox
- self._devicestorage.storeList([mail], outboxDb, function(err) {
- if (err) {
- callback(err);
- return;
+ // if a public key is available, add the recipient's key to the armored public keys,
+ // otherwise remember the recipient as unregistered for later sending
+ if (key) {
+ mail.publicKeysArmored.push(key.publicKey);
}
- callback();
- // don't wait for next round
- self._processOutbox(self._onUpdate);
+ after();
});
- }
- };
+ });
+ }
- /**
- * Checks the local device storage for pending mails.
- * @param {Function} callback(error, pendingMailsCount) Callback that informs you about the count of pending mails.
- */
- OutboxBO.prototype._processOutbox = function(callback) {
- var self = this,
- unsentMails = 0;
-
- // also, if a _processOutbox call is still in progress, ignore it.
- if (self._outboxBusy) {
+ function checkEncrypt() {
+ // only encrypt if all recipients have public keys
+ if (mail.publicKeysArmored.length < allReaders.length) {
+ storeAndForward(mail);
return;
}
- self._outboxBusy = true;
-
- // get pending mails from the outbox
- self._devicestorage.listItems(outboxDb, 0, null, function(err, pendingMails) {
- // error, we're done here
+ // encrypts the body and attachments and persists the mail object
+ self._emailDao.encrypt({
+ mail: mail,
+ publicKeysArmored: mail.publicKeysArmored
+ }, function(err) {
if (err) {
- self._outboxBusy = false;
callback(err);
return;
}
- // if we're not online, don't even bother sending mails.
- if (!self._emailDao._account.online || _.isEmpty(pendingMails)) {
- self._outboxBusy = false;
- callback(null, pendingMails.length);
+ storeAndForward(mail);
+ });
+ }
+
+ function storeAndForward(mail) {
+ // store in outbox
+ self._devicestorage.storeList([mail], outboxDb, function(err) {
+ if (err) {
+ callback(err);
return;
}
- // we're done after all the mails have been handled
- // update the outbox count...
- var after = _.after(pendingMails.length, function() {
- self._outboxBusy = false;
- callback(null, unsentMails);
- });
+ callback();
+ // don't wait for next round
+ self._processOutbox(self._onUpdate);
+ });
+ }
+};
+
+/**
+ * Checks the local device storage for pending mails.
+ * @param {Function} callback(error, pendingMailsCount) Callback that informs you about the count of pending mails.
+ */
+OutboxBO.prototype._processOutbox = function(callback) {
+ var self = this,
+ unsentMails = 0;
+
+ // also, if a _processOutbox call is still in progress, ignore it.
+ if (self._outboxBusy) {
+ return;
+ }
+
+ self._outboxBusy = true;
+
+ // get pending mails from the outbox
+ self._devicestorage.listItems(outboxDb, 0, null, function(err, pendingMails) {
+ // error, we're done here
+ if (err) {
+ self._outboxBusy = false;
+ callback(err);
+ return;
+ }
- // send pending mails if possible
- pendingMails.forEach(function(mail) {
- send(mail, after);
- });
+ // if we're not online, don't even bother sending mails.
+ if (!self._emailDao._account.online || _.isEmpty(pendingMails)) {
+ self._outboxBusy = false;
+ callback(null, pendingMails.length);
+ return;
+ }
+
+ // we're done after all the mails have been handled
+ // update the outbox count...
+ var after = _.after(pendingMails.length, function() {
+ self._outboxBusy = false;
+ callback(null, unsentMails);
});
- // send the message
- function send(mail, done) {
-
- // check is email is to be sent encrypted or as plaintex
- if (mail.encrypted === true) {
- // email was already encrypted before persisting in outbox, tell pgpmailer to send encrypted and not encrypt again
- self._emailDao.sendEncrypted({
- email: mail
- }, onSend);
- } else {
- // send email as plaintext
- self._emailDao.sendPlaintext({
- email: mail
- }, onSend);
- }
+ // send pending mails if possible
+ pendingMails.forEach(function(mail) {
+ send(mail, after);
+ });
+ });
+
+ // send the message
+ function send(mail, done) {
+
+ // check is email is to be sent encrypted or as plaintex
+ if (mail.encrypted === true) {
+ // email was already encrypted before persisting in outbox, tell pgpmailer to send encrypted and not encrypt again
+ self._emailDao.sendEncrypted({
+ email: mail
+ }, onSend);
+ } else {
+ // send email as plaintext
+ self._emailDao.sendPlaintext({
+ email: mail
+ }, onSend);
+ }
- function onSend(err) {
- if (err) {
+ function onSend(err) {
+ if (err) {
+ self._outboxBusy = false;
+ if (err.code === 42) {
+ // offline try again later
+ done();
+ } else {
self._outboxBusy = false;
- if (err.code === 42) {
- // offline try again later
- done();
- } else {
- self._outboxBusy = false;
- callback(err);
- }
- return;
+ callback(err);
}
+ return;
+ }
- // remove the pending mail from the storage
- removeFromStorage(mail, done);
+ // remove the pending mail from the storage
+ removeFromStorage(mail, done);
- // fire sent notification
- if (typeof self.onSent === 'function') {
- self.onSent(mail);
- }
+ // fire sent notification
+ if (typeof self.onSent === 'function') {
+ self.onSent(mail);
}
}
+ }
- // removes the mail object from disk after successfully sending it
- function removeFromStorage(mail, done) {
- self._devicestorage.removeList(outboxDb + '_' + mail.uid, function(err) {
- if (err) {
- self._outboxBusy = false;
- callback(err);
- return;
- }
+ // removes the mail object from disk after successfully sending it
+ function removeFromStorage(mail, done) {
+ self._devicestorage.removeList(outboxDb + '_' + mail.uid, function(err) {
+ if (err) {
+ self._outboxBusy = false;
+ callback(err);
+ return;
+ }
- done();
- });
- }
- };
+ done();
+ });
+ }
+};
- return OutboxBO;
-});
\ No newline at end of file
+module.exports = OutboxBO;
\ No newline at end of file
diff --git a/src/js/controller/about.js b/src/js/controller/about.js
index 7e952a0..5f2d39c 100644
--- a/src/js/controller/about.js
+++ b/src/js/controller/about.js
@@ -1,31 +1,29 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var cfg = require('js/app-config').config;
+var cfg = require('../app-config').config;
- //
- // Controller
- //
+//
+// Controller
+//
- var AboutCtrl = function($scope) {
+var AboutCtrl = function($scope) {
- $scope.state.about = {
- toggle: function(to) {
- $scope.state.lightbox = (to) ? 'about' : undefined;
- }
- };
+ $scope.state.about = {
+ toggle: function(to) {
+ $scope.state.lightbox = (to) ? 'about' : undefined;
+ }
+ };
- //
- // scope variables
- //
+ //
+ // scope variables
+ //
- $scope.version = cfg.appVersion;
- $scope.date = new Date();
+ $scope.version = cfg.appVersion;
+ $scope.date = new Date();
- //
- // scope functions
- //
- };
+ //
+ // scope functions
+ //
+};
- return AboutCtrl;
-});
\ No newline at end of file
+module.exports = AboutCtrl;
\ No newline at end of file
diff --git a/src/js/controller/account.js b/src/js/controller/account.js
index 7c409dd..ba1a46b 100644
--- a/src/js/controller/account.js
+++ b/src/js/controller/account.js
@@ -1,61 +1,59 @@
-define(function(require) {
- 'use strict';
-
- var appController = require('js/app-controller'),
- dl = require('js/util/download'),
- config = require('js/app-config').config,
- pgp, keychain, userId;
+'use strict';
+
+var appController = require('../app-controller'),
+ dl = require('../util/download'),
+ config = require('../app-config').config,
+ pgp, keychain, userId;
+
+//
+// Controller
+//
+
+var AccountCtrl = function($scope) {
+ userId = appController._emailDao._account.emailAddress;
+ keychain = appController._keychain;
+ pgp = appController._pgp;
+
+ $scope.state.account = {
+ toggle: function(to) {
+ $scope.state.lightbox = (to) ? 'account' : undefined;
+ }
+ };
//
- // Controller
+ // scope variables
//
- var AccountCtrl = function($scope) {
- userId = appController._emailDao._account.emailAddress;
- keychain = appController._keychain;
- pgp = appController._pgp;
+ var keyParams = pgp.getKeyParams();
+
+ $scope.eMail = userId;
+ $scope.keyId = keyParams._id.slice(8);
+ var fpr = keyParams.fingerprint;
+ $scope.fingerprint = fpr.slice(0, 4) + ' ' + fpr.slice(4, 8) + ' ' + fpr.slice(8, 12) + ' ' + fpr.slice(12, 16) + ' ' + fpr.slice(16, 20) + ' ' + fpr.slice(20, 24) + ' ' + fpr.slice(24, 28) + ' ' + fpr.slice(28, 32) + ' ' + fpr.slice(32, 36) + ' ' + fpr.slice(36);
+ $scope.keysize = keyParams.bitSize;
+ $scope.publicKeyUrl = config.cloudUrl + '/' + userId;
+
+ //
+ // scope functions
+ //
- $scope.state.account = {
- toggle: function(to) {
- $scope.state.lightbox = (to) ? 'account' : undefined;
+ $scope.exportKeyFile = function() {
+ keychain.getUserKeyPair(userId, function(err, keys) {
+ if (err) {
+ $scope.onError(err);
+ return;
}
- };
-
- //
- // scope variables
- //
-
- var keyParams = pgp.getKeyParams();
-
- $scope.eMail = userId;
- $scope.keyId = keyParams._id.slice(8);
- var fpr = keyParams.fingerprint;
- $scope.fingerprint = fpr.slice(0, 4) + ' ' + fpr.slice(4, 8) + ' ' + fpr.slice(8, 12) + ' ' + fpr.slice(12, 16) + ' ' + fpr.slice(16, 20) + ' ' + fpr.slice(20, 24) + ' ' + fpr.slice(24, 28) + ' ' + fpr.slice(28, 32) + ' ' + fpr.slice(32, 36) + ' ' + fpr.slice(36);
- $scope.keysize = keyParams.bitSize;
- $scope.publicKeyUrl = config.cloudUrl + '/' + userId;
-
- //
- // scope functions
- //
-
- $scope.exportKeyFile = function() {
- keychain.getUserKeyPair(userId, function(err, keys) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- var keyId = keys.publicKey._id;
- var file = 'whiteout_mail_' + userId + '_' + keyId.substring(8, keyId.length);
-
- dl.createDownload({
- content: keys.publicKey.publicKey + '\r\n' + keys.privateKey.encryptedKey,
- filename: file + '.asc',
- contentType: 'text/plain'
- });
+
+ var keyId = keys.publicKey._id;
+ var file = 'whiteout_mail_' + userId + '_' + keyId.substring(8, keyId.length);
+
+ dl.createDownload({
+ content: keys.publicKey.publicKey + '\r\n' + keys.privateKey.encryptedKey,
+ filename: file + '.asc',
+ contentType: 'text/plain'
});
- };
+ });
};
+};
- return AccountCtrl;
-});
\ No newline at end of file
+module.exports = AccountCtrl;
\ No newline at end of file
diff --git a/src/js/controller/add-account.js b/src/js/controller/add-account.js
index 35c3288..ccc1d17 100644
--- a/src/js/controller/add-account.js
+++ b/src/js/controller/add-account.js
@@ -1,120 +1,118 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var appCtrl = require('js/app-controller'),
- cfg = require('js/app-config').config;
+var appCtrl = require('../app-controller'),
+ cfg = require('../app-config').config;
- var AddAccountCtrl = function($scope, $location, $routeParams) {
- if (!appCtrl._auth && !$routeParams.dev) {
- $location.path('/'); // init app
- return;
- }
+var AddAccountCtrl = function($scope, $location, $routeParams) {
+ if (!appCtrl._auth && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
- $scope.step = 1;
+ $scope.step = 1;
- $scope.goTo = function(step) {
- $scope.step = step;
- };
+ $scope.goTo = function(step) {
+ $scope.step = step;
+ };
- $scope.createWhiteoutAccount = function() {
- if ($scope.form.$invalid) {
+ $scope.createWhiteoutAccount = function() {
+ if ($scope.form.$invalid) {
+ return;
+ }
+
+ $scope.busy = true;
+ $scope.errMsg = undefined; // reset error msg
+ $scope.emailAddress = $scope.user + '@' + cfg.wmailDomain;
+
+ // call REST api
+ appCtrl._adminDao.createUser({
+ emailAddress: $scope.emailAddress,
+ password: $scope.pass,
+ phone: $scope.phone.replace(/\s+/g, ''), // remove spaces from the phone number
+ betaCode: $scope.betaCode.toUpperCase()
+ }, function(err) {
+ $scope.busy = false;
+
+ if (err) {
+ $scope.errMsg = err.errMsg || err.message;
+ $scope.$apply();
return;
}
- $scope.busy = true;
- $scope.errMsg = undefined; // reset error msg
- $scope.emailAddress = $scope.user + '@' + cfg.wmailDomain;
-
- // call REST api
- appCtrl._adminDao.createUser({
- emailAddress: $scope.emailAddress,
- password: $scope.pass,
- phone: $scope.phone.replace(/\s+/g, ''), // remove spaces from the phone number
- betaCode: $scope.betaCode.toUpperCase()
- }, function(err) {
- $scope.busy = false;
+ $scope.goTo(3);
+ $scope.$apply();
+ });
+ };
- if (err) {
- $scope.errMsg = err.errMsg || err.message;
- $scope.$apply();
- return;
- }
+ $scope.validateUser = function() {
+ if ($scope.formValidate.$invalid) {
+ return;
+ }
- $scope.goTo(3);
+ $scope.busyValidate = true;
+ $scope.errMsgValidate = undefined; // reset error msg
+
+ // verify user to REST api
+ appCtrl._adminDao.validateUser({
+ emailAddress: $scope.emailAddress,
+ token: $scope.token.toUpperCase()
+ }, function(err) {
+ if (err) {
+ $scope.busyValidate = false;
+ $scope.errMsgValidate = err.errMsg || err.message;
$scope.$apply();
- });
- };
-
- $scope.validateUser = function() {
- if ($scope.formValidate.$invalid) {
return;
}
- $scope.busyValidate = true;
- $scope.errMsgValidate = undefined; // reset error msg
+ // proceed to login
+ $scope.login();
+ });
+ };
- // verify user to REST api
- appCtrl._adminDao.validateUser({
- emailAddress: $scope.emailAddress,
- token: $scope.token.toUpperCase()
- }, function(err) {
+ $scope.login = function() {
+ // store credentials in memory
+ appCtrl._auth.setCredentials({
+ provider: 'wmail',
+ emailAddress: $scope.emailAddress,
+ username: $scope.emailAddress,
+ realname: $scope.realname,
+ password: $scope.pass,
+ imap: cfg.wmail.imap,
+ smtp: cfg.wmail.smtp
+ });
+
+ // proceed to login and keygen
+ $location.path('/login');
+ $scope.$apply();
+ };
+
+ $scope.connectToGoogle = function() {
+ // test for oauth support
+ if (appCtrl._auth._oauth.isSupported()) {
+ // fetches the email address from the chrome identity api
+ appCtrl._auth.getOAuthToken(function(err) {
if (err) {
- $scope.busyValidate = false;
- $scope.errMsgValidate = err.errMsg || err.message;
- $scope.$apply();
- return;
+ return $scope.onError(err);
}
-
- // proceed to login
- $scope.login();
- });
- };
-
- $scope.login = function() {
- // store credentials in memory
- appCtrl._auth.setCredentials({
- provider: 'wmail',
- emailAddress: $scope.emailAddress,
- username: $scope.emailAddress,
- realname: $scope.realname,
- password: $scope.pass,
- imap: cfg.wmail.imap,
- smtp: cfg.wmail.smtp
- });
-
- // proceed to login and keygen
- $location.path('/login');
- $scope.$apply();
- };
-
- $scope.connectToGoogle = function() {
- // test for oauth support
- if (appCtrl._auth._oauth.isSupported()) {
- // fetches the email address from the chrome identity api
- appCtrl._auth.getOAuthToken(function(err) {
- if (err) {
- return $scope.onError(err);
- }
- $location.path('/login-set-credentials').search({
- provider: 'gmail'
- });
- $scope.$apply();
+ $location.path('/login-set-credentials').search({
+ provider: 'gmail'
});
- return;
- }
-
- // use normal user/password login
- $location.path('/login-set-credentials').search({
- provider: 'gmail'
+ $scope.$apply();
});
- };
+ return;
+ }
- $scope.connectTo = function(provider) {
- $location.path('/login-set-credentials').search({
- provider: provider
- });
- };
+ // use normal user/password login
+ $location.path('/login-set-credentials').search({
+ provider: 'gmail'
+ });
+ };
+
+ $scope.connectTo = function(provider) {
+ $location.path('/login-set-credentials').search({
+ provider: provider
+ });
};
+};
- return AddAccountCtrl;
-});
\ No newline at end of file
+module.exports = AddAccountCtrl;
\ No newline at end of file
diff --git a/src/js/controller/contacts.js b/src/js/controller/contacts.js
index 10cd441..0e72918 100644
--- a/src/js/controller/contacts.js
+++ b/src/js/controller/contacts.js
@@ -1,143 +1,139 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var angular = require('angular'),
- _ = require('underscore'),
- appController = require('js/app-controller'),
- keychain, pgp;
+var appController = require('../app-controller'),
+ keychain, pgp;
- //
- // Controller
- //
-
- var ContactsCtrl = function($scope) {
- keychain = appController._keychain,
- pgp = appController._pgp;
-
- $scope.state.contacts = {
- toggle: function(to) {
- $scope.state.lightbox = (to) ? 'contacts' : undefined;
-
- $scope.listKeys();
- }
- };
-
- // set default value so that the popover height is correct on init
- $scope.fingerprint = 'XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX';
+//
+// Controller
+//
- //
- // scope functions
- //
+var ContactsCtrl = function($scope) {
+ keychain = appController._keychain,
+ pgp = appController._pgp;
- $scope.listKeys = function() {
- keychain.listLocalPublicKeys(function(err, keys) {
- if (err) {
- $scope.onError(err);
- return;
- }
+ $scope.state.contacts = {
+ toggle: function(to) {
+ $scope.state.lightbox = (to) ? 'contacts' : undefined;
- keys.forEach(addParams);
+ $scope.listKeys();
+ }
+ };
- $scope.keys = keys;
- $scope.$apply();
+ // set default value so that the popover height is correct on init
+ $scope.fingerprint = 'XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX';
- function addParams(key) {
- var params = pgp.getKeyParams(key.publicKey);
- _.extend(key, params);
- }
- });
- };
+ //
+ // scope functions
+ //
- $scope.getFingerprint = function(key) {
- var fpr = key.fingerprint;
- var formatted = fpr.slice(0, 4) + ' ' + fpr.slice(4, 8) + ' ' + fpr.slice(8, 12) + ' ' + fpr.slice(12, 16) + ' ' + fpr.slice(16, 20) + ' ... ' + fpr.slice(20, 24) + ' ' + fpr.slice(24, 28) + ' ' + fpr.slice(28, 32) + ' ' + fpr.slice(32, 36) + ' ' + fpr.slice(36);
+ $scope.listKeys = function() {
+ keychain.listLocalPublicKeys(function(err, keys) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
- $scope.fingerprint = formatted;
- };
+ keys.forEach(addParams);
- $scope.importKey = function(publicKeyArmored) {
- var keyParams, pubkey;
+ $scope.keys = keys;
+ $scope.$apply();
- // verifiy public key string
- if (publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
- $scope.onError({
- showBugReporter: false,
- message: 'Invalid public key!'
- });
- return;
+ function addParams(key) {
+ var params = pgp.getKeyParams(key.publicKey);
+ _.extend(key, params);
}
+ });
+ };
- try {
- keyParams = pgp.getKeyParams(publicKeyArmored);
- } catch (e) {
- $scope.onError(new Error('Error reading public key params!'));
- return;
- }
+ $scope.getFingerprint = function(key) {
+ var fpr = key.fingerprint;
+ var formatted = fpr.slice(0, 4) + ' ' + fpr.slice(4, 8) + ' ' + fpr.slice(8, 12) + ' ' + fpr.slice(12, 16) + ' ' + fpr.slice(16, 20) + ' ... ' + fpr.slice(20, 24) + ' ' + fpr.slice(24, 28) + ' ' + fpr.slice(28, 32) + ' ' + fpr.slice(32, 36) + ' ' + fpr.slice(36);
- pubkey = {
- _id: keyParams._id,
- userId: keyParams.userId,
- userIds: keyParams.userIds,
- publicKey: publicKeyArmored,
- imported: true // mark manually imported keys
- };
+ $scope.fingerprint = formatted;
+ };
- keychain.saveLocalPublicKey(pubkey, function(err) {
- if (err) {
- $scope.onError(err);
- return;
- }
+ $scope.importKey = function(publicKeyArmored) {
+ var keyParams, pubkey;
- // update displayed keys
- $scope.listKeys();
+ // verifiy public key string
+ if (publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
+ $scope.onError({
+ showBugReporter: false,
+ message: 'Invalid public key!'
});
+ return;
+ }
+
+ try {
+ keyParams = pgp.getKeyParams(publicKeyArmored);
+ } catch (e) {
+ $scope.onError(new Error('Error reading public key params!'));
+ return;
+ }
+
+ pubkey = {
+ _id: keyParams._id,
+ userId: keyParams.userId,
+ userIds: keyParams.userIds,
+ publicKey: publicKeyArmored,
+ imported: true // mark manually imported keys
};
- $scope.removeKey = function(key) {
- keychain.removeLocalPublicKey(key._id, function(err) {
- if (err) {
- $scope.onError(err);
- return;
- }
+ keychain.saveLocalPublicKey(pubkey, function(err) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
- // update displayed keys
- $scope.listKeys();
- });
- };
+ // update displayed keys
+ $scope.listKeys();
+ });
};
- //
- // Directives
- //
+ $scope.removeKey = function(key) {
+ keychain.removeLocalPublicKey(key._id, function(err) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
- var ngModule = angular.module('contacts', []);
+ // update displayed keys
+ $scope.listKeys();
+ });
+ };
+};
- ngModule.directive('keyfileInput', function() {
- return function(scope, elm) {
- elm.on('change', function(e) {
- for (var i = 0; i < e.target.files.length; i++) {
- importKey(e.target.files.item(i));
- }
- });
+//
+// Directives
+//
+
+var ngModule = angular.module('contacts', []);
- function importKey(file) {
- var reader = new FileReader();
- reader.onload = function(e) {
- scope.importKey(e.target.result);
- };
- reader.readAsText(file);
+ngModule.directive('keyfileInput', function() {
+ return function(scope, elm) {
+ elm.on('change', function(e) {
+ for (var i = 0; i < e.target.files.length; i++) {
+ importKey(e.target.files.item(i));
}
- };
- });
+ });
- ngModule.directive('keyfileBtn', function() {
- return function(scope, elm) {
- elm.on('click touchstart', function(e) {
- e.preventDefault();
- document.querySelector('#keyfile-input').click();
- });
- };
- });
+ function importKey(file) {
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ scope.importKey(e.target.result);
+ };
+ reader.readAsText(file);
+ }
+ };
+});
+
+ngModule.directive('keyfileBtn', function() {
+ return function(scope, elm) {
+ elm.on('click touchstart', function(e) {
+ e.preventDefault();
+ document.querySelector('#keyfile-input').click();
+ });
+ };
+});
- return ContactsCtrl;
-});
\ No newline at end of file
+module.exports = ContactsCtrl;
\ No newline at end of file
diff --git a/src/js/controller/dialog.js b/src/js/controller/dialog.js
index 45108c1..8e33e22 100644
--- a/src/js/controller/dialog.js
+++ b/src/js/controller/dialog.js
@@ -1,16 +1,14 @@
-define(function() {
- 'use strict';
+'use strict';
- var DialogCtrl = function($scope) {
- $scope.confirm = function(ok) {
- $scope.state.dialog.open = false;
+var DialogCtrl = function($scope) {
+ $scope.confirm = function(ok) {
+ $scope.state.dialog.open = false;
- if ($scope.state.dialog.callback) {
- $scope.state.dialog.callback(ok);
- }
- $scope.state.dialog.callback = undefined;
- };
+ if ($scope.state.dialog.callback) {
+ $scope.state.dialog.callback(ok);
+ }
+ $scope.state.dialog.callback = undefined;
};
+};
- return DialogCtrl;
-});
\ No newline at end of file
+module.exports = DialogCtrl;
\ No newline at end of file
diff --git a/src/js/controller/login-existing.js b/src/js/controller/login-existing.js
index 35aa6bd..006c2ec 100644
--- a/src/js/controller/login-existing.js
+++ b/src/js/controller/login-existing.js
@@ -1,73 +1,71 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var appController = require('js/app-controller');
+var appController = require('../app-controller');
- var LoginExistingCtrl = function($scope, $location, $routeParams) {
- if (!appController._emailDao && !$routeParams.dev) {
- $location.path('/'); // init app
- return;
- }
+var LoginExistingCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
- var emailDao = appController._emailDao;
+ var emailDao = appController._emailDao;
- $scope.buttonEnabled = true;
+ $scope.buttonEnabled = true;
+ $scope.incorrect = false;
+
+ $scope.change = function() {
$scope.incorrect = false;
+ };
+
+ $scope.confirmPassphrase = function() {
+ if (!$scope.passphrase) {
+ return;
+ }
- $scope.change = function() {
- $scope.incorrect = false;
- };
+ // disable button once loggin has started
+ $scope.buttonEnabled = false;
+ $scope.incorrect = false;
+ unlockCrypto();
+ };
- $scope.confirmPassphrase = function() {
- if (!$scope.passphrase) {
+ function unlockCrypto() {
+ var userId = emailDao._account.emailAddress;
+ emailDao._keychain.getUserKeyPair(userId, function(err, keypair) {
+ if (err) {
+ handleError(err);
return;
}
- // disable button once loggin has started
- $scope.buttonEnabled = false;
- $scope.incorrect = false;
- unlockCrypto();
- };
-
- function unlockCrypto() {
- var userId = emailDao._account.emailAddress;
- emailDao._keychain.getUserKeyPair(userId, function(err, keypair) {
- if (err) {
- handleError(err);
- return;
- }
+ emailDao.unlock({
+ keypair: keypair,
+ passphrase: $scope.passphrase
+ }, onUnlock);
+ });
+ }
- emailDao.unlock({
- keypair: keypair,
- passphrase: $scope.passphrase
- }, onUnlock);
- });
+ function onUnlock(err) {
+ if (err) {
+ $scope.incorrect = true;
+ $scope.buttonEnabled = true;
+ $scope.$apply();
+ return;
}
- function onUnlock(err) {
+ appController._auth.storeCredentials(function(err) {
if (err) {
- $scope.incorrect = true;
- $scope.buttonEnabled = true;
- $scope.$apply();
- return;
+ return $scope.onError(err);
}
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
-
- $location.path('/desktop');
- $scope.$apply();
- });
- }
+ $location.path('/desktop');
+ $scope.$apply();
+ });
+ }
- function handleError(err) {
- $scope.incorrect = true;
- $scope.buttonEnabled = true;
- $scope.onError(err);
- }
- };
+ function handleError(err) {
+ $scope.incorrect = true;
+ $scope.buttonEnabled = true;
+ $scope.onError(err);
+ }
+};
- return LoginExistingCtrl;
-});
\ No newline at end of file
+module.exports = LoginExistingCtrl;
\ No newline at end of file
diff --git a/src/js/controller/login-initial.js b/src/js/controller/login-initial.js
index 8c04c7d..231f74e 100644
--- a/src/js/controller/login-initial.js
+++ b/src/js/controller/login-initial.js
@@ -1,121 +1,119 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var appController = require('js/app-controller');
+var appController = require('../app-controller');
- var LoginInitialCtrl = function($scope, $location, $routeParams) {
- if (!appController._emailDao && !$routeParams.dev) {
- $location.path('/'); // init app
- return;
- }
+var LoginInitialCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
- var emailDao = appController._emailDao,
- states, termsMsg = 'You must accept the Terms of Service to continue.';
+ var emailDao = appController._emailDao,
+ states, termsMsg = 'You must accept the Terms of Service to continue.';
- states = {
- IDLE: 1,
- PROCESSING: 2,
- DONE: 3
- };
- $scope.state.ui = states.IDLE; // initial state
-
- //
- // scope functions
- //
-
- /**
- * Continue to key import screen
- */
- $scope.importKey = function() {
- if (!$scope.state.agree) {
- $scope.onError({
- message: termsMsg
- });
- return;
- }
+ states = {
+ IDLE: 1,
+ PROCESSING: 2,
+ DONE: 3
+ };
+ $scope.state.ui = states.IDLE; // initial state
+
+ //
+ // scope functions
+ //
+
+ /**
+ * Continue to key import screen
+ */
+ $scope.importKey = function() {
+ if (!$scope.state.agree) {
+ $scope.onError({
+ message: termsMsg
+ });
+ return;
+ }
- // sing up to newsletter
- $scope.signUpToNewsletter();
- // go to key import
- $location.path('/login-new-device');
- };
+ // sing up to newsletter
+ $scope.signUpToNewsletter();
+ // go to key import
+ $location.path('/login-new-device');
+ };
- /**
- * Continue to keygen
- */
- $scope.generateKey = function() {
- if (!$scope.state.agree) {
- $scope.onError({
- message: termsMsg
- });
- return;
- }
+ /**
+ * Continue to keygen
+ */
+ $scope.generateKey = function() {
+ if (!$scope.state.agree) {
+ $scope.onError({
+ message: termsMsg
+ });
+ return;
+ }
- // sing up to newsletter
- $scope.signUpToNewsletter();
- // go to set keygen screen
- $scope.setState(states.PROCESSING);
+ // sing up to newsletter
+ $scope.signUpToNewsletter();
+ // go to set keygen screen
+ $scope.setState(states.PROCESSING);
+
+ setTimeout(function() {
+ emailDao.unlock({
+ passphrase: undefined // generate key without passphrase
+ }, function(err) {
+ if (err) {
+ $scope.setState(states.IDLE);
+ $scope.onError(err);
+ return;
+ }
- setTimeout(function() {
- emailDao.unlock({
- passphrase: undefined // generate key without passphrase
- }, function(err) {
+ appController._auth.storeCredentials(function(err) {
if (err) {
- $scope.setState(states.IDLE);
- $scope.onError(err);
- return;
+ return $scope.onError(err);
}
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
-
- $location.path('/desktop');
- $scope.$apply();
- });
+ $location.path('/desktop');
+ $scope.$apply();
});
- }, 500);
- };
-
- /**
- * [signUpToNewsletter description]
- * @param {Function} callback (optional)
- */
- $scope.signUpToNewsletter = function(callback) {
- if (!$scope.state.newsletter) {
- return;
- }
+ });
+ }, 500);
+ };
- var address = emailDao._account.emailAddress;
- var uri = 'https://whiteout.us8.list-manage.com/subscribe/post?u=52ea5a9e1be9e1d194f184158&id=6538e8f09f';
+ /**
+ * [signUpToNewsletter description]
+ * @param {Function} callback (optional)
+ */
+ $scope.signUpToNewsletter = function(callback) {
+ if (!$scope.state.newsletter) {
+ return;
+ }
- var formData = new FormData();
- formData.append('EMAIL', address);
- formData.append('b_52ea5a9e1be9e1d194f184158_6538e8f09f', '');
+ var address = emailDao._account.emailAddress;
+ var uri = 'https://whiteout.us8.list-manage.com/subscribe/post?u=52ea5a9e1be9e1d194f184158&id=6538e8f09f';
- var xhr = new XMLHttpRequest();
- xhr.open('post', uri, true);
+ var formData = new FormData();
+ formData.append('EMAIL', address);
+ formData.append('b_52ea5a9e1be9e1d194f184158_6538e8f09f', '');
- xhr.onload = function() {
- if (callback) {
- callback(null, xhr);
- }
- };
+ var xhr = new XMLHttpRequest();
+ xhr.open('post', uri, true);
- xhr.onerror = function(err) {
- if (callback) {
- callback(err);
- }
- };
-
- xhr.send(formData);
+ xhr.onload = function() {
+ if (callback) {
+ callback(null, xhr);
+ }
};
- $scope.setState = function(state) {
- $scope.state.ui = state;
+ xhr.onerror = function(err) {
+ if (callback) {
+ callback(err);
+ }
};
+
+ xhr.send(formData);
+ };
+
+ $scope.setState = function(state) {
+ $scope.state.ui = state;
};
+};
- return LoginInitialCtrl;
-});
\ No newline at end of file
+module.exports = LoginInitialCtrl;
\ No newline at end of file
diff --git a/src/js/controller/login-new-device.js b/src/js/controller/login-new-device.js
index b39091a..c9f16d1 100644
--- a/src/js/controller/login-new-device.js
+++ b/src/js/controller/login-new-device.js
@@ -1,141 +1,138 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var angular = require('angular'),
- appController = require('js/app-controller');
+var appController = require('../app-controller');
- var LoginExistingCtrl = function($scope, $location, $routeParams) {
- if (!appController._emailDao && !$routeParams.dev) {
- $location.path('/'); // init app
- return;
- }
-
- var emailDao = appController._emailDao,
- pgp = appController._pgp;
+var LoginExistingCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
- $scope.incorrect = false;
+ var emailDao = appController._emailDao,
+ pgp = appController._pgp;
- $scope.confirmPassphrase = function() {
- $scope.incorrect = false;
- unlockCrypto();
- };
+ $scope.incorrect = false;
- function unlockCrypto() {
- var userId = emailDao._account.emailAddress;
- // check if user already has a public key on the key server
- emailDao._keychain.getUserKeyPair(userId, function(err, keypair) {
- if (err) {
- $scope.onError(err);
- return;
- }
+ $scope.confirmPassphrase = function() {
+ $scope.incorrect = false;
+ unlockCrypto();
+ };
- keypair = keypair || {};
+ function unlockCrypto() {
+ var userId = emailDao._account.emailAddress;
+ // check if user already has a public key on the key server
+ emailDao._keychain.getUserKeyPair(userId, function(err, keypair) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
- // extract public key from private key block if missing in key file
- if (!$scope.key.publicKeyArmored || $scope.key.publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
- try {
- $scope.key.publicKeyArmored = pgp.extractPublicKey($scope.key.privateKeyArmored);
- } catch (e) {
- $scope.onError(new Error('Error parsing public key from private key!'));
- return;
- }
- }
+ keypair = keypair || {};
- // parse keypair params
- var privKeyParams, pubKeyParams;
+ // extract public key from private key block if missing in key file
+ if (!$scope.key.publicKeyArmored || $scope.key.publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
try {
- privKeyParams = pgp.getKeyParams($scope.key.privateKeyArmored);
- pubKeyParams = pgp.getKeyParams($scope.key.publicKeyArmored);
+ $scope.key.publicKeyArmored = pgp.extractPublicKey($scope.key.privateKeyArmored);
} catch (e) {
- $scope.onError(new Error('Error reading key params!'));
+ $scope.onError(new Error('Error parsing public key from private key!'));
return;
}
+ }
- // set parsed private key
- keypair.privateKey = {
- _id: privKeyParams._id,
+ // parse keypair params
+ var privKeyParams, pubKeyParams;
+ try {
+ privKeyParams = pgp.getKeyParams($scope.key.privateKeyArmored);
+ pubKeyParams = pgp.getKeyParams($scope.key.publicKeyArmored);
+ } catch (e) {
+ $scope.onError(new Error('Error reading key params!'));
+ return;
+ }
+
+ // set parsed private key
+ keypair.privateKey = {
+ _id: privKeyParams._id,
+ userId: userId,
+ userIds: privKeyParams.userIds,
+ encryptedKey: $scope.key.privateKeyArmored
+ };
+
+ if (!keypair.publicKey) {
+ // there is no public key on the key server yet... use parsed
+ keypair.publicKey = {
+ _id: pubKeyParams._id,
userId: userId,
- userIds: privKeyParams.userIds,
- encryptedKey: $scope.key.privateKeyArmored
+ userIds: pubKeyParams.userIds,
+ publicKey: $scope.key.publicKeyArmored
};
+ }
- if (!keypair.publicKey) {
- // there is no public key on the key server yet... use parsed
- keypair.publicKey = {
- _id: pubKeyParams._id,
- userId: userId,
- userIds: pubKeyParams.userIds,
- publicKey: $scope.key.publicKeyArmored
- };
+ // import and validate keypair
+ emailDao.unlock({
+ keypair: keypair,
+ passphrase: $scope.passphrase
+ }, function(err) {
+ if (err) {
+ $scope.incorrect = true;
+ $scope.onError(err);
+ return;
}
- // import and validate keypair
- emailDao.unlock({
- keypair: keypair,
- passphrase: $scope.passphrase
- }, function(err) {
- if (err) {
- $scope.incorrect = true;
- $scope.onError(err);
- return;
- }
-
- emailDao._keychain.putUserKeyPair(keypair, onUnlock);
- });
+ emailDao._keychain.putUserKeyPair(keypair, onUnlock);
});
+ });
+ }
+
+ function onUnlock(err) {
+ if (err) {
+ $scope.onError(err);
+ return;
}
- function onUnlock(err) {
+ appController._auth.storeCredentials(function(err) {
if (err) {
- $scope.onError(err);
- return;
+ return $scope.onError(err);
}
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
+ $location.path('/desktop');
+ $scope.$apply();
+ });
+ }
+};
- $location.path('/desktop');
- $scope.$apply();
- });
- }
- };
+var ngModule = angular.module('login-new-device', []);
+ngModule.directive('fileReader', function() {
+ return function(scope, elm) {
+ elm.bind('change', function(e) {
+ var files = e.target.files,
+ reader = new FileReader();
- var ngModule = angular.module('login-new-device', []);
- ngModule.directive('fileReader', function() {
- return function(scope, elm) {
- elm.bind('change', function(e) {
- var files = e.target.files,
- reader = new FileReader();
+ if (files.length === 0) {
+ return;
+ }
+
+ reader.onload = function(e) {
+ var rawKeys = e.target.result,
+ index = rawKeys.indexOf('-----BEGIN PGP PRIVATE KEY BLOCK-----'),
+ keyParts;
- if (files.length === 0) {
+ if (index === -1) {
+ scope.onError(new Error('Error parsing private PGP key block!'));
return;
}
- reader.onload = function(e) {
- var rawKeys = e.target.result,
- index = rawKeys.indexOf('-----BEGIN PGP PRIVATE KEY BLOCK-----'),
- keyParts;
-
- if (index === -1) {
- scope.onError(new Error('Error parsing private PGP key block!'));
- return;
- }
-
- keyParts = {
- publicKeyArmored: rawKeys.substring(0, index).trim(),
- privateKeyArmored: rawKeys.substring(index, rawKeys.length).trim()
- };
-
- scope.$apply(function() {
- scope.key = keyParts;
- });
+ keyParts = {
+ publicKeyArmored: rawKeys.substring(0, index).trim(),
+ privateKeyArmored: rawKeys.substring(index, rawKeys.length).trim()
};
- reader.readAsText(files[0]);
- });
- };
- });
- return LoginExistingCtrl;
-});
\ No newline at end of file
+ scope.$apply(function() {
+ scope.key = keyParts;
+ });
+ };
+ reader.readAsText(files[0]);
+ });
+ };
+});
+
+module.exports = LoginExistingCtrl;
\ No newline at end of file
diff --git a/src/js/controller/login-privatekey-download.js b/src/js/controller/login-privatekey-download.js
index 48860ff..3e7aec5 100644
--- a/src/js/controller/login-privatekey-download.js
+++ b/src/js/controller/login-privatekey-download.js
@@ -1,134 +1,132 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var appController = require('js/app-controller');
+var appController = require('../app-controller');
- var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams) {
- if (!appController._emailDao && !$routeParams.dev) {
- $location.path('/'); // init app
- return;
+var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
+ var keychain = appController._keychain,
+ emailDao = appController._emailDao,
+ userId = emailDao._account.emailAddress;
+
+ $scope.step = 1;
+
+ $scope.handlePaste = function(event) {
+ var evt = event;
+ if (evt.originalEvent) {
+ evt = evt.originalEvent;
}
- var keychain = appController._keychain,
- emailDao = appController._emailDao,
- userId = emailDao._account.emailAddress;
+ var value = evt.clipboardData.getData('text/plain');
+ if (!value) {
+ return;
+ }
- $scope.step = 1;
+ value = value.replace(/-/g, '');
+ $scope.code0 = value.slice(0, 4);
+ $scope.code1 = value.slice(4, 8);
+ $scope.code2 = value.slice(8, 12);
+ $scope.code3 = value.slice(12, 16);
+ $scope.code4 = value.slice(16, 20);
+ $scope.code5 = value.slice(20, 24);
+ };
- $scope.handlePaste = function(event) {
- var evt = event;
- if (evt.originalEvent) {
- evt = evt.originalEvent;
- }
+ $scope.verifyRecoveryToken = function(callback) {
+ if (!$scope.recoveryToken) {
+ $scope.onError(new Error('Please set the recovery token!'));
+ return;
+ }
- var value = evt.clipboardData.getData('text/plain');
- if (!value) {
+ keychain.getUserKeyPair(userId, function(err, keypair) {
+ if (err) {
+ $scope.onError(err);
return;
}
- value = value.replace(/-/g, '');
- $scope.code0 = value.slice(0, 4);
- $scope.code1 = value.slice(4, 8);
- $scope.code2 = value.slice(8, 12);
- $scope.code3 = value.slice(12, 16);
- $scope.code4 = value.slice(16, 20);
- $scope.code5 = value.slice(20, 24);
- };
-
- $scope.verifyRecoveryToken = function(callback) {
- if (!$scope.recoveryToken) {
- $scope.onError(new Error('Please set the recovery token!'));
- return;
- }
+ // remember for storage later
+ $scope.cachedKeypair = keypair;
- keychain.getUserKeyPair(userId, function(err, keypair) {
+ keychain.downloadPrivateKey({
+ userId: userId,
+ keyId: keypair.publicKey._id,
+ recoveryToken: $scope.recoveryToken.toUpperCase()
+ }, function(err, encryptedPrivateKey) {
if (err) {
$scope.onError(err);
return;
}
- // remember for storage later
- $scope.cachedKeypair = keypair;
+ $scope.encryptedPrivateKey = encryptedPrivateKey;
+ callback();
+ });
+ });
+ };
- keychain.downloadPrivateKey({
- userId: userId,
- keyId: keypair.publicKey._id,
- recoveryToken: $scope.recoveryToken.toUpperCase()
- }, function(err, encryptedPrivateKey) {
- if (err) {
- $scope.onError(err);
- return;
- }
+ $scope.decryptAndStorePrivateKeyLocally = function() {
+ var inputCode = '' + $scope.code0 + $scope.code1 + $scope.code2 + $scope.code3 + $scope.code4 + $scope.code5;
- $scope.encryptedPrivateKey = encryptedPrivateKey;
- callback();
- });
- });
- };
+ if (!inputCode) {
+ $scope.onError(new Error('Please enter the keychain code!'));
+ return;
+ }
- $scope.decryptAndStorePrivateKeyLocally = function() {
- var inputCode = '' + $scope.code0 + $scope.code1 + $scope.code2 + $scope.code3 + $scope.code4 + $scope.code5;
+ var options = $scope.encryptedPrivateKey;
+ options.code = inputCode.toUpperCase();
- if (!inputCode) {
- $scope.onError(new Error('Please enter the keychain code!'));
+ keychain.decryptAndStorePrivateKeyLocally(options, function(err, privateKey) {
+ if (err) {
+ $scope.onError(err);
return;
}
- var options = $scope.encryptedPrivateKey;
- options.code = inputCode.toUpperCase();
+ // add private key to cached keypair object
+ $scope.cachedKeypair.privateKey = privateKey;
- keychain.decryptAndStorePrivateKeyLocally(options, function(err, privateKey) {
+ // try empty passphrase
+ emailDao.unlock({
+ keypair: $scope.cachedKeypair,
+ passphrase: undefined
+ }, function(err) {
if (err) {
- $scope.onError(err);
+ // go to passphrase login screen
+ $scope.goTo('/login-existing');
return;
}
- // add private key to cached keypair object
- $scope.cachedKeypair.privateKey = privateKey;
-
- // try empty passphrase
- emailDao.unlock({
- keypair: $scope.cachedKeypair,
- passphrase: undefined
- }, function(err) {
+ // passphrase is corrent ... go to main app
+ appController._auth.storeCredentials(function(err) {
if (err) {
- // go to passphrase login screen
- $scope.goTo('/login-existing');
- return;
+ return $scope.onError(err);
}
- // passphrase is corrent ... go to main app
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
-
- $scope.goTo('/desktop');
- });
+ $scope.goTo('/desktop');
});
});
- };
+ });
+ };
- $scope.goForward = function() {
- if ($scope.step === 1) {
- $scope.verifyRecoveryToken(function() {
- $scope.step++;
- $scope.$apply();
- });
- return;
- }
+ $scope.goForward = function() {
+ if ($scope.step === 1) {
+ $scope.verifyRecoveryToken(function() {
+ $scope.step++;
+ $scope.$apply();
+ });
+ return;
+ }
- if ($scope.step === 2) {
- $scope.decryptAndStorePrivateKeyLocally();
- return;
- }
- };
+ if ($scope.step === 2) {
+ $scope.decryptAndStorePrivateKeyLocally();
+ return;
+ }
+ };
- $scope.goTo = function(location) {
- $location.path(location);
- $scope.$apply();
- };
+ $scope.goTo = function(location) {
+ $location.path(location);
+ $scope.$apply();
};
+};
- return LoginPrivateKeyDownloadCtrl;
-});
\ No newline at end of file
+module.exports = LoginPrivateKeyDownloadCtrl;
\ No newline at end of file
diff --git a/src/js/controller/login-set-credentials.js b/src/js/controller/login-set-credentials.js
index 5b34df0..74bbe0b 100644
--- a/src/js/controller/login-set-credentials.js
+++ b/src/js/controller/login-set-credentials.js
@@ -1,120 +1,118 @@
-define(function(require) {
- 'use strict';
-
- var ENCRYPTION_METHOD_NONE = 0;
- var ENCRYPTION_METHOD_STARTTLS = 1;
- var ENCRYPTION_METHOD_TLS = 2;
-
- var appCtrl = require('js/app-controller'),
- config = require('js/app-config').config;
-
- var SetCredentialsCtrl = function($scope, $location, $routeParams) {
- if (!appCtrl._auth && !$routeParams.dev) {
- $location.path('/'); // init app
- return;
+'use strict';
+
+var ENCRYPTION_METHOD_NONE = 0;
+var ENCRYPTION_METHOD_STARTTLS = 1;
+var ENCRYPTION_METHOD_TLS = 2;
+
+var appCtrl = require('../app-controller'),
+ config = require('../app-config').config;
+
+var SetCredentialsCtrl = function($scope, $location, $routeParams) {
+ if (!appCtrl._auth && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
+ var auth = appCtrl._auth;
+ var doctor = appCtrl._doctor;
+
+ //
+ // Presets and Settings
+ //
+
+ var provider = $location.search().provider;
+ $scope.hasProviderPreset = !!config[provider];
+ $scope.useOAuth = !!auth.oauthToken;
+ $scope.showDetails = (provider === 'custom');
+
+ if ($scope.useOAuth) {
+ $scope.emailAddress = auth.emailAddress;
+ }
+
+ if ($scope.hasProviderPreset) {
+ // use non-editable presets
+
+ // SMTP config
+ $scope.smtpHost = config[provider].smtp.host;
+ $scope.smtpPort = config[provider].smtp.port;
+ $scope.smtpCert = config[provider].smtp.ca;
+ $scope.smtpPinned = config[provider].smtp.pinned;
+
+ // transport encryption method
+ if (config[provider].smtp.secure && !config[provider].smtp.ignoreTLS) {
+ $scope.smtpEncryption = ENCRYPTION_METHOD_TLS;
+ } else if (!config[provider].smtp.secure && !config[provider].smtp.ignoreTLS) {
+ $scope.smtpEncryption = ENCRYPTION_METHOD_STARTTLS;
+ } else {
+ $scope.smtpEncryption = ENCRYPTION_METHOD_NONE;
}
- var auth = appCtrl._auth;
- var doctor = appCtrl._doctor;
-
- //
- // Presets and Settings
- //
-
- var provider = $location.search().provider;
- $scope.hasProviderPreset = !!config[provider];
- $scope.useOAuth = !!auth.oauthToken;
- $scope.showDetails = (provider === 'custom');
-
- if ($scope.useOAuth) {
- $scope.emailAddress = auth.emailAddress;
+ // IMAP config
+ $scope.imapHost = config[provider].imap.host;
+ $scope.imapPort = config[provider].imap.port;
+ $scope.imapCert = config[provider].imap.ca;
+ $scope.imapPinned = config[provider].imap.pinned;
+
+ // transport encryption method
+ if (config[provider].imap.secure && !config[provider].imap.ignoreTLS) {
+ $scope.imapEncryption = ENCRYPTION_METHOD_TLS;
+ } else if (!config[provider].imap.secure && !config[provider].imap.ignoreTLS) {
+ $scope.imapEncryption = ENCRYPTION_METHOD_STARTTLS;
+ } else {
+ $scope.imapEncryption = ENCRYPTION_METHOD_NONE;
}
-
- if ($scope.hasProviderPreset) {
- // use non-editable presets
-
- // SMTP config
- $scope.smtpHost = config[provider].smtp.host;
- $scope.smtpPort = config[provider].smtp.port;
- $scope.smtpCert = config[provider].smtp.ca;
- $scope.smtpPinned = config[provider].smtp.pinned;
-
- // transport encryption method
- if (config[provider].smtp.secure && !config[provider].smtp.ignoreTLS) {
- $scope.smtpEncryption = ENCRYPTION_METHOD_TLS;
- } else if (!config[provider].smtp.secure && !config[provider].smtp.ignoreTLS) {
- $scope.smtpEncryption = ENCRYPTION_METHOD_STARTTLS;
- } else {
- $scope.smtpEncryption = ENCRYPTION_METHOD_NONE;
+ }
+
+ $scope.test = function() {
+ // parse the