2 # vi: set softtabstop=4 shiftwidth=4 tabstop=8 expandtab:
4 import email
.FeedParser
6 from email
.MIMEText
import MIMEText
7 from email
.Utils
import parseaddr
20 FROM_ADDRESS
= "oc@hurts.ca"
21 SMTP_SERVER
= "127.0.0.1"
23 HELP_TEXT
= """Examples:
24 31 antares to 81 florence
25 stop 6097 to bayshore at 830 pm
26 merivale and baseline to 6097 by 9"""
29 syslog
.syslog(syslog
.LOG_INFO
, string
)
31 def sendMessage(msg
, to
):
32 msg
['From'] = FROM_ADDRESS
35 s
= smtplib
.SMTP(SMTP_SERVER
)
36 s
.sendmail(parseaddr(FROM_ADDRESS
)[1], [parseaddr(msg
['To'])[1]],
40 def sendError(e
, replyto
):
41 sendMessage(MIMEText(e
.args
[0]), replyto
)
43 def sendHelp(replyto
):
44 sendMessage(MIMEText(HELP_TEXT
), replyto
)
46 def findFirstLine(msg
):
47 for line
in msg
.get_payload(None, True).splitlines():
53 def handleMessage(msg
, replyto
):
57 # Look for a text/plain part.
58 for subpart
in email
.iterators
.typed_subpart_iterator(msg
, "text",
60 s
= findFirstLine(subpart
)
64 # No text/plain sub-parts, or the message body was empty
65 raise Exception("Your message was empty, or was not in plain "
67 + "For help, send the word 'help' by itself.\n")
70 logIt("Empty command from %s" % replyto
)
75 if s
.lower().startswith("help"):
79 cmd
= CommandParser
.CommandParser(s
).cmd
81 # Leave in 3 minutes if time is unspecified.
83 cmd
.time
= PlanTime
.PlanTime(time
.time() + 180,
84 PlanTime
.MUST_LEAVE_AFTER
)
86 itin
= Planner
.plan(cmd
.start
, cmd
.end
, cmd
.time
)
87 sf
= ShortFormatter
.ShortFormatter(itin
.entries
)
89 text
= "\n".join(sf
.lines
)
90 if itin
.anyUnparsed():
91 text
+= "\nWarning: This itinerary display may be incomplete!"
93 logIt("success, %d entries" % len(itin
.entries
))
94 sendMessage(MIMEText(text
), replyto
)
96 logIt("Exception: %s" % e
)
97 logIt(traceback
.format_exc())
100 # Always return success. Otherwise Postfix will send a bounce message.
103 def looksLikePostmaster(msg
, replyto
):
106 # from the vacation(1) manpage plus some extras
107 for s
in ('-request@', 'postmaster', 'uucp', 'mailer-daemon', 'mailer',
108 '-relay', 'abuse@', 'mailerdaemon', 'majordomo', 'maildaemon'):
112 p
= msg
["precedence"]
113 if p
and p
.lower() in ('bulk', 'junk', 'list'):
119 fp
= email
.FeedParser
.FeedParser()
120 for line
in sys
.stdin
:
124 # if these headers are here, we can reply semi-intelligently with errors
125 replyto
= msg
["reply-to"] or msg
["from"]
126 if looksLikePostmaster(msg
, replyto
):
127 logIt("Skipping reply to postmaster address '%s'" % replyto
)
130 return handleMessage(msg
, replyto
)
132 if __name__
== '__main__':
133 syslog
.openlog(sys
.argv
[0], syslog
.LOG_DAEMON
)