diff --git a/roundup/mailgw.py b/roundup/mailgw.py
index 94655476de3217461f77235d95ccb0bbd0dd9671..a2c15e30658c7a203d9e7c5efdeaa32ea12bdb00 100644 (file)
--- a/roundup/mailgw.py
+++ b/roundup/mailgw.py
+#
+# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
+# This module is free software, and you may redistribute it and/or modify
+# under the same terms as Python, so long as this copyright message and
+# disclaimer are retained in their original form.
+#
+# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
+# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+#
'''
An e-mail gateway for Roundup.
an exception, the original message is bounced back to the sender with the
explanatory message given in the exception.
-$Id: mailgw.py,v 1.5 2001-07-29 07:01:39 richard Exp $
+$Id: mailgw.py,v 1.10 2001-08-07 00:24:42 richard Exp $
'''
else:
content = message.fp.read()
- # extract out the summary from the message
- summary = []
- for line in content.split('\n'):
- line = line.strip()
- if summary and not line:
- break
- if not line:
- summary.append('')
- elif line[0] not in '>|':
- summary.append(line)
- summary = '\n'.join(summary)
+ summary, content = parseContent(content)
# handle the files
files = []
for (name, type, data) in attachments:
- files.append(self.db.file.create(type=type, name=name, content=data))
+ files.append(self.db.file.create(type=type, name=name,
+ content=data))
# now handle the db stuff
if nodeid:
- # If an item designator (class name and id number) is found there, the
- # newly created "msg" node is added to the "messages" property for
- # that item, and any new "file" nodes are added to the "files"
+ # If an item designator (class name and id number) is found there,
+ # the newly created "msg" node is added to the "messages" property
+ # for that item, and any new "file" nodes are added to the "files"
# property for the item.
- 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')
messages.append(message_id)
props['messages'] = messages
- apply(cl.set, (nodeid, ), props)
+ cl.set(nodeid, **props)
else:
# If just an item class name is found there, we attempt to create a
# new item of that class with its "messages" property initialized to
# contain the new "msg" node and its "files" property initialized to
# contain any new "file" nodes.
- message_id = self.db.msg.create(author=author, recipients=recipients,
- date=date.Date('.'), summary=summary, content=content,
- files=files)
- if not props.has_key('assignedto'):
+ message_id = self.db.msg.create(author=author,
+ recipients=recipients, date=date.Date('.'), summary=summary,
+ content=content, files=files)
+ # fill out the properties with defaults where required
+ if properties.has_key('assignedto') and \
+ not props.has_key('assignedto'):
props['assignedto'] = '1' # "admin"
- if not props.has_key('priority'):
- props['priority'] = '1' # "bug-fatal"
- if not props.has_key('status'):
+ if properties.has_key('status') and not props.has_key('status'):
props['status'] = '1' # "unread"
- if not props.has_key('title'):
+ if properties.has_key('title') and not props.has_key('title'):
props['title'] = title
props['messages'] = [message_id]
props['nosy'] = recipients[:]
props['nosy'].sort()
nodeid = cl.create(**props)
+def parseContent(content, blank_line=re.compile(r'[\r\n]+\s*[\r\n]+'),
+ eol=re.compile(r'[\r\n]+'), signature=re.compile(r'^[>|\s]*[-_]+\s*$')):
+ ''' The message body is divided into sections by blank lines.
+ Sections where the second and all subsequent lines begin with a ">" or "|"
+ character are considered "quoting sections". The first line of the first
+ non-quoting section becomes the summary of the message.
+ '''
+ sections = blank_line.split(content)
+ # extract out the summary from the message
+ summary = ''
+ l = []
+ for section in sections:
+ section = section.strip()
+ if not section:
+ continue
+ lines = eol.split(section)
+ if lines[0] and lines[0][0] in '>|':
+ continue
+ if len(lines) > 1 and lines[1] and lines[1][0] in '>|':
+ continue
+ if not summary:
+ summary = lines[0]
+ l.append(section)
+ continue
+ if signature.match(lines[0]):
+ break
+ l.append(section)
+ return summary, '\n'.join(l)
+
#
# $Log: not supported by cvs2svn $
+# 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.8 2001/08/05 07:06:07 richard
+# removed some print statements
+#
+# Revision 1.7 2001/08/03 07:18:22 richard
+# Implemented correct mail splitting (was taking a shortcut). Added unit
+# tests. Also snips signatures now too.
+#
+# Revision 1.6 2001/08/01 04:24:21 richard
+# mailgw was assuming certain properties existed on the issues being created.
+#
+# Revision 1.5 2001/07/29 07:01:39 richard
+# Added vim command to all source so that we don't get no steenkin' tabs :)
+#
# Revision 1.4 2001/07/28 06:43:02 richard
# Multipart message class has the getPart method now. Added some tests for it.
#