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
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