Code

When debugging mail (debug = <filename> setting in [mail] section of
[roundup.git] / roundup / mailgw.py
index 922dc12656a8d6dafc601aba82223b97fad1a32c..7a71d6a7017dc9e90705ec7b0c0335d600342696 100644 (file)
@@ -247,6 +247,22 @@ class Message(mimetools.Message):
             parts.append(part)
         return parts
 
+    def _decode_header_to_utf8(self, hdr):
+        l = []
+        prev_encoded = False
+        for part, encoding in decode_header(hdr):
+            if encoding:
+                part = part.decode(encoding)
+            # RFC 2047 specifies that between encoded parts spaces are
+            # swallowed while at the borders from encoded to non-encoded
+            # or vice-versa we must preserve a space. Multiple adjacent
+            # non-encoded parts should not occur.
+            if l and prev_encoded != bool(encoding):
+                l.append(' ')
+            prev_encoded = bool(encoding)
+            l.append(part)
+        return ''.join([s.encode('utf-8') for s in l])
+
     def getheader(self, name, default=None):
         hdr = mimetools.Message.getheader(self, name, default)
         # TODO are there any other False values possible?
@@ -257,24 +273,13 @@ class Message(mimetools.Message):
             return ''
         if hdr:
             hdr = hdr.replace('\n','') # Inserted by rfc822.readheaders
-        # 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])
+        return self._decode_header_to_utf8(hdr)
 
     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])
+            name = self._decode_header_to_utf8(name)
             l.append((name, addr))
         return l
 
@@ -549,6 +554,7 @@ class parsedMessage:
         self.nodeid = None
         self.author = None
         self.recipients = None
+        self.msg_props = {}
         self.props = None
         self.content = None
         self.attachments = None
@@ -1052,13 +1058,14 @@ encrypted.""")
                     'You are not permitted to add files to %(classname)s.'
                     ) % self.__dict__
 
+            self.msg_props['files'] = files
             if self.nodeid:
                 # extend the existing files list
                 fileprop = self.cl.get(self.nodeid, 'files')
                 fileprop.extend(files)
                 files = fileprop
 
-        self.props['files'] = files
+            self.props['files'] = files
 
     def create_msg(self):
         ''' Create msg containing all the relevant information from the message
@@ -1066,6 +1073,7 @@ encrypted.""")
         if not self.properties.has_key('messages'):
             return
         msg_props = self.mailgw.get_class_arguments('msg')
+        self.msg_props.update (msg_props)
         
         # Get the message ids
         inreplyto = self.message.getheader('in-reply-to') or ''
@@ -1093,8 +1101,8 @@ not find a text/plain part to use.
             try:
                 message_id = self.db.msg.create(author=self.author,
                     recipients=self.recipients, date=date.Date('.'),
-                    summary=summary, content=content, files=self.props['files'],
-                    messageid=messageid, inreplyto=inreplyto, **msg_props)
+                    summary=summary, content=content,
+                    messageid=messageid, inreplyto=inreplyto, **self.msg_props)
             except exceptions.Reject, error:
                 raise MailUsageError, _("""
 Mail message was rejected by a detector.
@@ -1658,7 +1666,17 @@ def uidFromAddress(db, address, create=1, **user_props):
     props = db.user.getprops()
     if props.has_key('alternate_addresses'):
         users = db.user.filter(None, {'alternate_addresses': address})
-        user = extractUserFromList(db.user, users)
+        # We want an exact match of the email, not just a substring
+        # match. Otherwise e.g. support@example.com would match
+        # discuss-support@example.com which is not what we want.
+        found_users = []
+        for u in users:
+            alt = db.user.get(u, 'alternate_addresses').split('\n')
+            for a in alt:
+                if a.strip().lower() == address.lower():
+                    found_users.append(u)
+                    break
+        user = extractUserFromList(db.user, found_users)
         if user is not None:
             return user
 
@@ -1688,7 +1706,7 @@ def uidFromAddress(db, address, create=1, **user_props):
         try:
             return db.user.create(username=trying, address=address,
                 realname=realname, roles=db.config.NEW_EMAIL_USER_ROLES,
-                password=password.Password(password.generatePassword()),
+                password=password.Password(password.generatePassword(), config=db.config),
                 **user_props)
         except exceptions.Reject:
             return 0