diff --git a/packages/client-app/MailSync b/packages/client-app/MailSync new file mode 100755 index 000000000..215b4fe81 Binary files /dev/null and b/packages/client-app/MailSync differ diff --git a/packages/client-app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx b/packages/client-app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx index 0df8ff0a4..8bedf5592 100644 --- a/packages/client-app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx +++ b/packages/client-app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx @@ -5,7 +5,7 @@ import {RetinaImg} from 'nylas-component-kit'; import {NylasAPI, Actions} from 'nylas-exports'; import OnboardingActions from '../onboarding-actions'; -import {runAuthRequest} from '../onboarding-helpers'; +import {runAuthValidation} from '../onboarding-helpers'; import FormErrorMessage from '../form-error-message'; import AccountTypes from '../account-types' @@ -99,7 +99,7 @@ const CreatePageForForm = (FormComponent) => { this.setState({submitting: true}); - runAuthRequest(accountInfo) + runAuthValidation(accountInfo) .then((json) => { OnboardingActions.moveToPage('account-onboarding-success') OnboardingActions.accountJSONReceived(json, json.localToken, json.cloudToken) diff --git a/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 b/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 index d76ae5f3e..cc99fd35a 100644 --- a/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 +++ b/packages/client-app/internal_packages/onboarding/lib/onboarding-helpers.es6 @@ -7,8 +7,10 @@ import { NylasAPI, NylasAPIRequest, RegExpUtils, + MailsyncProcess, } from 'nylas-exports'; + const IMAP_FIELDS = new Set([ "imap_host", "imap_port", @@ -86,7 +88,7 @@ export function buildGmailAuthURL(sessionKey) { return `${N1CloudAPI.APIRoot}/auth/gmail?state=${sessionKey}`; } -export function runAuthRequest(accountInfo) { +export function runAuthValidation(accountInfo) { const {username, type, email, name} = accountInfo; const data = { @@ -121,43 +123,37 @@ export function runAuthRequest(accountInfo) { } } - const noauth = { - user: '', - pass: '', - sendImmediately: true, - }; - // Send the form data directly to Nylas to get code // If this succeeds, send the received code to N1 server to register the account // Otherwise process the error message from the server and highlight UI as needed - const n1CloudIMAPAuthRequest = new NylasAPIRequest({ - api: N1CloudAPI, - options: { - path: '/auth', - method: 'POST', - timeout: 1000 * 180, // Same timeout as server timeout (most requests are faster than 90s, but server validation can be slow in some cases) - body: data, - auth: noauth, - }, - }) - return n1CloudIMAPAuthRequest.run().then((remoteJSON) => { - const localSyncIMAPAuthRequest = new NylasAPIRequest({ - api: NylasAPI, - options: { - path: `/auth`, - method: 'POST', - timeout: 1000 * 180, // Same timeout as server timeout (most requests are faster than 90s, but server validation can be slow in some cases) - body: data, - auth: noauth, - }, - }) - return localSyncIMAPAuthRequest.run().then((localJSON) => { - const accountWithTokens = Object.assign({}, localJSON); - accountWithTokens.localToken = localJSON.account_token; - accountWithTokens.cloudToken = remoteJSON.account_token; - return accountWithTokens - }) - }) + data.settings.id = 'test'; + const proc = new MailsyncProcess('test', data.settings); + return proc.test().then((accountJSON) => { + return accountJSON; + }); + + // TODO BG Re-enable cloud services + // return n1CloudIMAPAuthRequest.run().then((remoteJSON) => { + // const localSyncIMAPAuthRequest = new NylasAPIRequest({ + // api: NylasAPI, + // options: { + // path: `/auth`, + // method: 'POST', + // timeout: 1000 * 180, // Same timeout as server timeout (most requests are faster than 90s, but server validation can be slow in some cases) + // body: data, + // auth: { + // user: '', + // pass: '', + // sendImmediately: true, + // }, + // }, + // }) + // return localSyncIMAPAuthRequest.run().then((localJSON) => { + // const accountWithTokens = Object.assign({}, localJSON); + // accountWithTokens.localToken = localJSON.account_token; + // accountWithTokens.cloudToken = '';//remoteJSON.account_token; + // return accountWithTokens + // }) } export function isValidHost(value) { diff --git a/packages/client-app/src/global/nylas-exports.es6 b/packages/client-app/src/global/nylas-exports.es6 index 6e47f64cd..6dab8aff0 100644 --- a/packages/client-app/src/global/nylas-exports.es6 +++ b/packages/client-app/src/global/nylas-exports.es6 @@ -61,7 +61,7 @@ lazyLoad(`EdgehillAPI`, 'flux/edgehill-api'); lazyLoad(`LegacyEdgehillAPI`, 'flux/legacy-edgehill-api'); lazyLoad(`NylasAPIHelpers`, 'flux/nylas-api-helpers'); lazyLoad(`NylasAPIRequest`, 'flux/nylas-api-request'); - +lazyLoad(`MailsyncProcess`, 'mailsync-process'); // The Database lazyLoad(`Matcher`, 'flux/attributes/matcher'); lazyLoad(`DatabaseStore`, 'flux/stores/database-store'); diff --git a/packages/client-app/src/mailsync-process.es6 b/packages/client-app/src/mailsync-process.es6 new file mode 100644 index 000000000..08403c7e4 --- /dev/null +++ b/packages/client-app/src/mailsync-process.es6 @@ -0,0 +1,71 @@ +import { spawn } from 'child_process'; +import path from 'path'; + +const LocalizedErrorStrings = { + ErrorConnection: "Connection Error", + ErrorInvalidAccount: "This account is invalid, or does not have an inbox or all folder.", + ErrorTLSNotAvailable: "TLS Not Available", + ErrorParse: "Parsing Error", + ErrorCertificate: "Certificate Error", + ErrorAuthentication: "Authentication Error - Check your username and password.", + ErrorGmailIMAPNotEnabled: "Gmail IMAP is not enabled. Visit Gmail settings to turn it on.", + ErrorGmailExceededBandwidthLimit: "Gmail bandwidth exceeded. Please try again later.", + ErrorGmailTooManySimultaneousConnections: "There are too many active connections to your Gmail account. Please try again later.", + ErrorMobileMeMoved: "MobileMe has moved.", + ErrorYahooUnavailable: "Yahoo is unavailable.", + ErrorNonExistantFolder: "Sorry, this folder does not exist.", + ErrorStartTLSNotAvailable: "StartTLS is not available.", + ErrorGmailApplicationSpecificPasswordRequired: "A Gmail application-specific password is required.", + ErrorOutlookLoginViaWebBrowser: "The Outlook server said you must sign in via a web browser.", + ErrorNeedsConnectToWebmail: "The server said you must sign in via your webmail.", + ErrorNoValidServerFound: "No valid server found.", + ErrorAuthenticationRequired: "Authentication required.", +}; + +export default class MailsyncProcess { + constructor(mode, account) { + this.mode = mode; + this.account = account; + } + + _spawnProcess() { + const binaryPath = path.join(NylasEnv.getLoadSettings().resourcePath, 'MailSync'); + const sync = spawn(binaryPath, [`--mode`, this.mode]); + if (this.mode !== 'migrate') { + sync.stdout.once('data', () => { + console.log(this.account); + sync.stdin.write(`${JSON.stringify(this.account)}\n`); + }); + } + return sync; + } + + test() { + return new Promise((resolve, reject) => { + const sync = this._spawnProcess(); + let buffer = Buffer.from([]); + sync.stdout.on('data', (data) => { + buffer += data; + }); + sync.stderr.on('data', (data) => { + buffer += data; + }); + sync.on('error', (err) => { + reject(err, buffer); + }); + sync.on('close', (code) => { + try { + const lastLine = buffer.toString('UTF-8').split('\n').pop(); + const response = JSON.parse(lastLine); + if (code === 0) { + resolve(response); + } else { + reject(new Error(LocalizedErrorStrings[response.error])) + } + } catch (err) { + reject(err); + } + }); + }); + } +}