Search code examples
pythonseleniumauthenticationgoogle-accountpython-webbrowser

Logging into Gmail using Python with detecting failed login


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 protected]", "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.


Solution

  • 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: