diff --git a/.gitignore b/.gitignore
index d9c457d..97d8d25 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,4 @@ src/css/
dist/
release/
test/integration/src/
-src/lib/*.js
-src/js/crypto/aes-gcm.js
-src/js/crypto/util.js
.elasticbeanstalk/
diff --git a/.jshintrc b/.jshintrc
index c6b8a83..79d663e 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -23,15 +23,7 @@
"importScripts",
"process",
"Event",
- "QUnit",
- "test",
- "asyncTest",
- "ok",
- "equal",
- "deepEqual",
- "start",
"chrome",
- "requirejs",
"define",
"self",
"describe",
@@ -42,7 +34,13 @@
"before",
"beforeEach",
"after",
- "afterEach"
+ "afterEach",
+ "FastClick",
+ "angular",
+ "forge",
+ "Lawnchair",
+ "_",
+ "openpgp"
],
"globals": {
diff --git a/Gruntfile.js b/Gruntfile.js
index fa57114..dacb48e 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -6,6 +6,7 @@ module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
+
connect: {
dev: {
options: {
@@ -47,8 +48,9 @@ module.exports = function(grunt) {
},
clean: {
- dist: ['dist', 'src/lib/*.js', 'test/lib', 'test/integration/src']
+ dist: ['dist', 'test/lib', 'test/integration/src']
},
+
sass: {
dist: {
files: {
@@ -57,6 +59,7 @@ module.exports = function(grunt) {
}
}
},
+
autoprefixer: {
options: {
browsers: ['last 2 versions']
@@ -68,9 +71,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 +83,7 @@ module.exports = function(grunt) {
}
}
},
+
watch: {
css: {
files: ['src/sass/**/*.scss'],
@@ -86,7 +91,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,36 +102,52 @@ module.exports = function(grunt) {
tasks: ['copy:app', 'copy:ca', 'copy:tpl', 'copy:img', 'copy:font', 'manifest-dev', 'manifest']
}
},
- copy: {
- npm: {
- expand: true,
- flatten: true,
- cwd: 'node_modules/',
- 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'
- ],
- dest: 'src/lib/'
+
+ browserify: {
+ all: {
+ files: {
+ 'dist/js/app.min.js': ['src/js/app.js']
+ },
+ options: {
+ external: ['node-forge', 'net', 'tls'] // common.js apis not required at build time
+ }
},
+ /* TODO:
+ tls-worker: {},
+ mailreader-worker: {},
+ pbkdf2-worker: {},
+ unitTest: {},
+ unitTest: {},
+ integrationTest: {}
+ */
+ },
+
+ uglify: {
+ all: {
+ 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',
+ 'src/lib/fastclick/fastclick.js',
+ 'node_modules/ng-infinite-scroll/build/ng-infinite-scroll.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',
+ 'node_modules/dompurify/purify.js',
+ 'dist/js/app.min.js'
+ ]
+ }
+ },
+ options: {
+ banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n'
+ }
+ },
+
+ copy: {
npmDev: {
expand: true,
flatten: true,
@@ -134,24 +155,6 @@ module.exports = function(grunt) {
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,
- cwd: 'src/lib/',
- src: ['**'],
- dest: 'dist/lib/'
- },
- js: {
- expand: true,
- cwd: 'src/js/',
- src: ['**'],
- dest: 'dist/js/'
- },
font: {
expand: true,
cwd: 'src/font/',
@@ -170,12 +173,6 @@ module.exports = function(grunt) {
src: ['*'],
dest: 'dist/tpl/'
},
- ca: {
- expand: true,
- cwd: 'src/ca/',
- src: ['*'],
- dest: 'dist/ca/'
- },
app: {
expand: true,
cwd: 'src/',
@@ -200,16 +197,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: '/'
}
},
@@ -226,22 +213,13 @@ module.exports = function(grunt) {
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');
@@ -252,14 +230,14 @@ 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');
// Build tasks
- grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
+ grunt.registerTask('dist-npm', ['copy:npmDev']);
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
+ grunt.registerTask('dist-js', ['browserify', 'uglify']);
grunt.registerTask('dist-copy', ['copy']);
- grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy', 'manifest']);
+ grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-js', 'dist-copy', 'manifest']);
// Test/Dev tasks
grunt.registerTask('dev', ['connect:dev']);
diff --git a/package.json b/package.json
index 1ded9b2..a6e3162 100644
--- a/package.json
+++ b/package.json
@@ -29,20 +29,21 @@
"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",
+ "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.9",
+ "wo-smtpclient": "^0.3.8"
},
"devDependencies": {
"angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version",
@@ -50,19 +51,20 @@
"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-manifest": "^0.4.0",
"grunt-mocha": "~0.4.1",
- "grunt-node-webkit-builder": "~0.1.17",
"mocha": "~1.13.0",
"sinon": "~1.7.3"
}
-}
+}
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
index d0a577f..c1fad5b 100644
--- a/src/index.html
+++ b/src/index.html
@@ -26,9 +26,7 @@
-
-
-
+
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
- };
+ 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
+};
- /**
- * 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}'
- };
-
- 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..82e0408 100644
--- a/src/js/app-controller.js
+++ b/src/js/app-controller.js
@@ -1,271 +1,268 @@
/**
* 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;
+'use strict';
- var self = {};
+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;
- /**
- * Start the application.
- */
- self.start = function(options, callback) {
- if (self.started) {
- return callback();
- }
+var self = {};
- self.started = true;
- self.onError = options.onError;
+/**
+ * Start the application.
+ */
+self.start = function(options, callback) {
+ if (self.started) {
+ return callback();
+ }
- // 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();
- }
+ self.started = true;
+ self.onError = options.onError;
- function onDeviceReady() {
- axe.debug('Starting app.');
+ // 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();
+ }
- self.buildModules();
+ function onDeviceReady() {
+ axe.debug('Starting app.');
- // Handle offline and online gracefully
- window.addEventListener('online', self.onConnect.bind(self, self.onError));
- window.addEventListener('offline', self.onDisconnect.bind(self));
+ self.buildModules();
- self._appConfigStore.init('app-config', callback);
- }
+ // Handle offline and online gracefully
+ window.addEventListener('online', self.onConnect.bind(self, self.onError));
+ window.addEventListener('offline', self.onDisconnect.bind(self));
+
+ self._appConfigStore.init('app-config', callback);
+ }
+};
+
+/**
+ * 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
+ });
};
- /**
- * Initialize the dependency tree.
- */
- self.buildModules = function() {
- var lawnchairDao, restDao, pubkeyDao, privkeyDao, crypto, emailDao, keychain, pgp, userStorage, pgpbuilder, oauth, appConfigStore, auth;
+ 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();
- // start the mailreader's worker thread
- mailreader.startWorker(config.workerPath + '/../lib/mailreader-parser-worker.js');
+ emailDao.onError = self.onError;
+};
- // 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'));
+/**
+ * Calls runtime hooks to check if an app update is available.
+ */
+self.checkForUpdate = function() {
+ self._updateHandler.checkForUpdate(self.onError);
+};
- 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);
+/**
+ * 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) {
+ if (err) {
+ callback(err);
+ return;
+ }
- self.onError({
- title: str.updatePublicKeyTitle,
- message: message,
- positiveBtnStr: str.updatePublicKeyPosBtn,
- negativeBtnStr: str.updatePublicKeyNegBtn,
- showNegativeBtn: true,
- callback: callback
+ // Migrate the databases if necessary
+ self._updateHandler.update(onUpdate);
+ });
+
+ function onUpdate(err) {
+ if (err) {
+ callback({
+ errMsg: 'Update failed, please reinstall the app.',
+ err: err
});
+ return;
+ }
+
+ // account information for the email dao
+ var account = {
+ realname: options.realname,
+ emailAddress: options.emailAddress,
+ asymKeySize: config.asymKeySize
};
- 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;
- };
-
- /**
- * Calls runtime hooks to check if an app update is available.
- */
- self.checkForUpdate = function() {
- self._updateHandler.checkForUpdate(self.onError);
- };
-
- /**
- * 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
+ self._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.
+ */
+self.isOnline = function() {
+ return navigator.onLine;
+};
- // account information for the email dao
- var account = {
- realname: options.realname,
- emailAddress: options.emailAddress,
- asymKeySize: config.asymKeySize
- };
+/**
+ * Event handler that is called when the user agent goes offline.
+ */
+self.onDisconnect = function() {
+ self._emailDao.onDisconnect();
+};
- // init email dao
- self._emailDao.init({
- account: account
- }, function(err, keypair) {
- if (err) {
- callback(err);
- return;
- }
-
- callback(null, keypair);
- });
+/**
+ * Log the current user out by clear the app config store and deleting instances of imap-client and pgp-mailer.
+ */
+self.logout = function() {
+ // clear app config store
+ self._auth.logout(function(err) {
+ if (err) {
+ self.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
+ self._emailDao.onDisconnect(function(err) {
if (err) {
self.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.
+ */
+self.onConnect = function(callback) {
+ if (!self.isOnline() || !self._emailDao || !self._emailDao._account) {
+ // prevent connection infinite loop
+ callback();
+ return;
+ }
+
+ self._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;
- 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);
- // 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);
- // 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);
+ }
- // connect to clients
- self._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) : ''));
- 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;
+ }
- 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);
+ }
+};
- axe.debug('Reconnect attempt complete.');
- });
- }, config.reconnectInterval);
- }
- };
-
- return self;
-});
\ No newline at end of file
+exports = self;
\ No newline at end of file
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
});
-
- app.run(function($rootScope) {
- // global state... inherited to all child scopes
- $rootScope.state = {};
-
- // attach global error handler
- errorUtil.attachHandler($rootScope);
-
- // attach the back button handler to the root scope
- backButtonUtil.attachHandler($rootScope);
-
- // attach fastclick
- FastClick.attach(document.body);
+ $routeProvider.when('/login', {
+ templateUrl: 'tpl/login.html',
+ controller: LoginCtrl
});
-
- // 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);
-
- // manually bootstrap angular due to require.js
- angular.element().ready(function() {
- angular.bootstrap(document, ['mail']);
+ $routeProvider.when('/login-set-credentials', {
+ templateUrl: 'tpl/login-set-credentials.html',
+ controller: LoginSetCredentialsCtrl
});
-});
\ No newline at end of file
+ $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);
+
+ // attach the back button handler to the root scope
+ backButtonUtil.attachHandler($rootScope);
+
+ // attach fastclick
+ FastClick.attach(document.body);
+});
+
+// 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..e7780d1 100644
--- a/src/js/bo/auth.js
+++ b/src/js/bo/auth.js
@@ -1,355 +1,210 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var axe = require('axe'),
- str = require('js/app-config').string;
+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';
+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;
- };
+/**
+ * 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);
- }
-
- 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;
-
- done();
- });
- return;
- }
-
- 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
- }
- },
- 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);
- }
-
- self._appConfigStore.storeList([self.imap], IMAP_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
-
- self._appConfigStore.storeList([self.provider], PROVIDER_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
-
- self._appConfigStore.storeList([self.emailAddress], EMAIL_ADDR_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
-
- self._appConfigStore.storeList([self.username], USERNAME_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);
- }
-
- self.credentialsDirty = false;
- callback();
- });
- return;
- }
-
- self._pgp.encrypt(self.password, undefined, function(err, ciphertext) {
- if (err) {
- return callback(err);
- }
-
- self._appConfigStore.storeList([ciphertext], PASSWD_DB_KEY, function(err) {
- if (err) {
- return callback(err);
- }
-
- self.credentialsDirty = false;
- callback();
- });
- });
- });
- });
- });
- });
- });
- });
- };
-
- /**
- * 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
- });
- }
+/**
+ * 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);
}
- callback(null, {
- emailAddress: self.emailAddress,
- realname: self.realname
- });
+ chooseLogin();
});
- };
+ return;
+ }
- /**
- * 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;
+ chooseLogin();
- 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);
- }
-
- // 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) {
+ function chooseLogin() {
+ if (self.provider === 'gmail' && !self.password) {
+ // oauth login for gmail
+ self.getOAuthToken(function(err) {
if (err) {
return callback(err);
}
- self.oauthToken = oauthToken;
- self.emailAddress = emailAddress;
- callback();
+ done();
});
- }
- };
-
- /**
- * Loads email address, password, provider, ... from disk and sets them on `this`
- */
- Auth.prototype._loadCredentials = function(callback) {
- var self = this;
-
- if (self.initialized) {
- callback();
+ return;
}
- loadFromDB(SMTP_DB_KEY, function(err, smtp) {
- if (err) {
- return callback(err);
- }
-
-
- loadFromDB(IMAP_DB_KEY, function(err, imap) {
+ 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;
- loadFromDB(USERNAME_DB_KEY, function(err, username) {
+ done();
+ });
+ return;
+ }
+
+ 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
+ }
+ },
+ 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);
+ }
+
+ self._appConfigStore.storeList([self.imap], IMAP_DB_KEY, function(err) {
+ if (err) {
+ return callback(err);
+ }
+
+ self._appConfigStore.storeList([self.provider], PROVIDER_DB_KEY, function(err) {
+ if (err) {
+ return callback(err);
+ }
+
+ self._appConfigStore.storeList([self.emailAddress], EMAIL_ADDR_DB_KEY, function(err) {
if (err) {
return callback(err);
}
-
- loadFromDB(REALNAME_DB_KEY, function(err, realname) {
+ self._appConfigStore.storeList([self.username], USERNAME_DB_KEY, function(err) {
if (err) {
return callback(err);
}
-
- loadFromDB(EMAIL_ADDR_DB_KEY, function(err, emailAddress) {
+ self._appConfigStore.storeList([self.realname], REALNAME_DB_KEY, function(err) {
if (err) {
return callback(err);
}
- loadFromDB(PASSWD_DB_KEY, function(err, password) {
- if (err) {
- return callback(err);
- }
+ if (!self.password) {
+ self.credentialsDirty = false;
+ return callback();
+ }
- loadFromDB(PROVIDER_DB_KEY, function(err, provider) {
+ 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.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;
+ self.credentialsDirty = false;
+ callback();
+ });
+ return;
+ }
+ self._pgp.encrypt(self.password, undefined, function(err, ciphertext) {
+ if (err) {
+ return callback(err);
+ }
+
+ self._appConfigStore.storeList([ciphertext], PASSWD_DB_KEY, function(err) {
+ if (err) {
+ return callback(err);
+ }
+
+ self.credentialsDirty = false;
callback();
});
});
@@ -358,96 +213,239 @@ define(function(require) {
});
});
});
+ });
+};
- function loadFromDB(key, callback) {
- self._appConfigStore.listItems(key, 0, null, function(err, cachedItems) {
- callback(err, (!err && cachedItems && cachedItems[0]));
- });
- }
- };
+/**
+ * Returns the email address. Loads it from disk, if necessary
+ */
+Auth.prototype.getEmailAddress = function(callback) {
+ var self = this;
- /**
- * 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;
+ if (self.emailAddress) {
+ return callback(null, {
+ emailAddress: self.emailAddress,
+ realname: self.realname
+ });
+ }
- 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;
+ self._loadCredentials(function(err) {
+ if (err) {
+ return callback(err);
}
- if (self[component].ca === pemEncodedCert) {
- // ignore multiple successive tls handshakes, e.g. for gmail
- return;
+ 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);
+ }
+
+ function onToken(err, oauthToken) {
+ if (err) {
+ return callback(err);
}
- 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;
+ // shortcut if the email address is already known
+ if (self.emailAddress) {
+ self.oauthToken = oauthToken;
+ return callback();
}
- // 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;
+ // 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) {
+ callback();
+ }
+
+ loadFromDB(SMTP_DB_KEY, function(err, smtp) {
+ if (err) {
+ return callback(err);
+ }
+
+
+ loadFromDB(IMAP_DB_KEY, function(err, imap) {
+ if (err) {
+ return callback(err);
+ }
+
+
+ loadFromDB(USERNAME_DB_KEY, function(err, username) {
+ if (err) {
+ return callback(err);
}
- self[component].ca = pemEncodedCert;
- self.storeCredentials(function(err) {
+
+ loadFromDB(REALNAME_DB_KEY, function(err, realname) {
if (err) {
- callback(err);
- return;
+ return callback(err);
}
- onConnect(callback);
+
+ loadFromDB(EMAIL_ADDR_DB_KEY, function(err, emailAddress) {
+ if (err) {
+ return callback(err);
+ }
+
+ loadFromDB(PASSWD_DB_KEY, function(err, password) {
+ 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();
+ });
+ });
+ });
});
- }
+ });
});
- };
+ });
- /**
- * Logout of the app by clearing the app config store and in memory credentials
- */
- Auth.prototype.logout = function(callback) {
- var self = this;
+ function loadFromDB(key, callback) {
+ self._appConfigStore.listItems(key, 0, null, function(err, cachedItems) {
+ callback(err, (!err && cachedItems && cachedItems[0]));
+ });
+ }
+};
- // clear app config db
- self._appConfigStore.clear(function(err) {
- if (err) {
- callback(err);
+/**
+ * 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;
}
- // 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;
+ }
- callback();
- });
- };
+ onConnect(callback);
+ });
+ }
+ });
+};
- return Auth;
-});
\ No newline at end of file
+/**
+ * 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();
+ });
+};
+
+exports = Auth;
\ No newline at end of file
diff --git a/src/js/bo/outbox.js b/src/js/bo/outbox.js
index 8a09cfb..d67a5e5 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;
/**
- * 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;
+ * Semaphore-esque flag to avoid 'concurrent' calls to _processOutbox when the timeout fires, but a call is still in process.
+ * @private */
+ this._outboxBusy = false;
+};
- /** @private */
- this._keychain = keychain;
+/**
+ * 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._devicestorage = devicestorage;
+/**
+ * Outbox stops the periodic checking of the local device storage for pending mails.
+ */
+OutboxBO.prototype.stopChecking = function() {
+ if (!this._intervalId) {
+ 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;
- };
+ clearInterval(this._intervalId);
+ delete this._intervalId;
+};
- /**
- * 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);
- };
+/**
+ * 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
- /**
- * Outbox stops the periodic checking of the local device storage for pending mails.
- */
- OutboxBO.prototype.stopChecking = function() {
- if (!this._intervalId) {
- return;
- }
+ mail.publicKeysArmored = []; // gather the public keys
+ mail.uid = mail.id = util.UUID(); // the mail needs a random id & uid for storage in the database
- clearInterval(this._intervalId);
- delete this._intervalId;
- };
+ // do not encrypt mails with a bcc recipient, due to a possible privacy leak
+ if (mail.bcc.length > 0) {
+ storeAndForward(mail);
+ return;
+ }
- /**
- * 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
+ checkRecipients(allReaders);
- mail.publicKeysArmored = []; // gather the public keys
- mail.uid = mail.id = util.UUID(); // the mail needs a random id & uid for storage in the database
+ // check if there are unregistered recipients
+ function checkRecipients(recipients) {
+ var after = _.after(recipients.length, function() {
+ checkEncrypt();
+ });
- // do not encrypt mails with a bcc recipient, due to a possible privacy leak
- if (mail.bcc.length > 0) {
+ // 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;
}
- 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);
+ // encrypts the body and attachments and persists the mail object
+ self._emailDao.encrypt({
+ mail: mail,
+ publicKeysArmored: mail.publicKeysArmored
+ }, function(err) {
+ if (err) {
+ callback(err);
return;
}
- // encrypts the body and attachments and persists the mail object
- self._emailDao.encrypt({
- mail: mail,
- publicKeysArmored: mail.publicKeysArmored
- }, function(err) {
- if (err) {
- callback(err);
- return;
- }
+ storeAndForward(mail);
+ });
+ }
- storeAndForward(mail);
- });
- }
+ function storeAndForward(mail) {
+ // store in outbox
+ self._devicestorage.storeList([mail], outboxDb, function(err) {
+ if (err) {
+ callback(err);
+ return;
+ }
- function storeAndForward(mail) {
- // store in outbox
- self._devicestorage.storeList([mail], outboxDb, function(err) {
- if (err) {
- callback(err);
- return;
- }
+ callback();
+ // don't wait for next round
+ self._processOutbox(self._onUpdate);
+ });
+ }
+};
- 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;
- /**
- * 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;
+ }
- // also, if a _processOutbox call is still in progress, ignore it.
- if (self._outboxBusy) {
+ 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;
}
- self._outboxBusy = true;
+ // 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;
+ }
- // get pending mails from the outbox
- self._devicestorage.listItems(outboxDb, 0, null, function(err, pendingMails) {
- // error, we're done here
+ // 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 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) {
+ self._outboxBusy = false;
+ if (err.code === 42) {
+ // offline try again later
+ done();
+ } else {
+ self._outboxBusy = false;
+ callback(err);
+ }
+ return;
+ }
+
+ // remove the pending mail from the storage
+ removeFromStorage(mail, done);
+
+ // 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;
}
- // 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 pending mails if possible
- pendingMails.forEach(function(mail) {
- send(mail, after);
- });
+ done();
});
+ }
+};
- // 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) {
- self._outboxBusy = false;
- if (err.code === 42) {
- // offline try again later
- done();
- } else {
- self._outboxBusy = false;
- callback(err);
- }
- return;
- }
-
- // remove the pending mail from the storage
- removeFromStorage(mail, done);
-
- // 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;
- }
-
- done();
- });
- }
- };
-
- return OutboxBO;
-});
\ No newline at end of file
+exports = OutboxBO;
\ No newline at end of file
diff --git a/src/js/controller/about.js b/src/js/controller/about.js
index 7e952a0..c88f965 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 variables
- //
-
- $scope.version = cfg.appVersion;
- $scope.date = new Date();
-
- //
- // scope functions
- //
+ $scope.state.about = {
+ toggle: function(to) {
+ $scope.state.lightbox = (to) ? 'about' : undefined;
+ }
};
- return AboutCtrl;
-});
\ No newline at end of file
+ //
+ // scope variables
+ //
+
+ $scope.version = cfg.appVersion;
+ $scope.date = new Date();
+
+ //
+ // scope functions
+ //
+};
+
+exports = AboutCtrl;
\ No newline at end of file
diff --git a/src/js/controller/account.js b/src/js/controller/account.js
index 7c409dd..1ca2437 100644
--- a/src/js/controller/account.js
+++ b/src/js/controller/account.js
@@ -1,61 +1,59 @@
-define(function(require) {
- 'use strict';
+'use strict';
- var appController = require('js/app-controller'),
- dl = require('js/util/download'),
- config = require('js/app-config').config,
- pgp, keychain, userId;
+var appController = require('../app-controller'),
+ dl = require('../util/download'),
+ config = require('../app-config').config,
+ pgp, keychain, userId;
- //
- // Controller
- //
+//
+// Controller
+//
- var AccountCtrl = function($scope) {
- userId = appController._emailDao._account.emailAddress;
- keychain = appController._keychain;
- pgp = appController._pgp;
+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;
- }
- };
-
- //
- // 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'
- });
- });
- };
+ $scope.state.account = {
+ toggle: function(to) {
+ $scope.state.lightbox = (to) ? 'account' : undefined;
+ }
};
- return AccountCtrl;
-});
\ No newline at end of file
+ //
+ // 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'
+ });
+ });
+ };
+};
+
+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..622c923 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
+var AddAccountCtrl = function($scope, $location, $routeParams) {
+ if (!appCtrl._auth && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
+ $scope.step = 1;
+
+ $scope.goTo = function(step) {
+ $scope.step = step;
+ };
+
+ $scope.createWhiteoutAccount = function() {
+ if ($scope.form.$invalid) {
return;
}
- $scope.step = 1;
+ $scope.busy = true;
+ $scope.errMsg = undefined; // reset error msg
+ $scope.emailAddress = $scope.user + '@' + cfg.wmailDomain;
- $scope.goTo = function(step) {
- $scope.step = step;
- };
+ // 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.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.goTo(3);
+ if (err) {
+ $scope.errMsg = err.errMsg || err.message;
$scope.$apply();
- });
- };
-
- $scope.validateUser = function() {
- if ($scope.formValidate.$invalid) {
return;
}
- $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();
- return;
- }
-
- // 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.goTo(3);
$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();
- });
- return;
- }
-
- // 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
+ $scope.validateUser = function() {
+ if ($scope.formValidate.$invalid) {
+ return;
+ }
+
+ $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();
+ return;
+ }
+
+ // 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();
+ });
+ return;
+ }
+
+ // 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
+ });
+ };
+};
+
+exports = AddAccountCtrl;
\ No newline at end of file
diff --git a/src/js/controller/contacts.js b/src/js/controller/contacts.js
index 10cd441..cdf11ea 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
- //
+//
+// Controller
+//
- var ContactsCtrl = function($scope) {
- keychain = appController._keychain,
- pgp = appController._pgp;
+var ContactsCtrl = function($scope) {
+ keychain = appController._keychain,
+ pgp = appController._pgp;
- $scope.state.contacts = {
- toggle: function(to) {
- $scope.state.lightbox = (to) ? 'contacts' : undefined;
+ $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';
-
- //
- // scope functions
- //
-
- $scope.listKeys = function() {
- keychain.listLocalPublicKeys(function(err, keys) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- keys.forEach(addParams);
-
- $scope.keys = keys;
- $scope.$apply();
-
- function addParams(key) {
- var params = pgp.getKeyParams(key.publicKey);
- _.extend(key, params);
- }
- });
- };
-
- $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.fingerprint = formatted;
- };
-
- $scope.importKey = function(publicKeyArmored) {
- var keyParams, pubkey;
-
- // 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
- };
-
- keychain.saveLocalPublicKey(pubkey, function(err) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- // update displayed keys
- $scope.listKeys();
- });
- };
-
- $scope.removeKey = function(key) {
- keychain.removeLocalPublicKey(key._id, function(err) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- // update displayed keys
- $scope.listKeys();
- });
- };
+ $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';
+
//
- // Directives
+ // scope functions
//
- var ngModule = angular.module('contacts', []);
-
- 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));
- }
- });
-
- function importKey(file) {
- var reader = new FileReader();
- reader.onload = function(e) {
- scope.importKey(e.target.result);
- };
- reader.readAsText(file);
+ $scope.listKeys = function() {
+ keychain.listLocalPublicKeys(function(err, keys) {
+ if (err) {
+ $scope.onError(err);
+ return;
}
- };
- });
- ngModule.directive('keyfileBtn', function() {
- return function(scope, elm) {
- elm.on('click touchstart', function(e) {
- e.preventDefault();
- document.querySelector('#keyfile-input').click();
+ keys.forEach(addParams);
+
+ $scope.keys = keys;
+ $scope.$apply();
+
+ function addParams(key) {
+ var params = pgp.getKeyParams(key.publicKey);
+ _.extend(key, params);
+ }
+ });
+ };
+
+ $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.fingerprint = formatted;
+ };
+
+ $scope.importKey = function(publicKeyArmored) {
+ var keyParams, pubkey;
+
+ // verifiy public key string
+ if (publicKeyArmored.indexOf('-----BEGIN PGP PUBLIC KEY BLOCK-----') < 0) {
+ $scope.onError({
+ showBugReporter: false,
+ message: 'Invalid public key!'
});
- };
- });
+ return;
+ }
- return ContactsCtrl;
-});
\ No newline at end of file
+ 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
+ };
+
+ keychain.saveLocalPublicKey(pubkey, function(err) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
+
+ // update displayed keys
+ $scope.listKeys();
+ });
+ };
+
+ $scope.removeKey = function(key) {
+ keychain.removeLocalPublicKey(key._id, function(err) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
+
+ // update displayed keys
+ $scope.listKeys();
+ });
+ };
+};
+
+//
+// Directives
+//
+
+var ngModule = angular.module('contacts', []);
+
+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));
+ }
+ });
+
+ 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();
+ });
+ };
+});
+
+exports = ContactsCtrl;
\ No newline at end of file
diff --git a/src/js/controller/dialog.js b/src/js/controller/dialog.js
index 45108c1..912f7b9 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
+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..d520471 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
+var LoginExistingCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
+
+ var emailDao = appController._emailDao;
+
+ $scope.buttonEnabled = true;
+ $scope.incorrect = false;
+
+ $scope.change = function() {
+ $scope.incorrect = false;
+ };
+
+ $scope.confirmPassphrase = function() {
+ if (!$scope.passphrase) {
return;
}
- var emailDao = appController._emailDao;
-
- $scope.buttonEnabled = true;
+ // disable button once loggin has started
+ $scope.buttonEnabled = false;
$scope.incorrect = false;
-
- $scope.change = function() {
- $scope.incorrect = false;
- };
-
- $scope.confirmPassphrase = function() {
- if (!$scope.passphrase) {
- 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);
- });
- }
-
- function onUnlock(err) {
- if (err) {
- $scope.incorrect = true;
- $scope.buttonEnabled = true;
- $scope.$apply();
- return;
- }
-
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
-
- $location.path('/desktop');
- $scope.$apply();
- });
- }
-
- function handleError(err) {
- $scope.incorrect = true;
- $scope.buttonEnabled = true;
- $scope.onError(err);
- }
+ unlockCrypto();
};
- return LoginExistingCtrl;
-});
\ No newline at end of file
+ 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);
+ });
+ }
+
+ function onUnlock(err) {
+ if (err) {
+ $scope.incorrect = true;
+ $scope.buttonEnabled = true;
+ $scope.$apply();
+ return;
+ }
+
+ appController._auth.storeCredentials(function(err) {
+ if (err) {
+ return $scope.onError(err);
+ }
+
+ $location.path('/desktop');
+ $scope.$apply();
+ });
+ }
+
+ function handleError(err) {
+ $scope.incorrect = true;
+ $scope.buttonEnabled = true;
+ $scope.onError(err);
+ }
+};
+
+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..7d00616 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
+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.';
+
+ 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;
}
- 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;
- }
-
- // 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;
- }
-
- // 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;
- }
-
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
-
- $location.path('/desktop');
- $scope.$apply();
- });
- });
- }, 500);
- };
-
- /**
- * [signUpToNewsletter description]
- * @param {Function} callback (optional)
- */
- $scope.signUpToNewsletter = function(callback) {
- if (!$scope.state.newsletter) {
- return;
- }
-
- var address = emailDao._account.emailAddress;
- var uri = 'https://whiteout.us8.list-manage.com/subscribe/post?u=52ea5a9e1be9e1d194f184158&id=6538e8f09f';
-
- var formData = new FormData();
- formData.append('EMAIL', address);
- formData.append('b_52ea5a9e1be9e1d194f184158_6538e8f09f', '');
-
- var xhr = new XMLHttpRequest();
- xhr.open('post', uri, true);
-
- xhr.onload = function() {
- if (callback) {
- callback(null, xhr);
- }
- };
-
- xhr.onerror = function(err) {
- if (callback) {
- callback(err);
- }
- };
-
- xhr.send(formData);
- };
-
- $scope.setState = function(state) {
- $scope.state.ui = state;
- };
+ // sing up to newsletter
+ $scope.signUpToNewsletter();
+ // go to key import
+ $location.path('/login-new-device');
};
- return LoginInitialCtrl;
-});
\ No newline at end of file
+ /**
+ * 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);
+
+ setTimeout(function() {
+ emailDao.unlock({
+ passphrase: undefined // generate key without passphrase
+ }, function(err) {
+ if (err) {
+ $scope.setState(states.IDLE);
+ $scope.onError(err);
+ return;
+ }
+
+ appController._auth.storeCredentials(function(err) {
+ if (err) {
+ return $scope.onError(err);
+ }
+
+ $location.path('/desktop');
+ $scope.$apply();
+ });
+ });
+ }, 500);
+ };
+
+ /**
+ * [signUpToNewsletter description]
+ * @param {Function} callback (optional)
+ */
+ $scope.signUpToNewsletter = function(callback) {
+ if (!$scope.state.newsletter) {
+ return;
+ }
+
+ var address = emailDao._account.emailAddress;
+ var uri = 'https://whiteout.us8.list-manage.com/subscribe/post?u=52ea5a9e1be9e1d194f184158&id=6538e8f09f';
+
+ var formData = new FormData();
+ formData.append('EMAIL', address);
+ formData.append('b_52ea5a9e1be9e1d194f184158_6538e8f09f', '');
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('post', uri, true);
+
+ xhr.onload = function() {
+ if (callback) {
+ callback(null, xhr);
+ }
+ };
+
+ xhr.onerror = function(err) {
+ if (callback) {
+ callback(err);
+ }
+ };
+
+ xhr.send(formData);
+ };
+
+ $scope.setState = function(state) {
+ $scope.state.ui = state;
+ };
+};
+
+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..e85c5e5 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 LoginExistingCtrl = function($scope, $location, $routeParams) {
+ if (!appController._emailDao && !$routeParams.dev) {
+ $location.path('/'); // init app
+ return;
+ }
- var emailDao = appController._emailDao,
- pgp = appController._pgp;
+ var emailDao = appController._emailDao,
+ pgp = appController._pgp;
+ $scope.incorrect = false;
+
+ $scope.confirmPassphrase = function() {
$scope.incorrect = false;
+ unlockCrypto();
+ };
- $scope.confirmPassphrase = function() {
- $scope.incorrect = false;
- unlockCrypto();
- };
-
- 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;
- }
-
- keypair = keypair || {};
-
- // 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;
- }
- }
-
- // 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: 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;
- }
-
- emailDao._keychain.putUserKeyPair(keypair, onUnlock);
- });
- });
- }
-
- function onUnlock(err) {
+ 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;
}
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
+ keypair = keypair || {};
+
+ // 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;
}
+ }
- $location.path('/desktop');
- $scope.$apply();
- });
- }
- };
+ // 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;
+ }
- 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();
+ // set parsed private key
+ keypair.privateKey = {
+ _id: privKeyParams._id,
+ userId: userId,
+ userIds: privKeyParams.userIds,
+ encryptedKey: $scope.key.privateKeyArmored
+ };
- if (files.length === 0) {
+ 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;
}
- 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;
- });
- };
- reader.readAsText(files[0]);
+ emailDao._keychain.putUserKeyPair(keypair, onUnlock);
});
- };
- });
+ });
+ }
- return LoginExistingCtrl;
-});
\ No newline at end of file
+ function onUnlock(err) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
+
+ appController._auth.storeCredentials(function(err) {
+ if (err) {
+ return $scope.onError(err);
+ }
+
+ $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();
+
+ if (files.length === 0) {
+ 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;
+ });
+ };
+ reader.readAsText(files[0]);
+ });
+ };
+});
+
+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..e120d7f 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
+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 value = evt.clipboardData.getData('text/plain');
+ if (!value) {
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 value = evt.clipboardData.getData('text/plain');
- if (!value) {
- 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;
- }
-
- keychain.getUserKeyPair(userId, function(err, keypair) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- // remember for storage later
- $scope.cachedKeypair = keypair;
-
- keychain.downloadPrivateKey({
- userId: userId,
- keyId: keypair.publicKey._id,
- recoveryToken: $scope.recoveryToken.toUpperCase()
- }, function(err, encryptedPrivateKey) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- $scope.encryptedPrivateKey = encryptedPrivateKey;
- callback();
- });
- });
- };
-
- $scope.decryptAndStorePrivateKeyLocally = function() {
- var inputCode = '' + $scope.code0 + $scope.code1 + $scope.code2 + $scope.code3 + $scope.code4 + $scope.code5;
-
- if (!inputCode) {
- $scope.onError(new Error('Please enter the keychain code!'));
- return;
- }
-
- var options = $scope.encryptedPrivateKey;
- options.code = inputCode.toUpperCase();
-
- keychain.decryptAndStorePrivateKeyLocally(options, function(err, privateKey) {
- if (err) {
- $scope.onError(err);
- return;
- }
-
- // add private key to cached keypair object
- $scope.cachedKeypair.privateKey = privateKey;
-
- // try empty passphrase
- emailDao.unlock({
- keypair: $scope.cachedKeypair,
- passphrase: undefined
- }, function(err) {
- if (err) {
- // go to passphrase login screen
- $scope.goTo('/login-existing');
- return;
- }
-
- // passphrase is corrent ... go to main app
- appController._auth.storeCredentials(function(err) {
- if (err) {
- return $scope.onError(err);
- }
-
- $scope.goTo('/desktop');
- });
- });
- });
- };
-
- $scope.goForward = function() {
- if ($scope.step === 1) {
- $scope.verifyRecoveryToken(function() {
- $scope.step++;
- $scope.$apply();
- });
- return;
- }
-
- if ($scope.step === 2) {
- $scope.decryptAndStorePrivateKeyLocally();
- return;
- }
- };
-
- $scope.goTo = function(location) {
- $location.path(location);
- $scope.$apply();
- };
+ 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);
};
- return LoginPrivateKeyDownloadCtrl;
-});
\ No newline at end of file
+ $scope.verifyRecoveryToken = function(callback) {
+ if (!$scope.recoveryToken) {
+ $scope.onError(new Error('Please set the recovery token!'));
+ return;
+ }
+
+ keychain.getUserKeyPair(userId, function(err, keypair) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
+
+ // remember for storage later
+ $scope.cachedKeypair = keypair;
+
+ keychain.downloadPrivateKey({
+ userId: userId,
+ keyId: keypair.publicKey._id,
+ recoveryToken: $scope.recoveryToken.toUpperCase()
+ }, function(err, encryptedPrivateKey) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
+
+ $scope.encryptedPrivateKey = encryptedPrivateKey;
+ callback();
+ });
+ });
+ };
+
+ $scope.decryptAndStorePrivateKeyLocally = function() {
+ var inputCode = '' + $scope.code0 + $scope.code1 + $scope.code2 + $scope.code3 + $scope.code4 + $scope.code5;
+
+ if (!inputCode) {
+ $scope.onError(new Error('Please enter the keychain code!'));
+ return;
+ }
+
+ var options = $scope.encryptedPrivateKey;
+ options.code = inputCode.toUpperCase();
+
+ keychain.decryptAndStorePrivateKeyLocally(options, function(err, privateKey) {
+ if (err) {
+ $scope.onError(err);
+ return;
+ }
+
+ // add private key to cached keypair object
+ $scope.cachedKeypair.privateKey = privateKey;
+
+ // try empty passphrase
+ emailDao.unlock({
+ keypair: $scope.cachedKeypair,
+ passphrase: undefined
+ }, function(err) {
+ if (err) {
+ // go to passphrase login screen
+ $scope.goTo('/login-existing');
+ return;
+ }
+
+ // passphrase is corrent ... go to main app
+ appController._auth.storeCredentials(function(err) {
+ if (err) {
+ return $scope.onError(err);
+ }
+
+ $scope.goTo('/desktop');
+ });
+ });
+ });
+ };
+
+ $scope.goForward = function() {
+ if ($scope.step === 1) {
+ $scope.verifyRecoveryToken(function() {
+ $scope.step++;
+ $scope.$apply();
+ });
+ return;
+ }
+
+ if ($scope.step === 2) {
+ $scope.decryptAndStorePrivateKeyLocally();
+ return;
+ }
+ };
+
+ $scope.goTo = function(location) {
+ $location.path(location);
+ $scope.$apply();
+ };
+};
+
+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..3e40baf 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';
+'use strict';
- var ENCRYPTION_METHOD_NONE = 0;
- var ENCRYPTION_METHOD_STARTTLS = 1;
- var ENCRYPTION_METHOD_TLS = 2;
+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 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 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;
+ // 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;
- //
- // 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;
+ // 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;
+ $scope.test = function() {
+ // parse the