# for licensing information, please see LICENSE.md and README.md # copyright (c) rndusr, aka randomuser 2023 from selenium import webdriver from selenium.webdriver.common.by import By from common import MailProvider, MailMessage from selenium.common.exceptions import TimeoutException from selenium.common.exceptions import ElementNotInteractableException import json from time import sleep class ProtonWebmail(MailProvider): xpaths = { "username_box": "/html/body/div[1]/div[4]/div[1]/main/div[1]/div[2]/form/div[2]/div[1]/div/div/input", "password_box": "/html/body/div[1]/div[4]/div[1]/main/div[1]/div[2]/form/div[3]/div[1]/div/div[1]/input", "sign_in": "/html/body/div[1]/div[4]/div[1]/main/div[1]/div[2]/form/button", "messages": "/html/body/div[1]/div[3]/div/div[2]/div/div[2]/div/div/div/main/div/div/div/div/div/div[2]/div[2]", "messagebody": "/html/body/div[1]/div[3]/div/div[2]/div/div[2]/div/div/div/main/div/div/section/div/div[3]/div/div/article/div[2]", "backbutton": "//*[text()[contains(., 'Back')]]", "reply": "/html/body/div[1]/div[3]/div/div[2]/div/div[2]/div/div/div/main/div/div/section/div/div[3]/div/div/article/div[1]/div[4]/div[2]/button[1]", "replytextarea": "/html/body/div[1]/div[4]/div/div/div/div/section/div/div[1]/div/div/textarea", "replysubmit": "/html/body/div[1]/div[4]/div/div/div/footer/div/div[1]/button[1]", } def transform_message_header(self, header): return header.replace('\n', ' - ').replace('Unread email - ', '') def get(self): self.messages_failed = 0 self.read_data() self._get_webdriver() self.webdriver.get("https://account.proton.me/login") self._wait_for_elem(self.xpaths["username_box"]) sleep(0.5) self._type_in_elem(self.xpaths["username_box"], self.username) self._click_elem(self.xpaths["password_box"]) self._type_in_elem(self.xpaths["password_box"], self.password) self._click_elem(self.xpaths["sign_in"]) self._wait_for_elem(self.xpaths["messages"]) for i in self._get_elem_children(self._to_elem(self.xpaths["messages"])): index = self.transform_message_header(i.text) if not self.is_seen(index): text = i.text # we can interact with it, just selenium doesn't like it try: self._click_elem(i) except ElementNotInteractableException: pass self._wait_for_elem(self.xpaths["messagebody"]) sleep(5) self.webdriver.switch_to.frame( self._to_elem(self.xpaths["messagebody"]) \ .find_elements(By.XPATH, "//iframe")[0] ) splitted = index.split(' - ') message = MailMessage( index = self.transform_message_header(text), sender = splitted[0], subject = splitted[3], maintext = self.webdriver.page_source, ) self.add_to_seen(message) self.webdriver.switch_to.default_content() sleep(2) self._click_elem(self.xpaths["backbutton"]) sleep(2) else: # check if we have to reply to this email print("checking if we have to reply") search = self.transform_message_header(i.text) selected = None for message in self.seen_messages: if message.index == search: selected = message if not selected: continue for message_to_send in self.to_send: print('loop iter 1') print(message_to_send.in_response_to_id, selected.id) if message_to_send.in_response_to_id == selected.id: # we do have to reply print("sending reply to message id {}".format(str(selected.id))) try: self._click_elem(i) except ElementNotInteractableException: pass self._wait_for_elem(self.xpaths["messagebody"]) sleep(5) self._click_elem(self.xpaths["reply"]) sleep(1) replytextarea = self._to_elem(self.xpaths["replytextarea"]) replytextarea.clear() replytextarea.send_keys(message_to_send.body) sleep(1) self._click_elem(self.xpaths["replysubmit"]) sleep(2) self._click_elem(self.xpaths["backbutton"]) sleep(2) self.write_data() self.webdriver.quit() return self