0

I'm writing a python-selenium script to send emails automatically using mail.google.com.

HTML Page :

<textarea rows="1" id=":125" class="vO" name="to" spellcheck="false" autocomplete="false" autocapitalize="off" autocorrect="off" tabindex="1" dir="ltr" aria-label="To" role="combobox" aria-autocomplete="list" style="width: 391px;"></textarea>

What I tried :

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver=webdriver.Firefox()
#Open URL
driver.get("https://mail.google.com/") 
#Enter username
driver.find_element_by_id("identifierId").send_keys("test@gmail.com") 
#click next button in username page
driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/div/div[1]/div/content/span").click()
sleep(4) 
#Enter password
password_xpath="/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/content/form/div[1]/div/div[1]/div/div[1]/input"
driver.find_element_by_xpath(password_xpath).send_keys("test")
#click next button in password page
driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/div/div[1]/div/content/span").click()
sleep(2) 
#Compose new mail
driver.get("https://mail.google.com/mail/u/0/#inbox?compose=new")
sleep(6) 
#Type Recipient's email address
#The following code is to enter the Recipient's email address in Compose Window
#----------------------------------------------------------------------------
driver.find_element_by_id(":125").send_keys("abc@gmail.com")
#driver.find_element_by_name("to").send_keys("abc@gmail.com")
#driver.find_element_by_xpath("//*[@id=':125']").send_keys("abc@gmail.com")
#driver.find_element_by_link_text("To").send_keys("abc@gmail.com")
#driver.find_element_by_partial_link_text("To").send_keys("abc@gmail.com")
#driver.find_element_by_link_text("Recipients").send_keys("abc@gmail.com")
#driver.find_element_by_partial_link_text("Recipients").send_keys("abc@gmail.com")
#driver.find_element_by_tag_name("textarea").send_keys("abc@gmail.com")
#driver.find_element_by_class_name("v0").send_keys("abc@gmail.com")
#driver.find_element_by_class_name("wA").send_keys("abc@gmail.com")
#driver.find_element_by_css_selector("#\:125").send_keys("abc@gmail.com")
#----------------------------------------------------------------------------
#Type Subject
#driver.find_element_by_id(":125").send_keys("abc@gmail.com")
#Type Content
#driver.find_element_by_id(":125").send_keys("abc@gmail.com")
#Click Send button
#driver.find_element_by_id(":15r").click()

Issue:

It takes some time to load and display the Compose window. So it shows "Unable to locate element" as the compose window is not displayed due to slow Internet Connection.

Output:

selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: [id=":125"]
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: [name="to"]
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: //*[@id=':125']

I used the following code from the here

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, ":125"))).send_keys("abc")

But it shows the following error:

Traceback (most recent call last):
  File "sendmail2.py", line 24, in <module>
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, ":125"))).send_keys("abc")
  File "/home/dipankar/.local/lib/python2.7/site-packages/selenium/webdriver/support/wait.py", line 80, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 

EDIT: (Here is the complete HTML code)

<div class="wO nr l1"><input class="wA" tabindex="-1" aria-hidden="true"><textarea rows="1" id=":zo" class="vO" name="to" spellcheck="false" autocomplete="false" autocapitalize="off" autocorrect="off" tabindex="1" dir="ltr" aria-label="To" role="combobox" aria-autocomplete="list" style="width: 391px;"></textarea><div class="aA6"><span><div style="width: 1px; height: 1px; position: absolute;" tabindex="1"></div><div style="width: 1px; height: 1px; position: absolute;" tabindex="1"></div><span><span id=":14u" class="aB gQ pE" role="link" tabindex="1" data-tooltip="Add Cc Recipients ‪(Ctrl-Shift-C)‬" aria-label="Add Cc Recipients ‪(Ctrl-Shift-C)‬" style="-moz-user-select: none;">Cc</span><span id=":14r" class="aB  gQ pB" role="link" tabindex="1" data-tooltip="Add Bcc Recipients ‪(Ctrl-Shift-B)‬" aria-label="Add Bcc Recipients ‪(Ctrl-Shift-B)‬" style="-moz-user-select: none;">Bcc</span><span id=":10m" role="button" tabindex="1" aria-hidden="false" class="bcV" style="visibility: visible; display: none;" data-tooltip="Some recipients use services that don't support encryption (click for details)" aria-label="Some recipients use services that don't support encryption (click for details)"></span></span><div style="width: 1px; height: 1px; position: absolute;" tabindex="1"></div></span></div></div>

