diff --git a/roundup/mailgw.py b/roundup/mailgw.py
index a2c15e30658c7a203d9e7c5efdeaa32ea12bdb00..19151b2108934e9c711511fe468dcfcd023e0a7c 100644 (file)
--- a/roundup/mailgw.py
+++ b/roundup/mailgw.py
an exception, the original message is bounced back to the sender with the
explanatory message given in the exception.
an exception, the original message is bounced back to the sender with the
explanatory message given in the exception.
-$Id: mailgw.py,v 1.10 2001-08-07 00:24:42 richard Exp $
+$Id: mailgw.py,v 1.15 2001-08-30 06:01:17 richard Exp $
'''
import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
import traceback
'''
import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
import traceback
-import date
+import hyperdb, date
+
+class MailUsageError(ValueError):
+ pass
class Message(mimetools.Message):
''' subclass mimetools.Message so we can retrieve the parts of the
class Message(mimetools.Message):
''' subclass mimetools.Message so we can retrieve the parts of the
'''
# ok, figure the subject, author, recipients and content-type
message = Message(fp)
'''
# ok, figure the subject, author, recipients and content-type
message = Message(fp)
+ m = []
try:
self.handle_message(message)
try:
self.handle_message(message)
+ except MailUsageError, value:
+ # bounce the message back to the sender with the usage message
+ fulldoc = '\n'.join(string.split(__doc__, '\n')[2:])
+ sendto = [message.getaddrlist('from')[0][1]]
+ m = ['Subject: Failed issue tracker submission', '']
+ m.append(str(value))
+ m.append('\nMail Gateway Help\n=================')
+ m.append(fulldoc)
except:
# bounce the message back to the sender with the error message
sendto = [message.getaddrlist('from')[0][1]]
except:
# bounce the message back to the sender with the error message
sendto = [message.getaddrlist('from')[0][1]]
except:
pass
m.append(fp.read())
except:
pass
m.append(fp.read())
+ if m:
try:
smtp = smtplib.SMTP(self.MAILHOST)
smtp.sendmail(self.ADMIN_EMAIL, sendto, '\n'.join(m))
try:
smtp = smtplib.SMTP(self.MAILHOST)
smtp.sendmail(self.ADMIN_EMAIL, sendto, '\n'.join(m))
Parse the message as per the module docstring.
'''
# handle the subject line
Parse the message as per the module docstring.
'''
# handle the subject line
- m = subject_re.match(message.getheader('subject'))
+ subject = message.getheader('subject', '')
+ m = subject_re.match(subject)
if not m:
if not m:
- raise ValueError, 'No [designator] found in subject "%s"'
+ raise MailUsageError, '''
+The message you sent to roundup did not contain a properly formed subject
+line. The subject must contain a class name or designator to indicate the
+"topic" of the message. For example:
+ Subject: [issue] This is a new issue
+ - this will create a new issue in the tracker with the title "This is
+ a new issue".
+ Subject: [issue1234] This is a followup to issue 1234
+ - this will append the message's contents to the existing issue 1234
+ in the tracker.
+
+Subject was: "%s"
+'''%subject
classname = m.group('classname')
nodeid = m.group('nodeid')
title = m.group('title').strip()
subject_args = m.group('args')
classname = m.group('classname')
nodeid = m.group('nodeid')
title = m.group('title').strip()
subject_args = m.group('args')
- cl = self.db.getclass(classname)
+ try:
+ cl = self.db.getclass(classname)
+ except KeyError:
+ raise MailUsageError, '''
+The class name you identified in the subject line ("%s") does not exist in the
+database.
+
+Valid class names are: %s
+Subject was: "%s"
+'''%(classname, ', '.join(self.db.getclasses()), subject)
properties = cl.getprops()
props = {}
args = m.group('args')
properties = cl.getprops()
props = {}
args = m.group('args')
try:
key, value = prop.split('=')
except ValueError, message:
try:
key, value = prop.split('=')
except ValueError, message:
- raise ValueError, 'Args list not of form [arg=value,value,...;arg=value,value,value..] (specific exception message was "%s")'%message
- type = properties[key]
- if type.isStringType:
+ raise MailUsageError, '''
+Subject argument list not of form [arg=value,value,...;arg=value,value...]
+ (specific exception message was "%s")
+
+Subject was: "%s"
+'''%(message, subject)
+ try:
+ type = properties[key]
+ except KeyError:
+ raise MailUsageError, '''
+Subject argument list refers to an invalid property: "%s"
+
+Subject was: "%s"
+'''%(key, subject)
+ if isinstance(type, hyperdb.String):
props[key] = value
props[key] = value
- elif type.isDateType:
+ elif isinstance(type, hyperdb.Date):
props[key] = date.Date(value)
props[key] = date.Date(value)
- elif type.isIntervalType:
+ elif isinstance(type, hyperdb.Interval):
props[key] = date.Interval(value)
props[key] = date.Interval(value)
- elif type.isLinkType:
+ elif isinstance(type, hyperdb.Link):
props[key] = value
props[key] = value
- elif type.isMultilinkType:
+ elif isinstance(type, hyperdb.Multilink):
props[key] = value.split(',')
# handle the users
props[key] = value.split(',')
# handle the users
attachments.append((name, part.gettype(), data))
if content is None:
attachments.append((name, part.gettype(), data))
if content is None:
- raise ValueError, 'No text/plain part found'
+ raise MailUsageError, '''
+Roundup requires the submission to be plain text. The message parser could
+not find a text/plain part o use.
+'''
elif content_type[:10] == 'multipart/':
# skip over the intro to the first boundary
elif content_type[:10] == 'multipart/':
# skip over the intro to the first boundary
# this one's our content
content = part.fp.read()
if content is None:
# this one's our content
content = part.fp.read()
if content is None:
- raise ValueError, 'No text/plain part found'
+ raise MailUsageError, '''
+Roundup requires the submission to be plain text. The message parser could
+not find a text/plain part o use.
+'''
elif content_type != 'text/plain':
elif content_type != 'text/plain':
- raise ValueError, 'No text/plain part found'
+ raise MailUsageError, '''
+Roundup requires the submission to be plain text. The message parser could
+not find a text/plain part o use.
+'''
else:
content = message.fp.read()
else:
content = message.fp.read()
message_id = self.db.msg.create(author=author,
recipients=recipients, date=date.Date('.'), summary=summary,
content=content, files=files)
message_id = self.db.msg.create(author=author,
recipients=recipients, date=date.Date('.'), summary=summary,
content=content, files=files)
- messages = cl.get(nodeid, 'messages')
+ try:
+ messages = cl.get(nodeid, 'messages')
+ except IndexError:
+ raise MailUsageError, '''
+The node specified by the designator in the subject of your message ("%s")
+does not exist.
+
+Subject was: "%s"
+'''%(nodeid, subject)
messages.append(message_id)
props['messages'] = messages
cl.set(nodeid, **props)
messages.append(message_id)
props['messages'] = messages
cl.set(nodeid, **props)
#
# $Log: not supported by cvs2svn $
#
# $Log: not supported by cvs2svn $
+# Revision 1.14 2001/08/13 23:02:54 richard
+# Make the mail parser a little more robust.
+#
+# Revision 1.13 2001/08/12 06:32:36 richard
+# using isinstance(blah, Foo) now instead of isFooType
+#
+# Revision 1.12 2001/08/08 01:27:00 richard
+# Added better error handling to mailgw.
+#
+# Revision 1.11 2001/08/08 00:08:03 richard
+# oops ;)
+#
+# Revision 1.10 2001/08/07 00:24:42 richard
+# stupid typo
+#
# Revision 1.9 2001/08/07 00:15:51 richard
# Added the copyright/license notice to (nearly) all files at request of
# Bizar Software.
# Revision 1.9 2001/08/07 00:15:51 richard
# Added the copyright/license notice to (nearly) all files at request of
# Bizar Software.