More seeds.
[ottawa-travel-planner.git] / mailPlanner.py
blob5ae1f5e2f8ba4f87f3447cb59f59ec9cf2eef011
1 #!/usr/bin/python
2 # vi: set softtabstop=4 shiftwidth=4 tabstop=8 expandtab:
4 import email.FeedParser
5 import email.iterators
6 from email.MIMEText import MIMEText
7 from email.Utils import parseaddr
8 import smtplib
9 import sys
10 import traceback
11 import syslog
13 import Planner
14 import PlanTime
15 import time
16 import CommandParser
17 import ShortFormatter
19 FROM_ADDRESS = "oc@hurts.ca"
20 SMTP_SERVER = "127.0.0.1"
22 HELP_TEXT = """Examples:
23 31 antares to 81 florence
24 stop 6097 to bayshore at 830 pm
25 merivale and baseline to 6097 by 9"""
27 def logIt(string):
28 syslog.syslog(syslog.LOG_INFO, string)
30 def sendMessage(msg, to):
31 msg['From'] = FROM_ADDRESS
32 msg['To'] = to
34 s = smtplib.SMTP(SMTP_SERVER)
35 s.sendmail(parseaddr(FROM_ADDRESS)[1], [parseaddr(msg['To'])[1]],
36 msg.as_string())
37 s.close()
39 def sendError(e, replyto):
40 sendMessage(MIMEText(e.args[0]), replyto)
42 def sendHelp(replyto):
43 sendMessage(MIMEText(HELP_TEXT), replyto)
45 def findFirstLine(msg):
46 for line in msg.get_payload(None, True).splitlines():
47 s = line.strip()
48 if len(s) != 0:
49 return s
50 return None
52 def handleMessage(msg, replyto):
53 try:
54 s = None
56 # Look for a text/plain part.
57 for subpart in email.iterators.typed_subpart_iterator(msg, "text",
58 "plain"):
59 s = findFirstLine(subpart)
60 if s is not None:
61 break
62 else:
63 # No text/plain sub-parts, or the message body was empty
64 raise Exception("Your message was empty, or was not in plain "
65 + "text format.\n\n"
66 + "For help, send the word 'help' by itself.\n")
68 if s is None:
69 logIt("Empty command from %s" % replyto)
70 sendHelp(replyto)
71 return 0
73 logIt(s)
74 if s.lower().startswith("help"):
75 sendHelp(replyto)
76 return 0
78 cmd = CommandParser.CommandParser(s).cmd
80 # Leave in 3 minutes if time is unspecified.
81 if cmd.time is None:
82 cmd.time = PlanTime.PlanTime(time.time() + 180,
83 PlanTime.MUST_LEAVE_AFTER)
85 itin = Planner.plan(cmd.start, cmd.end, cmd.time)
86 sf = ShortFormatter.ShortFormatter(itin.entries)
88 text = "\n".join(sf.lines)
89 if itin.anyUnparsed():
90 text += "\nWarning: This itinerary display may be incomplete!"
92 logIt("success, %d entries" % len(itin.entries))
93 sendMessage(MIMEText(text), replyto)
94 except Exception, e:
95 logIt("Exception: %s" % e)
96 logIt(traceback.format_exc())
97 sendError(e, replyto)
99 # Always return success. Otherwise Postfix will send a bounce message.
100 return 0
102 def main():
103 fp = email.FeedParser.FeedParser()
104 for line in sys.stdin:
105 fp.feed(line)
106 msg = fp.close()
108 # if these headers are here, we can reply semi-intelligently with errors
109 replyto = msg["reply-to"] or msg["from"]
110 return handleMessage(msg, replyto)
112 if __name__ == '__main__':
113 syslog.openlog(sys.argv[0], syslog.LOG_DAEMON)
114 sys.exit(main())