如何在 protonmail.com 上访问iframe中的消息字段?

How to access message field inside iframe on protonmail.com?

提问人:achille 提问时间:10/29/2023 最后编辑:tripleeeachille 更新时间:10/29/2023 访问量:37

问:

我正在尝试在 Protonmail 服务器上使用 Python Selenium 发送电子邮件。一切正常,直到我收到电子邮件。

要访问电子邮件字段,我使用以下 xpath:。当通过 DOM 手动搜索时,它会给出一个独特的元素(Chromium 也给出相同的 xpath)。"//div[@id='rooster-editor']/div[1]"

但是在脚本中,此 XPath 会抛出“没有此类元素”异常。我首先认为该错误是由页面未完全加载的事实引起的,如这篇文章中所述:Selenium Webdriver - NoSuchElementExceptions。 为了避免这个问题,我插入了一个 20 秒 ,但问题仍然存在。implicitly_wait

我也不认为这个功能可以解决这个问题:因为我的片段比手动发送电子邮件慢。EC.presence_of_element_located(By.XPATH,"//div[@id='rooster-editor']/div[1]"

总而言之,这是我在代码片段中引入一些“等待”或“时间睡眠”的地方:从单击“新消息”按钮 - >隐式等待 20 秒 - >填写收件人电子邮件 - > 2 秒睡眠 - >电子邮件主题 - > 3 秒睡眠 - >然后电子邮件。因此,我不认为问题可能是由未完全加载的页面引起的。

所以我的问题是:什么会带来这样的例外?

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

class FindProton():
        def test(self, recipient, subject, msg):
            self.recipient = recipient
            self.subject = subject
            self.msg = msg
            baseUrl = 'https://www.protonmail.com'
            driver = webdriver.Firefox()
            driver.get(baseUrl)
            driver.maximize_window()
            driver.implicitly_wait(5)
            time.sleep(2)
    
            #SIGN IN 
            elementXpath = driver.find_element(By.XPATH,"//span[text()='Sign in']") 
            elementXpath.click()
    
            #USERNAME 
            time.sleep(3)
            #elementId_0 = driver.find_element(By.ID,'username').click()
            elementId_0 = driver.find_element(By.ID,'username')
            #elementId_0.send_keys(self.user)
            elementId_0.send_keys('xxxxxxx')
    
            #PASSWORD
            time.sleep(1)
            elementId_1 = driver.find_element(By.ID,'password')
            #elementId_1.send_keys(self.passwd)
            elementId_1.send_keys('xxxxxx')
    
            time.sleep(2)
            elementId_2 = driver.find_element(By.XPATH,"//button[text()='Sign in']")
            elementId_2.click()
    
            #my router is the hell slow so I introduce a long implicit wait...
            driver.implicitly_wait(20)
            #time.sleep(1)
            elementId_3 = driver.find_element(By.XPATH,"//button[text()='New message']")
            elementId_3.click()
    
            driver.implicitly_wait(15)
            #recipient ; part of id=dynamic, so use id contains 
            element_4 = driver.find_element(By.XPATH,"//input[contains(@id,'to-composer-')]")
            element_4.send_keys(self.recipient)
    
            time.sleep(2)
            #subject, part of id = dynamic, so use id contains 
            element_5 = driver.find_element(By.XPATH,"//input[contains(@id,'subject-composer-')]")
            element_5.send_keys(self.subject)
               
            time.sleep(3)
            #email message: BUG HERE !
            element_6 = driver.find_element(By.XPATH,"//div[@id='rooster-editor']/div[1]").click()

    ff=FindProton()
    ff.test('unkn[email protected]','no subject email','this is a short message')
python selenium-webdriver nosuchelementexception

评论

0赞 tripleee 10/29/2023
使用 Selenium 实现自动化似乎是错误的。Proton Bridge 允许您为此使用标准 SMTP。

答:

2赞 Yaroslavm 10/29/2023 #1

消息区域放置在带有选择器的 iframe 中。[data-testid=rooster-iframe]

因此,要访问该元素,您需要先切换到 iframe 内容。

另请注意,该消息不是输入字段,要键入,您应该单击它并首先模拟键盘操作。

在 iframe 中键入 / 任何其他操作后,要访问以前的上下文,您应该切换到默认上下文。

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
import time

   #your code
   action_chains = ActionChains(driver)
   message_frame = driver.find_element(By.CSS_SELECTOR, '[data-testid=rooster-iframe]')
   driver.switch_to.frame(message_frame)

   element_6 = driver.find_element(By.XPATH, "//div[@id='rooster-editor']/div[1]")
   element_6.click()
   action_chains.send_keys(msg).perform()
   # if you finished with actions inside iframe - add line below
   driver.switch_to.default_content()