Пример #1
0
def notify_followers(obj, event):
    """Tell our followers when a comment has been added.

       This method composes and sends emails to all users that have added a
       comment to this conversation and requested to be notified of follow-ups.
    """
    request = getattr(obj, 'REQUEST', None)
    if not request:
        return
    if not ISlcUnderflow.providedBy(request):
        return

    # Get info necessary to send email
    mail_host = getToolByName(obj, 'MailHost')
    portal_url = getToolByName(obj, 'portal_url')
    portal = portal_url.getPortalObject()

    settings = getSettings()
    if settings is None or settings.sender is None:
        sender = portal.getProperty('email_from_address')
    else:
        sender = settings.sender

    # Check if a sender address is available
    if not sender:
        return

    # Compose and send emails to all users that have add a comment to this
    # conversation and enabled user_notification.
    conversation = aq_parent(obj)
    content_object = aq_parent(conversation)

    # Avoid sending multiple notification emails to the same person
    # when he has commented multiple times.
    emails = set()
    for comment in conversation.getComments():
        if (obj != comment and
            comment.user_notification and comment.author_email):
            emails.add(comment.author_email)

    if not emails:
        return

    subject = translate(u"A comment has been posted [${uid}#${id}]",
        mapping={'uid': IUUID(content_object), 'id': obj.id},
        context=obj.REQUEST)
    template = component.getMultiAdapter((obj, obj.REQUEST),
        name="mail_notification")
    message = template.render({
            'title': safe_unicode(content_object.title),
            'link': content_object.absolute_url() +
                    '/view#' + obj.id,
            'text': obj.text
    })
    for email in emails:
        # Send email
        try:
            mail_host.send(message, email, sender, subject, charset='utf-8')
        except SMTPException:
            logger.error('SMTP exception while trying to send an ' +
                         'email from %s to %s',
                         sender,
                         email)
Пример #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
Пример #3
0
def notify_nosy(obj, event):
    """ Give the nosy list access to the question. Then tell them about the new
        question. """
    request = getattr(obj, 'REQUEST', None)
    if not request:
        return
    if not ISlcUnderflow.providedBy(request):
        return

    # Get info necessary to send email
    mail_host = getToolByName(obj, 'MailHost')
    portal_url = getToolByName(obj, 'portal_url')
    membership = getToolByName(obj, 'portal_membership')

    portal = portal_url.getPortalObject()
    member = api.user.get_current()
    user_id = member.getId()
    username = member.getProperty('fullname')

    settings = getSettings()
    if settings is None or settings.sender is None:
        sender = portal.getProperty('email_from_address')
    else:
        sender = settings.sender

    # Check if a sender address is available
    if not sender:
        return

    # Add Reader role on any nosy principals, remove from non-selected ones.
    disown = []

    for principal, roles in obj.get_local_roles():
        if principal not in obj.nosy:
            disown.append(principal)

    for principal in obj.nosy:
        obj.manage_addLocalRoles(principal, ['Reader'])

    if disown:
        obj.manage_delLocalRoles(disown)

    emails = set()
    groups_tool = getToolByName(obj, 'portal_groups')
    members = get_nosy_members(obj, obj.nosy)
    for member in members:
        if member is not None:
            email = member.getProperty('email')
            if email != '' and email != user_id:
                emails.add(email)

    if not emails:
        return

    # Transform the text of the question
    transforms = getToolByName(obj, 'portal_transforms')
    text = obj.question.output
    if isinstance(text, unicode):
        text = text.encode('utf8')
    transform = transforms.convertTo('text/plain', text, context=obj,
        mimetype='text/html')
    if transform:
        text = transform.getData().strip()
    else:
        text = ''

    if isinstance(event, ObjectModifiedEvent):
        subject = translate(u"A question has been modified in ${container} [${uid}]",
            mapping={'uid': IUUID(obj),
                     'container': obj.aq_parent.Title()},
            context=obj.REQUEST)
    else:
        if obj.inforequest:
            subject = translate(u"Response required: StarDesk Message from ${username}",
                mapping={'username': username or user_id},
                context=obj.REQUEST)
        else:
            subject = translate(u"StarDesk Message from ${username} to ${container} members",
                mapping={'username': username or user_id,
                         'container': obj.aq_parent.Title()},
                context=obj.REQUEST)

    if obj.inforequest:
        template = component.getMultiAdapter((obj, obj.REQUEST),
                name="mail_notification_nosy_inforequest")
    else:
        template = component.getMultiAdapter((obj, obj.REQUEST),
                name="mail_notification_nosy")

    message = template.render({
        'username': username or user_id,
        'title': safe_unicode(obj.title),
        'link': obj.absolute_url(),
        'text': safe_unicode(text),
        'container': obj.aq_parent.Title()
    })
    # remove the current user from the notification, he doesn't need to receive it, he asked in the first place
    for email in emails:
        # Send email
        try:
            mail_host.send(message, email, sender, subject, charset='utf-8')
        except SMTPException:
            logger.error('SMTP exception while trying to send an ' +
                         'email from %s to %s',
                         sender,
                         email)