-
Notifications
You must be signed in to change notification settings - Fork 0
/
ics2email.py
116 lines (91 loc) · 4.17 KB
/
ics2email.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import requests
import smtplib
import sqlite3
import yaml
from email.message import EmailMessage
from email.utils import make_msgid, formatdate
from ics import Calendar
from os import path
from re import sub
from slugify import slugify
def get_smtp_session():
s = smtplib.SMTP_SSL(smtp_url)
s.login(*smtp_credentials)
return s
def send_email(to, subj, body, attachment=None, smtp_session=get_smtp_session):
msg = EmailMessage()
msg['Subject'] = subj
msg['From'] = f'{from_name} <{from_address}>'
msg['To'] = to
msg['Date'] = formatdate(localtime=True)
msg['Message-ID'] = make_msgid(domain=from_address.split('@')[1])
msg.add_header('List-Unsubscribe', f'<mailto:{from_address}?subject={calendar_name}-ics2email-unsubscribe>')
msg.set_content(sub('<[^<]+?>', '', body))
msg.add_alternative(body, subtype='html')
if attachment:
msg.add_attachment(cal_template.format(attachment.serialize()).encode('utf-8'), maintype='text', subtype='calendar',
filename=f"{slugify(attachment.name)}.ics")
with smtp_session() as session:
session.send_message(msg)
if __name__ == '__main__':
# load config file
if not path.exists('config.yaml'):
raise Exception('config.yaml not found')
data = yaml.load(open('config.yaml', 'r'), Loader=yaml.FullLoader)
email_addresses = data.get('recipients')
smtp_url = data.get('smtp-url')
smtp_credentials = data.get('smtp-credentials')
calendar_url = data.get('ics-url')
from_name = data.get('from-name')
from_address = data.get('from-address')
calendar_name = data.get('calendar-name')
cal_template = '''
BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
{}
END:VCALENDAR'''
# db connection
con = sqlite3.connect("calendar-data.db")
cur = con.cursor()
# create db table if it doesn't already exist
cur.execute("CREATE TABLE IF NOT EXISTS ics_events (uid TEXT, created TEXT, last_modified TEXT)")
con.commit()
# load known events from database
known_events = {}
for row in cur.execute("SELECT uid, created, last_modified FROM ics_events"):
known_events[row[0]] = {
'created': row[1],
'last_modified': row[2]
}
c = Calendar(requests.get(calendar_url).text)
for event in c.events:
if event.uid not in known_events:
print(f'New event: {event.name}')
for address in email_addresses:
send_email(
address,
f'New Event: {event.name}',
f'''<h1>New {calendar_name} Event: {event.name}</h1>
<time datetime="{event.begin.format()}"><strong>start:</strong> {event.begin.format()}</time><BR>
<time datetime="{event.end.format()}"><strong>end:</strong> {event.end.format()}</time><BR>
{f'<a href="{event.url}">{event.url}</a><BR><BR>' if event.url else '<BR>'}
<p>{event.description}</p>''',
event)
cur.execute("INSERT INTO ics_events VALUES (?, ?, ?)", (event.uid, event.created.format(), event.last_modified.format() if event.last_modified else None))
con.commit()
elif known_events[event.uid]['last_modified'] != event.last_modified.format():
print(f'Event modified: {event.name}')
for address in email_addresses:
send_email(
address,
f'Updated Event: {event.name}',
f'''<h1>Updated {calendar_name} Event: {event.name}</h1>
<time datetime="{event.begin.format()}"><strong>start:</strong> {event.begin.format()}</time><BR>
<time datetime="{event.end.format()}"><strong>end:</strong> {event.end.format()}</time><BR>
{f'<a href="{event.url}">{event.url}</a><BR><BR>' if event.url else '<BR>'}
<p>{event.description}</p>''',
event)
# update last_modified record
cur.execute("UPDATE ics_events SET last_modified = ? WHERE uid = ?", (event.last_modified.format(), event.uid))
con.commit()