Example #1
0
def pester_answerer(event):
    # Place an annotation on the member that will cause sticky-status messages
    # to display a notice

    # Stubbing out this method for a demo
    return

    request = getattr(event.object, 'REQUEST', None)
    if not request:
        return
    if not ISlcUnderflow.providedBy(request):
        return

    try:
        pm = getToolByName(event.object, 'portal_membership')
    except AttributeError:
        # seldom case of zope user in event.object that cannot acquire portal tools
        return
    pc = getToolByName(event.object, 'portal_catalog')
    userid = event.object.getUserId()
    member = pm.getMemberById(userid)

    # Find questions we need to answer
    brains = pc(portal_type='slc.underflow.question', inforequest=True)

    for brain in brains:
        if userid not in brain.commentators:
            # XXX This code really belongs in some utililty inside
            # slc.stickystatusmessages
            timestamp = datetime.now().isoformat()
            annotations = IAnnotations(member)
            sticky_messages = annotations.get(SSMKEY, {})

            mapping = { 'u': brain.getURL() }
            msg = _(u'An information request is waiting for your response. '
                u'Click <a href="${u}">here</a> to respond to it now.')
            msg = interpolate(msg, mapping)

            mdict= {
                'type': 'info',
                'message': msg,
                'timestamp': timestamp,
                }
            sticky_messages[timestamp] = mdict
            annotations[SSMKEY] = sticky_messages
Example #2
0
    def __call__(self, site, msg):
        recipient = email.Utils.parseaddr(msg.get('To'))[1]

        settings = getSettings()
        if settings is None or settings.sender is None:
            # Cannot handle email unless we have a dedicated address for it
            return False 

        if recipient.lower() != settings.sender.strip().lower():
            # It is not addressed to us
            return False

        sender = msg.get('From')
        sender = email.Utils.parseaddr(sender)[1].lower()

        # Drop privileges to the right user
        acl_users = getToolByName(site, 'acl_users')
        pm = getToolByName(site, 'portal_membership')
        props = getToolByName(site, 'portal_properties').site_properties
        user = None
        if props.getProperty('use_email_as_login'):
            # If email logins are used, the user's email might be his id
            user = pm.getMemberById(sender)
            if user is not None:
                if user.getProperty('email') == sender:
                    user = user.getUser()
                else:
                    user = None

        if user is None:
            potential = pm.searchMembers('email', sender)
            # Email might match more than one user, check for exact match
            for u in potential:
                if sender == u['email']:
                    user = pm.getMemberById(u['username']).getUser()
                    break

        if user is None:
            raise NotFoundError(_("Sender is not a valid user"))

        newSecurityManager(None, user.__of__(acl_users))

        # Find relevant comment
        subject = msg.get('subject', '').strip()
        if not subject:
            raise NotFoundError(_("Subject is blank"))

        subject = decodeheader(subject)
        pat = re.compile('[^[]*\[([^#]+)(#([^\]]+))?\]')
        m = pat.match(subject)
        if m is None:
            raise NotFoundError(_("Unable to match a question"))
        
        questionid = m.groups()[0]
        commentid = m.groups()[2] # Might be None

        question = uuidToObject(questionid)
        if question is None:
            raise NotFoundError(_("Unable to match a question"))

        can_reply = getSecurityManager().checkPermission(
            'Reply to item', question)

        if not can_reply:
            raise PermissionError(_("Insufficient privileges"))

        comment = createObject('plone.Comment')

        member = pm.getAuthenticatedMember()
        address = member.getProperty('email')
        fullname = member.getProperty('fullname')
        if not fullname or fullname == '':
            fullname = member.getUserName()
        elif isinstance(fullname, str):
            fullname = unicode(fullname, 'utf-8')

        if address and isinstance(address, str):
            address = unicode(address, 'utf-8')

        comment.creator = member.getUserName()
        comment.author_username = comment.creator
        comment.author_name = fullname
        comment.author_email = address
        comment.creation_date = datetime.utcnow()
        comment.modification_date = comment.creation_date

        # Walk the message and get the inline component
        for part in msg.walk():
            if part.is_multipart():
                # Ignore multipart envelope if it exists
                continue
            if part.get_filename() is not None:
                # Ignore attachments
                continue

            content_type = part.get_content_type()

            if content_type not in ('text/plain', 'text/html'):
                # Skip non text/html parts
                continue

            payload = part.get_payload(decode=1)
            if content_type == 'text/html':
                transforms = getToolByName(site, 'portal_transforms')
                transform = transforms.convertTo('text/plain',
                    payload, context=site, mimetype='text/html')
                if transform:
                    payload = transform.getData().strip()
                else:
                    raise PermanentError(_(u"Could not convert html email"))

            comment.text = payload.strip()
            break # Get out of the for loop

        # Add comment to conversation
        conversation = IConversation(question)
        if commentid is not None:
            # Add a reply to an existing comment
            conversation_to_reply_to = conversation.get(commentid)
            replies = IReplies(conversation_to_reply_to)
            comment_id = replies.addComment(comment)
        else:
            # Add a comment to the conversation
            comment_id = conversation.addComment(comment)

        return True