1

I know that multiple people have asked a similar question about this however, I would like to know how to login to gmail (or google account) using python. I have a code already (see below) that can loggin the user to gmail using selenium. However I noticed a few problems.

  1. The browser closes when the program stops/closes.
  2. It can not detect a failed login.

Both problems really need to be solved for me to be able to work on my project. I don't mind using something else than selenium like pyautogui to open google. However, it needs to be able to detect a failed login and then close the browser, if the login is successful the browser should stay open for the user to use.

My code:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

def gmail_login(username, password):
    gmailId = username
    passWord = password
    driver = webdriver.Chrome(ChromeDriverManager().install())
    try:
        driver.get(r'https://accounts.google.com/signin/v2/identifier?continue=' + \
                   'https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1' + \
                   '&flowName=GlifWebSignIn&flowEntry = ServiceLogin')
        driver.implicitly_wait(3)

        loginBox = driver.find_element_by_xpath('//*[@id ="identifierId"]')
        loginBox.send_keys(gmailId)

        nextButton = driver.find_elements_by_xpath('//*[@id ="identifierNext"]')
        nextButton[0].click()

        passWordBox = driver.find_element_by_xpath(
            '//*[@id ="password"]/div[1]/div / div[1]/input')
        passWordBox.send_keys(passWord)

        nextButton = driver.find_elements_by_xpath('//*[@id ="passwordNext"]')
        nextButton[0].click()

    except:
        driver.close()


gmail_login("email@gmail.com", "Password")

I tought of checking the url after the program has finished if it is equal to a logged in url however that didn't really work too well and now I am out of ideas.

Deepak Rai
  • 2,163
  • 3
  • 21
  • 36
  • So you want the browser to stay open after login and you also want an error message to be thrown on a failed login? – Life is complex Feb 13 '21 at 05:06
  • exactly. And close the browser with failed login. – Jordy van Dongen Feb 13 '21 at 09:53
  • Did you try the code that I sent you via discord? The code works on my end, so you need to troubleshoot the code in stages. stage 1 - connect to site, stage 2 - enter username, stage 3 - click next button, etc. – Life is complex Feb 16 '21 at 12:55
  • Does this answer your question? [“This browser or app may not be secure” error while attempting to login in to Gmail account using GeckoDriver Firefox through Selenium and Python](https://stackoverflow.com/questions/59515561/this-browser-or-app-may-not-be-secure-error-while-attempting-to-login-in-to-gm) – questioning Nov 29 '21 at 10:39
  • @questioning Not really, this question was about the error message of entering the incorrect username/password and how it could detect that. I was able to get around the "insecure browser" error before. – Jordy van Dongen Dec 01 '21 at 16:33

3 Answers3

2

Updated 02-14-2021


I was able to extract this error message:

enter image description here

using this code:

signin_failure = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t sign you in')]")
if signin_failure[1].text == 'Couldn’t sign you in':
   print('something went wrong')

In a normal gmail login you will get one of these two error messages:

  • Couldn’t find your Google Account
  • Wrong password. Try again or click Forgot password to reset it

The XPATH to get these error messages is:

wrong_email = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t find your Google Account')]")

wrong_password = driver.find_elements_by_xpath("//*[contains(text(),'Wrong password. Try again or click Forgot password to reset it')]")

if you want to close the browser after an error message, such as Couldn’t sign you in then add a driver.close() statement.

signin_failure = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t sign you in')]")
if signin_failure[1].text == 'Couldn’t sign you in':
   print('something went wrong')
   driver.close()

If you want to keep the browser open then don't use the driver.close() statement, but add this experimental_option

chrome_options.add_experimental_option("detach", True)

I was also able to throw these error messages:

signin_failure = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t sign you in')]")

# this message was throw when the next button was clicked prior to entering a username
no_input = driver.find_elements_by_xpath("//*[contains(text(),'Enter a valid email of phone number')]")

PSEUDOCODE CODE:

This is how you could do it, but you might have to adjust the code as you test.

def gmail_login(username, password):
    driver = webdriver.Chrome(ChromeDriverManager().install())
    try:
        driver.get(r'https://accounts.google.com/signin/v2/identifier?continue=' + \
                   'https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1' + \
                   '&flowName=GlifWebSignIn&flowEntry = ServiceLogin')
        driver.implicitly_wait(3)

        loginBox = driver.find_element_by_xpath('//*[@id ="identifierId"]')
        loginBox.send_keys(username)

        nextButton = driver.find_elements_by_xpath('//*[@id ="identifierNext"]')
        nextButton[0].click()

        wrong_email = driver.find_elements_by_xpath("//*[contains(text(),'Couldn’t find your Google Account')]")

        # you need to check this slice
        if wrong_email[1].text == 'Couldn’t find your Google Account':
            print('something went wrong')
            driver.close()

        else:
            passWordBox = driver.find_element_by_xpath('//*[@id ="password"]/div[1]/div / div[1]/input')
            passWordBox.send_keys(password)

            nextButton = driver.find_elements_by_xpath('//*[@id ="passwordNext"]')
            nextButton[0].click()

            wrong_password = driver.find_elements_by_xpath("//*[contains(text(),'Wrong password. Try again or click Forgot password to reset it')]")

            # you need to check this slice
            if wrong_password[1].text == 'Wrong password. Try again or click Forgot password to reset it':
                print('something went wrong')
                driver.close()

    except:
        driver.close()

Original post


Google forbids using automated scripts for logging into Gmail. I have tried using selenium and I get this warning.

Cannot sign-in

When I click Learn More I get this message.

enter image description here

Please note this line: Are being controlled through software automation rather than a human

Here are other question where they discuss work arounds for this Google direct login issue:

Life is complex
  • 15,374
  • 5
  • 29
  • 58
1

You should be looking at the Gmail API for programmatic access, it will work a lot better than trying to drive the UI like selenium does. https://developers.google.com/gmail/api/quickstart/python

eemz
  • 1,183
  • 6
  • 10
  • I have heard of the Gmail API, however, this will be a simple Tkinter project for my school to login easily. They cannot all enable the Gmail API to open their account. – Jordy van Dongen Feb 06 '21 at 11:54
  • 1
    Have you tried this solution to log in first via stackoverflow and navigate to gmail.com: https://stackoverflow.com/questions/59515561/this-browser-or-app-may-not-be-secure-error-while-attempting-to-login-in-to-gm/62195934 . Failed login you should be able to catch easily over there in the alert messages at the bottom of the text field in case of failed account/password entry. – automationleg Feb 12 '21 at 23:31
  • I understand what you mean, however I will not the only person using this. This part of the code will be connected to a Tkinter program for everyone to use in my school. I don't think anybody in my school has a stackoverflow account, and I can't expect all of them to create one. Thanks for the suggestion, however. – Jordy van Dongen Feb 13 '21 at 09:59
1

I have no time right now to code, but:

To make your browser stay open just delete your driver.close() function, this is what makes it to stop when program reach it.

To solve your problem, just try to make a successfull login and a failing one, look for a WebElement in both that indicates one of the events in an unique way, then, put the driver.close() in an if declaration only if selenium finds the WebElement in viewport after the login (failed one), otherwise do not let it execute the instruction.

Easy as that.