138 lines
4.2 KiB
Python
Executable file
138 lines
4.2 KiB
Python
Executable file
#!/bin/env/python3
|
|
import os
|
|
import email
|
|
from datetime import datetime, timezone
|
|
|
|
from imapclient import IMAPClient
|
|
from smtplib import SMTP_SSL
|
|
|
|
from dateutil.parser import parse as d_parse
|
|
from cron_descriptor import get_description
|
|
from croniter import croniter
|
|
|
|
|
|
help_text = """
|
|
A very comprehensive help text
|
|
"""
|
|
service_address = "remindme@friedersdorff.com"
|
|
|
|
|
|
def empty_reply(msg):
|
|
reply = email.message.EmailMessage()
|
|
reply["Subject"] = f"RE: {msg['Subject']}"
|
|
reply["Message-ID"] = email.utils.make_msgid()
|
|
reply["In-Reply-To"] = msg["Message-ID"]
|
|
reply["References"] = msg["Message-ID"]
|
|
reply["To"] = msg["Reply-To"] or msg["From"]
|
|
reply["From"] = service_address
|
|
return reply
|
|
|
|
|
|
def list_reminders(person, client):
|
|
persons_messages = client.fetch(
|
|
client.search(["FROM", person]), "BODY.PEEK[]"
|
|
)
|
|
reminders = []
|
|
for uid, reminder in persons_messages.items():
|
|
reminder = email.message_from_bytes(reminder[b"BODY[]"])
|
|
reminders.append(
|
|
f"({uid}) {reminder['Subject']}: {reminder.get_payload().strip()}"
|
|
)
|
|
return "\n".join(reminders)
|
|
|
|
|
|
def ack_message(uid, message, client):
|
|
msg = email.message_from_bytes(message[b"BODY[]"])
|
|
if msg.is_multipart():
|
|
return None, True
|
|
client.delete_messages([uid])
|
|
|
|
payload = msg.get_payload().strip()
|
|
if payload.startswith("help"):
|
|
reply = empty_reply(msg)
|
|
reply.set_content(help_text)
|
|
return reply, True
|
|
|
|
reply = empty_reply(msg)
|
|
reply.set_content(list_reminders(msg["From"], client))
|
|
|
|
if payload.startswith("list"):
|
|
reply["Subject"] = f"List of active reminders (was: {reply['Subject']})"
|
|
return reply, True
|
|
else:
|
|
msg.replace_header("Subject", f"Set reminder: {reply['Subject']}")
|
|
prefix = (
|
|
f"Successfully set reminder: {payload}.\n\n" "Your reminders are:"
|
|
)
|
|
reply.set_content(f"{prefix}\n{reply.get_content()}")
|
|
return reply, False
|
|
|
|
|
|
def remind(uid, message, client):
|
|
msg = email.message_from_bytes(message[b"BODY[]"])
|
|
|
|
payload = msg.get_payload().strip()
|
|
if payload.startswith("repeat"):
|
|
try:
|
|
croniter(payload, datetime.now())
|
|
except Exception as e:
|
|
print("An error occured", e)
|
|
return None, False
|
|
|
|
remind_time = d_parse(payload.splitlines()[0])
|
|
if not remind_time.tzinfo:
|
|
sender_timezone = d_parse(msg["Date"]).tzinfo
|
|
remind_time = remind_time.replace(tzinfo=sender_timezone)
|
|
|
|
now = datetime.now(timezone.utc)
|
|
if now > remind_time:
|
|
reply = empty_reply(msg)
|
|
reply.replace_header("Subject", f"Reminder: {msg['Subject']}")
|
|
reply.set_content(f"This is a reminder:\n{msg['Subject']}")
|
|
return reply, True
|
|
else:
|
|
return None, False
|
|
|
|
|
|
def main():
|
|
mhost = "mail.friedersdorff.com"
|
|
user = os.environ["REMINDME_USERNAME"]
|
|
passwd = os.environ["REMINDME_PASS"]
|
|
with IMAPClient(host=mhost) as iclient, SMTP_SSL(mhost) as sclient:
|
|
iclient.login(user, passwd)
|
|
sclient.login(user, passwd)
|
|
iclient.select_folder("INBOX")
|
|
|
|
unseen_msgs = iclient.fetch(iclient.search(["UNSEEN"]), "BODY.PEEK[]")
|
|
for uid, message in unseen_msgs.items():
|
|
reply, delete = ack_message(uid, message, iclient)
|
|
try:
|
|
if reply:
|
|
sclient.send_message(reply)
|
|
if delete:
|
|
pass
|
|
# iclient.delete_messages([uid])
|
|
else:
|
|
pass
|
|
# iclient.set_flags([uid], [r"\SEEN"])
|
|
except Exception as e:
|
|
print("An error occured", e)
|
|
|
|
all_msgs = iclient.fetch(iclient.search(["NOT", "DELETED"]), "BODY[]")
|
|
for uid, message in all_msgs.items():
|
|
reply, delete = remind(uid, message, iclient)
|
|
try:
|
|
if reply:
|
|
sclient.send_message(reply)
|
|
if delete:
|
|
pass
|
|
# iclient.delete_messages([uid])
|
|
else:
|
|
pass
|
|
# iclient.set_flags([uid], [r"\SEEN"])
|
|
except Exception as e:
|
|
print("An error occured", e)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|