diff --git a/roundup/mailgw.py b/roundup/mailgw.py
index fb7b6a2e3ee796065580c80a38e2e8cf8ea7f080..8346b0590cb605ab7a0ac6d4dcba5f1557273f0a 100644 (file)
--- a/roundup/mailgw.py
+++ b/roundup/mailgw.py
and given "file" class nodes that are linked to the "msg" node.
. In a multipart/alternative message or part, we look for a text/plain
subpart and ignore the other parts.
+ . A message/rfc822 is treated similar tomultipart/mixed (except for
+ special handling of the first text part) if unpack_rfc822 is set in
+ the mailgw config section.
Summary
-------
from roundup import configuration, hyperdb, date, password, rfc2822, exceptions
from roundup.mailer import Mailer, MessageSendError
from roundup.i18n import _
+from roundup.hyperdb import iter_roles
try:
import pyme, pyme.core, pyme.gpgme
yield sig
sig = sig.next
-
-def iter_roles(roles):
- ''' handle the text processing of turning the roles list
- into something python can use more easily
- '''
- for role in [x.lower().strip() for x in roles.split(',')]:
- yield role
-
-def user_has_role(db, userid, role_list):
- ''' see if the given user has any roles that appear
- in the role_list
- '''
- for role in iter_roles(db.user.get(userid, 'roles')):
- if role in iter_roles(role_list):
- return True
- return False
-
-
def check_pgp_sigs(sig, gpgctx, author):
''' Theoretically a PGP message can have several signatures. GPGME
returns status on all signatures in a linked list. Walk that
def getheader(self, name, default=None):
hdr = mimetools.Message.getheader(self, name, default)
+ # TODO are there any other False values possible?
+ # TODO if not hdr: return hdr
+ if hdr is None:
+ return None
if not hdr:
return ''
if hdr:
def getname(self):
"""Find an appropriate name for this message."""
+ name = None
if self.gettype() == 'message/rfc822':
# handle message/rfc822 specially - the name should be
# the subject of the actual e-mail embedded here
+ # we add a '.eml' extension like other email software does it
self.fp.seek(0)
- name = Message(self.fp).getheader('subject')
- else:
+ s = cStringIO.StringIO(self.getbody())
+ name = Message(s).getheader('subject')
+ if name:
+ name = name + '.eml'
+ if not name:
# try name on Content-Type
name = self.getparam('name')
if not name:
# flagging.
# multipart/form-data:
# For web forms only.
+ # message/rfc822:
+ # Only if configured in [mailgw] unpack_rfc822
- def extract_content(self, parent_type=None, ignore_alternatives = False):
+ def extract_content(self, parent_type=None, ignore_alternatives=False,
+ unpack_rfc822=False):
"""Extract the body and the attachments recursively.
If the content is hidden inside a multipart/alternative part,
ig = ignore_alternatives and not content_found
for part in self.getparts():
new_content, new_attach = part.extract_content(content_type,
- not content and ig)
+ not content and ig, unpack_rfc822)
# If we haven't found a text/plain part yet, take this one,
# otherwise make it an attachment.
attachments.extend(new_attach)
if ig and content_type == 'multipart/alternative' and content:
attachments = []
+ elif unpack_rfc822 and content_type == 'message/rfc822':
+ s = cStringIO.StringIO(self.getbody())
+ m = Message(s)
+ ig = ignore_alternatives and not content
+ new_content, attachments = m.extract_content(m.gettype(), ig,
+ unpack_rfc822)
+ attachments.insert(0, m.text_as_attachment())
elif (parent_type == 'multipart/signed' and
content_type == 'application/pgp-signature'):
# ignore it so it won't be saved as an attachment
self.default_class = value.strip()
self.mailer = Mailer(instance.config)
- self.logger = logging.getLogger('mailgw')
+ self.logger = logging.getLogger('roundup.mailgw')
# should we trap exceptions (normal usage) or pass them through
# (for testing)
fcntl.flock(f.fileno(), FCNTL.LOCK_UN)
return 0
- def do_imap(self, server, user='', password='', mailbox='', ssl=0):
+ def do_imap(self, server, user='', password='', mailbox='', ssl=0,
+ cram=0):
''' Do an IMAP connection
'''
import getpass, imaplib, socket
return 1
try:
- server.login(user, password)
+ if cram:
+ server.login_cram_md5(user, password)
+ else:
+ server.login(user, password)
except imaplib.IMAP4.error, e:
self.logger.exception('IMAP login failure')
return 1
# if we've not found a valid classname prefix then force the
# scanning to handle there being a leading delimiter
- title_re = r'(?P<title>%s[^%s]+)'%(
+ title_re = r'(?P<title>%s[^%s]*)'%(
not matches['classname'] and '.' or '', delim_open)
m = re.match(title_re, tmpsubject.strip(), re.IGNORECASE)
if m:
if (title and properties.has_key('title') and not
issue_props.has_key('title')):
issue_props['title'] = title
+ if (nodeid and properties.has_key('title') and not
+ config['MAILGW_SUBJECT_UPDATES_TITLE']):
+ issue_props['title'] = cl.get(nodeid,'title')
#
# handle message-id and in-reply-to
# or we will skip PGP processing
def pgp_role():
if self.instance.config.PGP_ROLES:
- return user_has_role(self.db, author,
- self.instance.config.PGP_ROLES)
+ return self.db.user.has_role(author,
+ iter_roles(self.instance.config.PGP_ROLES))
else:
return True
encrypted.""")
# now handle the body - find the message
ig = self.instance.config.MAILGW_IGNORE_ALTERNATIVES
- content, attachments = message.extract_content(ignore_alternatives = ig)
+ content, attachments = message.extract_content(ignore_alternatives=ig,
+ unpack_rfc822=self.instance.config.MAILGW_UNPACK_RFC822)
if content is None:
raise MailUsageError, _("""
Roundup requires the submission to be plain text. The message parser could