forked from amperser/proselint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clock.py
104 lines (77 loc) · 3.17 KB
/
clock.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
"""Check emails to editor@proselint.com, lint them, and reply."""
from apscheduler.schedulers.blocking import BlockingScheduler
import gmail
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from worker import conn
import requests
import hashlib
import json
import os
import logging
import re
logging.basicConfig()
scheduler = BlockingScheduler()
# Settings
user = "hello@lifelinter.com"
user_to = "editor@proselint.com"
name = "proselint"
password = os.environ['gmail_password']
tagline = "Proselint, a linter for prose."
url = "http://proselint.com"
api_url = "http://api.proselint.com/v0/"
def quoted(string, every=64):
"""Insert a quote before linebreaks."""
return "> " + re.sub("\r\n(?=[^\r\n])", "\r\n> ", string)
@scheduler.scheduled_job('interval', minutes=0.25)
def check_email():
"""Check the mail account and lint new mail."""
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login(user, password)
g = gmail.login(user, password)
# Check for unread messages.
unread = g.inbox().mail(unread=True)
# Submit a job to lint each email sent to editor@proselint.com. Record the
# resulting job_ids somewhere (in Redis, I suppose), keyed by a hash of the
# email.
for u in unread:
u.fetch()
signature = (u.fr.decode('utf-8') +
u.subject.decode('utf-8') +
u.body.decode('utf-8'))
hash = hashlib.sha256(signature.encode('utf-8')).hexdigest()
if user_to in u.to or user_to in u.headers.get('Cc', []):
job_id = conn.get(hash)
if not job_id:
# If the email hasn't been sent for processing, send it.
r = requests.post(api_url, data={"text": u.body})
conn.set(hash, r.json()["job_id"])
print("Email {} sent for processing.".format(hash))
else:
# Otherwise, check whether the results are ready, and if so,
# reply with them.
r = requests.get(api_url, params={"job_id": job_id})
if r.json()["status"] == "success":
reply = quoted(u.body)
errors = r.json()['data']['errors']
reply += "\r\n\r\n".join([json.dumps(e) for e in errors])
msg = MIMEMultipart()
msg["From"] = "{} <{}>".format(name, user)
msg["To"] = u.fr
msg["Subject"] = "Re: " + u.subject
if u.headers.get('Message-ID'):
msg.add_header("In-Reply-To", u.headers['Message-ID'])
msg.add_header("References", u.headers['Message-ID'])
body = reply + "\r\n\r\n--\r\n" + tagline + "\r\n" + url
msg.attach(MIMEText(body, "plain"))
text = msg.as_string()
server.sendmail(user, u.fr, text)
# Mark the email as read.
u.read()
u.archive()
print("Email {} has been replied to.".format(hash))
scheduler.start()