mail-sync/proton.py

107 lines
4.9 KiB
Python

# 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