Code

- update with possible tracker issue
[roundup.git] / roundup / mailgw.py
index b3659b9a6b68dfe0b186957ec14e994e5c1b8269..fb7b6a2e3ee796065580c80a38e2e8cf8ea7f080 100644 (file)
@@ -79,7 +79,9 @@ __docformat__ = 'restructuredtext'
 
 import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
 import time, random, sys, logging
-import traceback, MimeWriter, rfc822
+import traceback, rfc822
+
+from email.Header import decode_header
 
 from roundup import configuration, hyperdb, date, password, rfc2822, exceptions
 from roundup.mailer import Mailer, MessageSendError
@@ -261,9 +263,30 @@ class Message(mimetools.Message):
 
     def getheader(self, name, default=None):
         hdr = mimetools.Message.getheader(self, name, default)
+        if not hdr:
+            return ''
         if hdr:
             hdr = hdr.replace('\n','') # Inserted by rfc822.readheaders
-        return rfc2822.decode_header(hdr)
+        # historically this method has returned utf-8 encoded string
+        l = []
+        for part, encoding in decode_header(hdr):
+            if encoding:
+                part = part.decode(encoding)
+            l.append(part)
+        return ''.join([s.encode('utf-8') for s in l])
+
+    def getaddrlist(self, name):
+        # overload to decode the name part of the address
+        l = []
+        for (name, addr) in mimetools.Message.getaddrlist(self, name):
+            p = []
+            for part, encoding in decode_header(name):
+                if encoding:
+                    part = part.decode(encoding)
+                p.append(part)
+            name = ''.join([s.encode('utf-8') for s in p])
+            l.append((name, addr))
+        return l
 
     def getname(self):
         """Find an appropriate name for this message."""
@@ -501,9 +524,8 @@ class Message(mimetools.Message):
 
 class MailGW:
 
-    def __init__(self, instance, db, arguments=()):
+    def __init__(self, instance, arguments=()):
         self.instance = instance
-        self.db = db
         self.arguments = arguments
         self.default_class = None
         for option, value in self.arguments:
@@ -779,6 +801,21 @@ class MailGW:
 
         Parse the message as per the module docstring.
         '''
+        # get database handle for handling one email
+        self.db = self.instance.open ('admin')
+        try:
+            return self._handle_message (message)
+        finally:
+            self.db.close()
+
+    def _handle_message(self, message):
+        ''' message - a Message instance
+
+        Parse the message as per the module docstring.
+
+        The implementation expects an opened database and a try/finally
+        that closes the database.
+        '''
         # detect loops
         if message.getheader('x-roundup-loop', ''):
             raise IgnoreLoop
@@ -1093,7 +1130,7 @@ The mail gateway is not properly set up. Please contact
         # Don't create users if anonymous isn't allowed to register
         create = 1
         anonid = self.db.user.lookup('anonymous')
-        if not (self.db.security.hasPermission('Create', anonid, 'user')
+        if not (self.db.security.hasPermission('Register', anonid, 'user')
                 and self.db.security.hasPermission('Email Access', anonid)):
             create = 0
 
@@ -1113,7 +1150,7 @@ The mail gateway is not properly set up. Please contact
                 from_address = from_list[0][1]
                 registration_info = ""
                 if self.db.security.hasPermission('Web Access', author) and \
-                   self.db.security.hasPermission('Create', anonid, 'user'):
+                   self.db.security.hasPermission('Register', anonid, 'user'):
                     tracker_web = self.instance.config.TRACKER_WEB
                     registration_info = """ Please register at:
 
@@ -1259,8 +1296,8 @@ not find a text/plain part to use.
         #
         # handle the attachments
         #
-        if properties.has_key('files'):
-            files = []
+        files = []
+        if attachments and properties.has_key('files'):
             for (name, mime_type, data) in attachments:
                 if not self.db.security.hasPermission('Create', author, 'file'):
                     raise Unauthorized, _(
@@ -1274,8 +1311,8 @@ not find a text/plain part to use.
                     pass
                 else:
                     files.append(fileid)
-            # attach the files to the issue
-            if not self.db.security.hasPermission('Edit', author,
+            # allowed to attach the files to an existing node?
+            if nodeid and not self.db.security.hasPermission('Edit', author,
                     classname, 'files'):
                 raise Unauthorized, _(
                     'You are not permitted to add files to %(classname)s.'
@@ -1308,8 +1345,8 @@ not find a text/plain part to use.
 Mail message was rejected by a detector.
 %(error)s
 """) % locals()
-            # attach the message to the node
-            if not self.db.security.hasPermission('Edit', author,
+            # allowed to attach the message to the existing node?
+            if nodeid and not self.db.security.hasPermission('Edit', author,
                     classname, 'messages'):
                 raise Unauthorized, _(
                     'You are not permitted to add messages to %(classname)s.'
@@ -1335,16 +1372,21 @@ Mail message was rejected by a detector.
                 if not props.has_key(prop) :
                     props[prop] = issue_props[prop]
 
-            # Check permissions for each property
-            for prop in props.keys():
-                if not self.db.security.hasPermission('Edit', author,
-                        classname, prop):
-                    raise Unauthorized, _('You are not permitted to edit '
-                        'property %(prop)s of class %(classname)s.') % locals()
-
             if nodeid:
+                # Check permissions for each property
+                for prop in props.keys():
+                    if not self.db.security.hasPermission('Edit', author,
+                            classname, prop):
+                        raise Unauthorized, _('You are not permitted to edit '
+                            'property %(prop)s of class %(classname)s.') % locals()
                 cl.set(nodeid, **props)
             else:
+                # Check permissions for each property
+                for prop in props.keys():
+                    if not self.db.security.hasPermission('Create', author,
+                            classname, prop):
+                        raise Unauthorized, _('You are not permitted to set '
+                            'property %(prop)s of class %(classname)s.') % locals()
                 nodeid = cl.create(**props)
         except (TypeError, IndexError, ValueError, exceptions.Reject), message:
             raise MailUsageError, _("""