EDIT 2: Temporary Solution: [ The following code works ]

(Here I increased the waiting time as the Network Speed is low.)

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver=webdriver.Firefox()
#Open URL
driver.get("https://mail.google.com/") 
#Enter username
driver.find_element_by_id("identifierId").send_keys("sender@gmail.com") 
#click next button in username page
driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/div/div[1]/div/content/span").click()
sleep(4) 
#Enter password
password_xpath="/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/content/form/div[1]/div/div[1]/div/div[1]/input"
driver.find_element_by_xpath(password_xpath).send_keys("test")
#click next button in password page
driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div[2]/div/div/div[2]/div/div/div[1]/div/content/span").click()
sleep(2) 
#Compose new mail
compose_button_xpath="/html/body/div[7]/div[3]/div/div[2]/div[1]/div[1]/div[1]/div[2]/div/div/div/div[1]/div/div"
driver.find_element_by_xpath(compose_button_xpath).click()
sleep(10)
#Wait 20 seconds for compose window. It depends upon network speed
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, ":zo")))
#The following code is to enter the Recipient's email address in Compose Window
driver.find_element_by_xpath("//*[@id=':125']").send_keys("receiver@gmail.com,")
#Type Subject
driver.find_element_by_name("subjectbox").send_keys("Subject123")
#Type Content
driver.find_element_by_xpath("//*[@id=':12s']").send_keys("Content")
#Click Send button
driver.find_element_by_xpath("//*[@id=':11d']").click()
Dipankar Nalui
  • 1,121
  • 5
  • 18
  • 33

2 Answers2

0

You can use below Xpath

driver.find_element_by_xpath("//textarea[@name='to']").send_keys("abc@gmail.com")
Prany
  • 2,078
  • 2
  • 13
  • 31
  • It works for `driver.find_element_by_xpath("//*[@id=':125']")` – Dipankar Nalui Jun 21 '18 at 19:43
  • problem is not with finding element. Problem is "compose window is taking too much time to display." so it has to wait until the compose window is displayed. inside compose window, we can find the above element. if compose window is displayed, then element is found. – Dipankar Nalui Jun 21 '18 at 19:47
  • I see in your code, you've used webdriver wait. isn't that solving your problem? – Prany Jun 22 '18 at 17:11
  • Yes, it works. But it is a temporary solution. Because sometimes the internet connection is too slow. So it is really difficult to handle the `WebDriverWait()`. I need to change the second parameter of this function based on internet speed. – Dipankar Nalui Jun 24 '18 at 12:29
  • You can try by adding implicit wait - driver.implicitly_wait(20) – Prany Jun 24 '18 at 17:47
-1

You can implement a function which waits for the appearance of a certain element. Maybe something like this:

from selenium.common.exceptions import NoSuchElementException

def wait_for_element(driver, id_selector, timeout=30):
    start = time.time()

    while time.time() - start < timeout:
        try:
            return driver.find_element_by_id(id_selector)
        except NoSuchElementException:
            time.sleep(0.1)
            continue
    raise NoSuchElementException

Obviously you cannot wait till infinity so there should be a timeout. Then in your code:

my_input = wait_for_element(driver, ":125")
my_input.send_keys("abc@gmail.com")
Innuendo
  • 631
  • 5
  • 9