0
votes

The end goal is to send myself an email if my public ip address changes, as I don't have dynamic dns and have to manually enter the ip addresses myself for my web server. I've done all I possibly can to try and get bash utilities to do the job for me, but CenturyLink is unfortunately out to block me no matter how I configure my outbound mail.

So I've turned to graphical python/selenium web page automation, which will sign into my gmail account for me, click the 'compose' button, then enter in the To:, Subject:, and text segments and hit send. Everything is working except for one small part - the To: field. The html/css is different for this than all the others and no matter how I try to select the field using

driver.find_element_by_class_name()

or

driver.find_element_by_id()

I just can't seem to fill out the field. Bash will give me an error like

:lo cannot be reached by keyboard 

or textarea#:lo.vO is not a valid selector

When I did an inspect element, the element looked like this:

<textarea rows="1" id=":lo" 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: 462px;"></textarea>

My code so far is this: (note: which does not include getting ip info yet, just gmail login / manipulation)

from selenium import webdriver
import time

driver = webdriver.Firefox();
driver.get('https://www.gmail.com');
username = driver.find_element_by_id('identifierId');
username.send_keys("EMAIL");
driver.find_elements_by_class_name('RveJvd.snByac')[1].click();
time.sleep(2); #password not entered in username field
password = driver.find_element_by_class_name('whsOnd.zHQkBf');
password.send_keys("PASSWORD");
driver.find_elements_by_class_name('RveJvd.snByac')[0].click();

#end login, start composing

time.sleep(5); #wait for sign in
driver.find_element_by_class_name('T-I.J-J5-Ji.T-I-KE.L3').click();
to = driver.find_element_by_class_name('textarea#:lo.vO'); #incorrect
to.send_keys("EMAIL");
subject = driver.find_element_by_id(':l6');
subject.send_keys("IP Address changed");
content = driver.find_element_by_id(':m9');
content.send_keys("Test Test\n");
4
this sounds like an XY problem. Why is your question about emailing yourself when the issue you are trying to solve is about setting your webserver's IP?Corey Goldberg
Hi, seems to be an xpath or element inaccessible issue. Can you add the screen print of gmail login? I will try fetching the xpathSwadhikar
Just noted that the 'To:' text area element's id changes dynamically while composing message in different browserSwadhikar

4 Answers

1
votes

I think there seems to be a dynamic variation with the element ids in different browser. For me when I tried to compose the mail to fetch the XPATH I noted the XPATH was //*[@id=":oa"] but while the script launched it was //*[@id=":my"].

To accommodate this I have used element querying using XPATH //textarea[1] as the Recipients section is always the first textarea. This proves to work well consistently across different browser sessions.

Code Snippet

>>> d = webdriver.Chrome()
[14424:7728:0809/135301.805:ERROR:install_util.cc(597)] Unable to read registry value HKLM\SOFTWARE\Policies\Google\Chrome\MachineLevelUserCloudPolicyEnrollmentToken for writing result=2

DevTools listening on ws://127.0.0.1:12582/devtools/browser/31a5ab42-a4d2-46f3-95c6-a0c9ddc129d7
>>> d.get('https://www.gmail.com')
>>> d.find_element_by_xpath(xpath)
<selenium.webdriver.remote.webelement.WebElement (session="6072286733856e53b69af89ea981001c", element="0.42218760484088036-1")>
>>> d.find_element_by_xpath('//textarea[1]').send_keys('cswadhikar@gmail.com')

Result

compose

1
votes

Have you tried to use the Gmail API? It's easier faster and more efficient than using Selenium.

Here's the quickstart: https://developers.google.com/gmail/api/quickstart/python

(I'm writing an answer because I don't have the reputation to just comment)

1
votes
0
votes

Try this code to send an email with Gmail. It has To, Subject and Send button functionality :

driver.find_element(By.XPATH, '//*[@id=":k2"]/div/div').click()# Compose button time.sleep(5)

driver.find_element(By.NAME, 'to').send_keys("Enter the email address of recipients")# to field in compose time.sleep(2)

driver.find_element(By.NAME,'subjectbox').send_keys("This email is send using selenium")# Subject field in compose time.sleep(2)

driver.find_element(By.XPATH,'//*[@id=":p3"]').click()# click on send button

time.sleep(5)

driver.close()