justinkalland/protonmail-api

Connection Error

Opened this issue · 4 comments

const pm = await ProtonMail.connect({
        username: 'email@protonmail.com',
        password: 'password'
    })
D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:513
            const timeoutError = new Errors_js_1.TimeoutError(`waiting for ${options.title} failed: timeout ${options.timeout}ms exceeded`);
                                 ^

TimeoutError: waiting for selector `#login_btn` failed: timeout 30000ms exceeded
at new WaitTask (D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:513:34)
at DOMWorld.waitForSelectorInPage (D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:424:26)
at Object.internalHandler.waitFor (D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\QueryHandler.js:31:77)
at DOMWorld.waitForSelector (D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:317:29)
at Frame.waitForSelector (D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\FrameManager.js:841:51)
at Page.waitForSelector (D:\projects\project\node_modules\puppeteer\lib\cjs\puppeteer\common\Page.js:2313:33)
at ProtonMail._connect (D:\projects\project\node_modules\protonmail-api\lib\proton-mail.js:57:16)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Function.connect (D:\projects\project\node_modules\protonmail-api\lib\proton-mail.js:31:5)
at async D:\projects\project\old\protonmail\test.js:6:16

Node.js v17.1.0

its no longer working. If you look at the source its doing...

await page.goto('https://account.proton.me/login')

which doesnt exist anymore and re-routes to their new login page where the elements are named different things.

im hacking on it now and might make a pr to update it.

      await page.evaluate(() => {
            window.conversationApi = window.angular.element(document.body).injector().get('conversationApi')
            window.labelsModel = window.angular.element(document.body).injector().get('labelsModel')
            window.labelModel = window.angular.element(document.body).injector().get('Label')
            window.MessageModel = window.angular.element(document.body).injector().get('messageModel')
            window.addressesModel = window.angular.element(document.body).injector().get('addressesModel')
            window.messageApi = window.angular.element(document.body).injector().get('messageApi')
            window.encryptMessage = window.angular.element(document.body).injector().get('encryptMessage')
        })

Is all wrong as well sadly.

Got the same error, I updated this part of the code:

    await page.goto('https://account.proton.me/login')
    await page.waitForSelector('button.button:nth-child(6)')
    await page.type('#username', this._config.username)
    await page.type('#password', this._config.password)
    await page.click('button.button:nth-child(6)')

I have to say it is not a good way to fetch a button. I wish Protonmail has an API to work with...

Effectively, once the proper selectors are set, the URL updated and the error catching issue is solved :

    await page.goto('https://account.proton.me/login/')
    await page.waitForSelector('button[type=submit]')
    await page.waitForSelector('#username')
    await page.type('#username', this._config.username)
    await page.waitForSelector('#password')
    await page.type('#password', this._config.password)
    await page.click('button[type=submit]')
    await Promise.race([
      page.waitForSelector('div[role=alert]'),
      page.waitForSelector('.notification.bg-danger')])
      .catch(() => { 
          throw new Error('Invalid username and/or password') 
      })

then it all works out perfectly up to that eval bloc :

      await page.evaluate(() => {
            window.conversationApi = window.angular.element(document.body).injector().get('conversationApi')
            window.labelsModel = window.angular.element(document.body).injector().get('labelsModel')
            window.labelModel = window.angular.element(document.body).injector().get('Label')
            window.MessageModel = window.angular.element(document.body).injector().get('messageModel')
            window.addressesModel = window.angular.element(document.body).injector().get('addressesModel')
            window.messageApi = window.angular.element(document.body).injector().get('messageApi')
            window.encryptMessage = window.angular.element(document.body).injector().get('encryptMessage')
        })

Is all wrong as well sadly.

With an error message stating that « Evaluation failed: TypeError: Cannot read properties of undefined (reading 'element') ». It looks like it's trying to access the Angular.js library from within the window object.

Issue 1 — This library is now nowhere to be found in the window object. I'm assuming Proton choose to drop it when it stopped receiving support in January of this year. It was first used as a dom selector, which is easy to replace with jQuery or native JS. But it's passed injector() function, that was used to inject in the dom some dependency from the Proton API, that i am not sure how to emulate. I assume the doc says it all, but me being so unfamiliar with Angular, i can't quite understand what it did angular.injector Doc

Issue 2 — The «conversationApi, labelsModel, messageModel» etc endpoints seem to no longer exist since the Protonmail app rework. There might be new equivalents, but i haven't put my hand on them yet, and their data structure might be widely different from what our protonmail-api expect.

If anyone is willing and able to enlighten us, you're welcome

Sendgrid + ProtonMail works btw, free to get started & @ 50k emails a month just $19.99, not an ad but I saw this thread got discouraged tried Sendgrid it worked and now I am happy so just fyi! My environment is Namecheap + Vercel + Sveltekit + Protonmail + Sendgrid btw!