mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-07 05:04:58 +08:00
Reintroduce concept of provider
, start work on Gmail
This commit is contained in:
parent
1fe7fdf4b1
commit
76d873c2b2
6 changed files with 40 additions and 38 deletions
|
@ -69,6 +69,6 @@ server.register(plugins, (err) => {
|
||||||
|
|
||||||
server.start((startErr) => {
|
server.start((startErr) => {
|
||||||
if (startErr) { throw startErr; }
|
if (startErr) { throw startErr; }
|
||||||
console.log('Server running at:', server.info.uri);
|
console.log('API running at:', server.info.uri);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,12 +8,10 @@ const {
|
||||||
IMAPConnection,
|
IMAPConnection,
|
||||||
DatabaseConnector,
|
DatabaseConnector,
|
||||||
SyncPolicy,
|
SyncPolicy,
|
||||||
|
Provider,
|
||||||
} = require('nylas-core');
|
} = require('nylas-core');
|
||||||
|
|
||||||
// TODO: Move these to config somehow / somewhere
|
const {GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REDIRECT_URL} = process.env;
|
||||||
const CLIENT_ID = '271342407743-nibas08fua1itr1utq9qjladbkv3esdm.apps.googleusercontent.com';
|
|
||||||
const CLIENT_SECRET = 'WhmxErj-ei6vJXLocNhBbfBF';
|
|
||||||
const REDIRECT_URL = 'http://localhost:5100/auth/gmail/oauthcallback';
|
|
||||||
|
|
||||||
const SCOPES = [
|
const SCOPES = [
|
||||||
'https://www.googleapis.com/auth/userinfo.email', // email address
|
'https://www.googleapis.com/auth/userinfo.email', // email address
|
||||||
|
@ -41,12 +39,13 @@ const exchangeSettings = Joi.object().keys({
|
||||||
eas_server_host: [Joi.string().ip().required(), Joi.string().hostname().required()],
|
eas_server_host: [Joi.string().ip().required(), Joi.string().hostname().required()],
|
||||||
}).required();
|
}).required();
|
||||||
|
|
||||||
const buildAccountWith = ({name, email, settings, credentials}) => {
|
const buildAccountWith = ({name, email, provider, settings, credentials}) => {
|
||||||
return DatabaseConnector.forShared().then((db) => {
|
return DatabaseConnector.forShared().then((db) => {
|
||||||
const {AccountToken, Account} = db;
|
const {AccountToken, Account} = db;
|
||||||
|
|
||||||
const account = Account.build({
|
const account = Account.build({
|
||||||
name: name,
|
name: name,
|
||||||
|
provider: provider,
|
||||||
emailAddress: email,
|
emailAddress: email,
|
||||||
syncPolicy: SyncPolicy.defaultPolicy(),
|
syncPolicy: SyncPolicy.defaultPolicy(),
|
||||||
connectionSettings: settings,
|
connectionSettings: settings,
|
||||||
|
@ -103,6 +102,7 @@ module.exports = (server) => {
|
||||||
return buildAccountWith({
|
return buildAccountWith({
|
||||||
name,
|
name,
|
||||||
email,
|
email,
|
||||||
|
provider: Provider.IMAP,
|
||||||
settings: _.pick(settings, [
|
settings: _.pick(settings, [
|
||||||
'imap_host', 'imap_port',
|
'imap_host', 'imap_port',
|
||||||
'smtp_host', 'smtp_port',
|
'smtp_host', 'smtp_port',
|
||||||
|
@ -120,9 +120,7 @@ module.exports = (server) => {
|
||||||
reply(Serialization.jsonStringify(response));
|
reply(Serialization.jsonStringify(response));
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
// TODO: Lots more of this
|
reply({error: err.message}).code(400);
|
||||||
console.log(err)
|
|
||||||
reply({error: err.toString()});
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -137,7 +135,7 @@ module.exports = (server) => {
|
||||||
auth: false,
|
auth: false,
|
||||||
},
|
},
|
||||||
handler: (request, reply) => {
|
handler: (request, reply) => {
|
||||||
const oauthClient = new OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);
|
const oauthClient = new OAuth2(GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REDIRECT_URL);
|
||||||
reply.redirect(oauthClient.generateAuthUrl({
|
reply.redirect(oauthClient.generateAuthUrl({
|
||||||
access_type: 'offline',
|
access_type: 'offline',
|
||||||
prompt: 'consent',
|
prompt: 'consent',
|
||||||
|
@ -161,16 +159,16 @@ module.exports = (server) => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
handler: (request, reply) => {
|
handler: (request, reply) => {
|
||||||
const oauthClient = new OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);
|
const oauthClient = new OAuth2(GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REDIRECT_URL);
|
||||||
oauthClient.getToken(request.query.code, (err, tokens) => {
|
oauthClient.getToken(request.query.code, (err, tokens) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reply(err.message).code(400);
|
reply({error: err.message}).code(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
oauthClient.setCredentials(tokens);
|
oauthClient.setCredentials(tokens);
|
||||||
google.oauth2({version: 'v2', auth: oauthClient}).userinfo.get((error, profile) => {
|
google.oauth2({version: 'v2', auth: oauthClient}).userinfo.get((error, profile) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reply(error.message).code(400);
|
reply({error: error.message}).code(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,15 +181,21 @@ module.exports = (server) => {
|
||||||
const credentials = {
|
const credentials = {
|
||||||
access_token: tokens.access_token,
|
access_token: tokens.access_token,
|
||||||
refresh_token: tokens.refresh_token,
|
refresh_token: tokens.refresh_token,
|
||||||
client_id: CLIENT_ID,
|
client_id: GMAIL_CLIENT_ID,
|
||||||
client_secret: CLIENT_SECRET,
|
client_secret: GMAIL_CLIENT_SECRET,
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
IMAPConnection.connect({}, Object.assign({}, settings, credentials)),
|
IMAPConnection.connect({}, Object.assign({}, settings, credentials)),
|
||||||
])
|
])
|
||||||
.then(() =>
|
.then(() =>
|
||||||
buildAccountWith({name: profile.name, email: profile.email, settings, credentials})
|
buildAccountWith({
|
||||||
|
name: profile.name,
|
||||||
|
email: profile.email,
|
||||||
|
provider: Provider.Gmail,
|
||||||
|
settings,
|
||||||
|
credentials,
|
||||||
|
})
|
||||||
)
|
)
|
||||||
.then(({account, token}) => {
|
.then(({account, token}) => {
|
||||||
const response = account.toJSON();
|
const response = account.toJSON();
|
||||||
|
@ -199,8 +203,7 @@ module.exports = (server) => {
|
||||||
reply(Serialization.jsonStringify(response));
|
reply(Serialization.jsonStringify(response));
|
||||||
})
|
})
|
||||||
.catch((connectionErr) => {
|
.catch((connectionErr) => {
|
||||||
// TODO: Lots more of this
|
reply({error: connectionErr.message}).code(400);
|
||||||
reply({error: connectionErr.toString()});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"storage": {
|
|
||||||
"database": "account-$ACCOUNTID",
|
|
||||||
"username": null,
|
|
||||||
"password": null,
|
|
||||||
"options": {
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"storage": "./account-$ACCOUNTID.sqlite"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,14 @@
|
||||||
global.Promise = require('bluebird');
|
global.Promise = require('bluebird');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
Provider: {
|
||||||
|
Gmail: 'gmail',
|
||||||
|
IMAP: 'imap',
|
||||||
|
},
|
||||||
DatabaseConnector: require('./database-connector'),
|
DatabaseConnector: require('./database-connector'),
|
||||||
PubsubConnector: require('./pubsub-connector'),
|
PubsubConnector: require('./pubsub-connector'),
|
||||||
IMAPConnection: require('./imap-connection'),
|
IMAPConnection: require('./imap-connection'),
|
||||||
SyncPolicy: require('./sync-policy'),
|
SyncPolicy: require('./sync-policy'),
|
||||||
SchedulerUtils: require('./scheduler-utils'),
|
SchedulerUtils: require('./scheduler-utils'),
|
||||||
Config: require(`./config/${process.env.ENV || 'development'}`),
|
|
||||||
ExtendableError: require('./extendable-error'),
|
ExtendableError: require('./extendable-error'),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const {JSONType, JSONARRAYType} = require('../../database-types');
|
const {JSONType, JSONARRAYType} = require('../../database-types');
|
||||||
|
|
||||||
const algorithm = 'aes-256-ctr';
|
const {DB_ENCRYPTION_ALGORITHM, DB_ENCRYPTION_PASSWORD} = process.env;
|
||||||
const password = 'd6F3Efeq';
|
|
||||||
|
|
||||||
module.exports = (sequelize, Sequelize) => {
|
module.exports = (sequelize, Sequelize) => {
|
||||||
const Account = sequelize.define('Account', {
|
const Account = sequelize.define('Account', {
|
||||||
name: Sequelize.STRING,
|
name: Sequelize.STRING,
|
||||||
|
provider: Sequelize.STRING,
|
||||||
emailAddress: Sequelize.STRING,
|
emailAddress: Sequelize.STRING,
|
||||||
connectionSettings: JSONType('connectionSettings'),
|
connectionSettings: JSONType('connectionSettings'),
|
||||||
connectionCredentials: Sequelize.STRING,
|
connectionCredentials: Sequelize.STRING,
|
||||||
|
@ -37,7 +37,7 @@ module.exports = (sequelize, Sequelize) => {
|
||||||
if (!(json instanceof Object)) {
|
if (!(json instanceof Object)) {
|
||||||
throw new Error("Call setCredentials with JSON!")
|
throw new Error("Call setCredentials with JSON!")
|
||||||
}
|
}
|
||||||
const cipher = crypto.createCipher(algorithm, password)
|
const cipher = crypto.createCipher(DB_ENCRYPTION_ALGORITHM, DB_ENCRYPTION_PASSWORD)
|
||||||
let crypted = cipher.update(JSON.stringify(json), 'utf8', 'hex')
|
let crypted = cipher.update(JSON.stringify(json), 'utf8', 'hex')
|
||||||
crypted += cipher.final('hex');
|
crypted += cipher.final('hex');
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ module.exports = (sequelize, Sequelize) => {
|
||||||
},
|
},
|
||||||
|
|
||||||
decryptedCredentials: function decryptedCredentials() {
|
decryptedCredentials: function decryptedCredentials() {
|
||||||
const decipher = crypto.createDecipher(algorithm, password)
|
const decipher = crypto.createDecipher(DB_ENCRYPTION_ALGORITHM, DB_ENCRYPTION_PASSWORD)
|
||||||
let dec = decipher.update(this.connectionCredentials, 'hex', 'utf8')
|
let dec = decipher.update(this.connectionCredentials, 'hex', 'utf8')
|
||||||
dec += decipher.final('utf8');
|
dec += decipher.final('utf8');
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const {
|
const {
|
||||||
|
Provider,
|
||||||
SchedulerUtils,
|
SchedulerUtils,
|
||||||
IMAPConnection,
|
IMAPConnection,
|
||||||
PubsubConnector,
|
PubsubConnector,
|
||||||
|
@ -129,13 +130,19 @@ class SyncWorker {
|
||||||
|
|
||||||
return Category.findAll().then((categories) => {
|
return Category.findAll().then((categories) => {
|
||||||
const priority = ['inbox', 'drafts', 'sent'].reverse();
|
const priority = ['inbox', 'drafts', 'sent'].reverse();
|
||||||
const categoriesToSync = categories.sort((a, b) =>
|
let categoriesToSync = categories.sort((a, b) =>
|
||||||
(priority.indexOf(a.role) - priority.indexOf(b.role)) * -1
|
(priority.indexOf(a.role) - priority.indexOf(b.role)) * -1
|
||||||
)
|
)
|
||||||
|
|
||||||
// const filtered = sorted.filter(cat =>
|
if (this._account.provider === Provider.Gmail) {
|
||||||
// ['[Gmail]/All Mail', '[Gmail]/Trash', '[Gmail]/Spam'].includes(cat.name)
|
categoriesToSync = categoriesToSync.filter(cat =>
|
||||||
// )
|
['[Gmail]/All Mail', '[Gmail]/Trash', '[Gmail]/Spam'].includes(cat.name)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (categoriesToSync.length !== 3) {
|
||||||
|
throw new Error(`Account is missing a core Gmail folder: ${categoriesToSync.join(',')}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Don't accumulate errors, just bail on the first error and clear
|
// TODO Don't accumulate errors, just bail on the first error and clear
|
||||||
// the queue and the connection
|
// the queue and the connection
|
||||||
|
|
Loading…
Add table
Reference in a new issue