def request_password_reset(user, profile, request):
    profile.password_reset_key = sha1(
        str(random.random())).hexdigest()
    profile.password_reset_time = datetime.datetime.now()
    context = find_site(profile)
    reset_url = resource_url(
        context, request, "reset_confirm.html",
        query=dict(key=profile.password_reset_key))

    # send email
    mail = Message()
    system_name = get_setting(context, 'system_name', 'KARL')
    admin_email = get_setting(context, 'admin_email')
    mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
    mail["To"] = "%s <%s>" % (profile.title, profile.email)
    mail["Subject"] = "%s Password Reset Request" % system_name
    body = render(
        "templates/email_reset_password.pt",
        dict(login=user['login'],
             reset_url=reset_url,
             system_name=system_name),
        request=request,
    )

    if isinstance(body, unicode):
        body = body.encode("UTF-8")

    mail.set_payload(body, "UTF-8")
    mail.set_type("text/html")

    recipients = [profile.email]
    mailer = getUtility(IMailDelivery)
    mailer.send(recipients, mail)
Exemple #2
0
    def bounce_message_throttled(self, message):
        mailer = getUtility(IMailDelivery)
        from_email = get_setting(self.root, 'postoffice.bounce_from_email')
        if from_email is None:
            from_email = get_setting(self.root, 'admin_email')

        bounce_message = Message()
        bounce_message['From'] = from_email
        bounce_message['To'] = message['From']
        bounce_message['Subject'] = 'Your submission to Karl has bounced.'
        bounce_message.set_type('text/html')
        bounce_message.set_payload(
            render(
                'templates/bounce_email_throttled.pt',
                dict(
                    subject=message.get('Subject'),
                    system_name=get_setting(self.root, 'system_name', 'KARL'),
                    admin_email=get_setting(self.root, 'admin_email'),
                ),
            ).encode('UTF-8'), 'UTF-8')

        self.queue.bounce(message,
                          wrap_send(mailer.bounce),
                          from_email,
                          bounce_message=bounce_message)
Exemple #3
0
def request_password_reset(user, profile, request):
    profile.password_reset_key = sha1(str(random.random())).hexdigest()
    profile.password_reset_time = datetime.datetime.now()
    context = find_site(profile)
    reset_url = resource_url(context,
                             request,
                             "reset_confirm.html",
                             query=dict(key=profile.password_reset_key))

    # send email
    mail = Message()
    system_name = get_setting(context, 'system_name', 'KARL')
    admin_email = get_setting(context, 'admin_email')
    mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
    mail["To"] = "%s <%s>" % (profile.title, profile.email)
    mail["Subject"] = "%s Password Reset Request" % system_name
    body = render(
        "templates/email_reset_password.pt",
        dict(login=user['login'], reset_url=reset_url,
             system_name=system_name),
        request=request,
    )

    if isinstance(body, unicode):
        body = body.encode("UTF-8")

    mail.set_payload(body, "UTF-8")
    mail.set_type("text/html")

    recipients = [profile.email]
    mailer = getUtility(IMailDelivery)
    mailer.send(recipients, mail)
Exemple #4
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, "Admin UI: Send Email")
        admin_email = get_setting(context, "admin_email")
        system_name = get_setting(context, "system_name")
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ("self", "%s <%s>" % (admin.title, admin.email)),
            ("admin", "%s Administrator <%s>" % (system_name, admin_email)),
        ]

        if "send_email" in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params["to_group"]
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, "security_state", None) == "inactive":
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params["from_email"] == "self":
                    message["From"] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message["From"] = from_emails[1][1]
                    message_from = admin_email
                message["To"] = "%s <%s>" % (profile.title, profile.email)
                message["Subject"] = request.params["subject"]
                body = u"<html><body>%s</body></html>" % (request.params["text"])
                message.set_payload(body.encode("UTF-8"), "UTF-8")
                message.set_type("text/html")

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = model_url(context, request, "admin.html", query=dict(status_message=status_message))
            else:
                redirect_to = model_url(
                    find_communities(context),
                    request,
                    "all_communities.html",
                    query=dict(status_message=status_message),
                )

            return HTTPFound(location=redirect_to)

        return dict(api=api, menu=_menu_macro(), to_groups=self.to_groups, from_emails=from_emails)
Exemple #5
0
def login_user(request, profile, login, userid):
    site = request.root
    admin_only = asbool(request.registry.settings.get('admin_only', ''))
    admins = aslist(request.registry.settings.get('admin_userids', ''))
    if admin_only and userid not in admins:
        return site_down_view(site, request)

    settings = request.registry.settings
    device_cookie_name = settings.get('device_cookie', 'CxR61DzG3P0Ae1')
    max_age = settings.get('login_cookie_max_age', '36000')
    max_age = int(max_age)

    response = remember_login(site, request, userid, max_age)
    # have we logged in from this computer & browser before?
    active_device = request.cookies.get(device_cookie_name, None)
    if active_device is None and profile is not None:
        # if not, send email
        reset_url = request.resource_url(profile, 'change_password.html')
        mail = Message()
        system_name = settings.get('system_name', 'KARL')
        admin_email = settings.get('admin_email')
        mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
        mail["To"] = "%s <%s>" % (profile.title, profile.email)
        mail["Subject"] = "New %s Login Notification" % system_name
        user_agent = user_agents.parse(request.user_agent)
        body = render(
            "templates/email_suspicious_login.pt",
            dict(login=login, reset_url=reset_url, device_info=user_agent),
            request=request,
        )
        if isinstance(body, unicode):
            body = body.encode("UTF-8")
        mail.set_payload(body, "UTF-8")
        mail.set_type("text/html")
        recipients = [profile.email]
        mailer = getUtility(IMailDelivery)
        mailer.send(recipients, mail)

        # set cookie to avoid further notifications for this device
        active_device = ''.join(
            random.choice(string.ascii_uppercase + string.digits)
            for _ in range(16))
        response.set_cookie(device_cookie_name,
                            active_device,
                            max_age=315360000)

    if profile is not None:
        profile.active_device = active_device
    request.session['logout_reason'] = None
    return response
Exemple #6
0
def send_reminders(env, start, end):
    print
    print "Sending reminders for passwords expiring between %s and %s" % (
        start.strftime('%Y-%m-%d %H:%M'), end.strftime('%Y-%m-%d %H:%M'))
    print
    root = env['root']
    registry = env['registry']
    request = env['request']

    system_name = get_setting(root, 'system_name', 'KARL')
    admin_email = get_setting(root, 'admin_email')
    site_url = get_setting(root, 'script_app_url')
    reset_url = "%s/reset_request.html" % site_url

    profiles = find_profiles(root)
    for profile in profiles.values():
        auth_method = profile.auth_method.lower()
        if auth_method != 'password':
            continue

        expiration = profile.password_expiration_date
        if expiration > start and expiration < end:
            mail = Message()
            mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
            mail["To"] = "%s <%s>" % (profile.title, profile.email)
            mail["Subject"] = "%s Password Expiration Reminder" % system_name
            body = render(
                "templates/password_expiration_reminder.pt",
                dict(login=profile.__name__,
                     reset_url=reset_url,
                     expiration_date=start.strftime('%Y-%m-%d'),
                     system_name=system_name),
                request=request,
            )

            if isinstance(body, unicode):
                body = body.encode("UTF-8")

            mail.set_payload(body, "UTF-8")
            mail.set_type("text/html")

            recipients = [profile.email]
            mailer = getUtility(IMailDelivery)
            mailer.send(recipients, mail)
            print "Sent reminder to user '%s'" % profile.title.encode("UTF-8")

    print
def send_reminders(env, start, end):
    print
    print "Sending reminders for passwords expiring between %s and %s" % (
        start.strftime('%Y-%m-%d %H:%M'), end.strftime('%Y-%m-%d %H:%M'))
    print
    root = env['root']
    registry = env['registry']
    request = env['request']

    system_name = get_setting(root, 'system_name', 'KARL')
    admin_email = get_setting(root, 'admin_email')
    site_url = get_setting(root, 'script_app_url')
    reset_url = "%s/reset_request.html" % site_url

    profiles = find_profiles(root)
    for profile in profiles.values():
        expiration = profile.password_expiration_date
        if expiration > start and expiration < end:
            mail = Message()
            mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
            mail["To"] = "%s <%s>" % (profile.title, profile.email)
            mail["Subject"] = "%s Password Expiration Reminder" % system_name
            body = render(
                "templates/password_expiration_reminder.pt",
                dict(login=profile.__name__,
                    reset_url=reset_url,
                    expiration_date=start.strftime('%Y-%m-%d'),
                    system_name=system_name),
                    request=request,
            )

            if isinstance(body, unicode):
                body = body.encode("UTF-8")

            mail.set_payload(body, "UTF-8")
            mail.set_type("text/html")

            recipients = [profile.email]
            mailer = getUtility(IMailDelivery)
            mailer.send(recipients, mail)
            print "Sent reminder to user '%s'" % profile.title

    print
Exemple #8
0
    def bounce_message_throttled(self, message):
        mailer = getUtility(IMailDelivery)
        from_email = get_setting(self.root, 'postoffice.bounce_from_email')
        if from_email is None:
            from_email = get_setting(self.root, 'admin_email')

        bounce_message = Message()
        bounce_message['From'] = from_email
        bounce_message['To'] = message['From']
        bounce_message['Subject'] = 'Your submission to Karl has bounced.'
        bounce_message.set_type('text/html')
        bounce_message.set_payload(render_template(
            'templates/bounce_email_throttled.pt',
            subject=message.get('Subject'),
            system_name=get_setting(self.root, 'system_name', 'KARL'),
            admin_email=get_setting(self.root, 'admin_email'),
        ).encode('UTF-8'), 'UTF-8')

        self.queue.bounce(
            message, wrap_send(mailer.send), from_email,
            bounce_message=bounce_message
        )
Exemple #9
0
def join_community_view(context, request):
    """ User sends an email to community moderator(s) asking to join
    the community.  Email contains a link to "add_existing" view, in members,
    that a moderator can use to add member to the community.

    """
    assert ICommunity.providedBy(context)

    # Get logged in user
    profiles = find_profiles(context)
    user = authenticated_userid(request)
    profile = profiles[user]

    # Handle form submission
    if "form.submitted" in request.POST:
        message = request.POST.get("message", "")
        moderators = [profiles[id] for id in context.moderator_names]
        mail = Message()
        mail["From"] = "%s <%s>" % (profile.title, profile.email)
        mail["To"] = ",".join(
            ["%s <%s>" % (p.title, p.email) for p in moderators])
        mail["Subject"] = "Request to join %s community" % context.title

        body_template = get_renderer(
            "templates/email_join_community.pt").implementation()
        profile_url = resource_url(profile, request)
        accept_url = resource_url(context,
                                  request,
                                  "members",
                                  "add_existing.html",
                                  query={"user_id": user})
        body = body_template(message=message,
                             community_title=context.title,
                             person_name=profile.title,
                             profile_url=profile_url,
                             accept_url=accept_url)

        if isinstance(body, unicode):
            body = body.encode("UTF-8")

        mail.set_payload(body, "UTF-8")
        mail.set_type("text/html")

        recipients = [p.email for p in moderators]
        mailer = getUtility(IMailDelivery)
        mailer.send(recipients, mail)

        status_message = "Your request has been sent to the moderators."
        location = resource_url(context,
                                request,
                                query={"status_message": status_message})

        return HTTPFound(location=location)

    # Show form
    page_title = "Join " + context.title
    api = TemplateAPI(context, request, page_title)
    return dict(api=api,
                profile=profile,
                community=context,
                post_url=resource_url(context, request, "join.html"),
                formfields=api.formfields)
Exemple #10
0
def join_community_view(context, request):
    """ User sends an email to community moderator(s) asking to join
    the community.  Email contains a link to "add_existing" view, in members,
    that a moderator can use to add member to the community.

    """
    assert ICommunity.providedBy(context)

    # Get logged in user
    profiles = find_profiles(context)
    user = authenticated_userid(request)
    profile = profiles[user]

    # Handle form submission
    if "form.submitted" in request.POST:
        message = request.POST.get("message", "")
        moderators = [profiles[id] for id in context.moderator_names]
        mail = Message()
        mail["From"] = "%s <%s>" % (profile.title, profile.email)
        mail["To"] = ",".join(
            ["%s <%s>" % (p.title, p.email) for p in moderators]
        )
        mail["Subject"] = "Request to join %s community" % context.title

        body_template = get_renderer(
            "templates/email_join_community.pt").implementation()
        profile_url = resource_url(profile, request)
        accept_url=resource_url(context, request, "members", "add_existing.html",
                             query={"user_id": user})
        body = body_template(
            message=message,
            community_title=context.title,
            person_name=profile.title,
            profile_url=profile_url,
            accept_url=accept_url
        )

        if isinstance(body, unicode):
            body = body.encode("UTF-8")

        mail.set_payload(body, "UTF-8")
        mail.set_type("text/html")

        recipients = [p.email for p in moderators]
        mailer = getUtility(IMailDelivery)
        mailer.send(recipients, mail)

        status_message = "Your request has been sent to the moderators."
        location = resource_url(context, request,
                             query={"status_message": status_message})

        return HTTPFound(location=location)

    # Show form
    page_title = "Join " + context.title
    api = TemplateAPI(context, request, page_title)
    return dict(api=api,
             profile=profile,
             community=context,
             post_url=resource_url(context, request, "join.html"),
             formfields=api.formfields)
Exemple #11
0
    def __call__(self):
        context, request = self.context, self.request
        request.layout_manager.use_layout('admin')
        api = AdminTemplateAPI(context, request, 'Admin UI: Send Email')
        admin_email = get_setting(context, 'admin_email')
        system_name = get_setting(context, 'system_name')
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ('self', '%s <%s>' % (admin.title, admin.email)),
            ('admin', '%s Administrator <%s>' % (system_name, admin_email)),
        ]

        if 'send_email' in request.params or 'submit' in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params['to_group']
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, 'security_state', None) == 'inactive':
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params['from_email'] == 'self':
                    message['From'] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message['From'] = from_emails[1][1]
                    message_from = admin_email
                message['To'] = '%s <%s>' % (profile.title, profile.email)
                message['Subject'] = request.params['subject']
                body = u'<html><body>%s</body></html>' % (
                    request.params['text']
                )
                message.set_payload(body.encode('UTF-8'), 'UTF-8')
                message.set_type('text/html')

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = resource_url(
                    context, request, 'admin.html',
                    query=dict(status_message=status_message))
            else:
                redirect_to = resource_url(
                    find_communities(context), request, 'all_communities.html',
                    query=dict(status_message=status_message))

            return HTTPFound(location=redirect_to)

        return dict(
            api=api,
            menu=_menu_macro(),
            to_groups = self.to_groups,
            from_emails=from_emails,
        )
Exemple #12
0
def login_view(context, request):
    settings = request.registry.settings
    came_from = request.session.get('came_from', request.url)
    if 'login.html' in came_from or 'logout.html' in came_from:
        came_from = request.application_url
    request.session['came_from'] = came_from

    submitted = request.params.get('form.submitted', None)
    if submitted:
        # identify
        login = request.POST.get('login')
        password = request.POST.get('password')
        if login is None or password is None:
            return HTTPFound(location='%s/login.html' %
                             request.application_url)

        max_retries = request.registry.settings.get('max_login_retries', 8)
        left = context.login_tries.get(login, max_retries)
        left = left - 1

        users = find_users(context)
        user = users.get_by_login(login)
        profiles = find_profiles(context)
        profile = profiles.get(user['id']) if user else None

        # max tries almost reached, send email warning
        if left == 2 and profile is not None:
            reset_url = request.resource_url(profile, 'change_password.html')
            mail = Message()
            system_name = settings.get('system_name', 'KARL')
            admin_email = settings.get('admin_email')
            mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
            mail["To"] = "%s <%s>" % (profile.title, profile.email)
            mail["Subject"] = "Too many failed logins to %s" % system_name
            body = render(
                "templates/email_locked_warning.pt",
                dict(login=login, reset_url=reset_url,
                     system_name=system_name),
                request=request,
            )
            if isinstance(body, unicode):
                body = body.encode("UTF-8")
            mail.set_payload(body, "UTF-8")
            mail.set_type("text/html")
            recipients = [profile.email]
            mailer = getUtility(IMailDelivery)
            mailer.send(recipients, mail)

        # if max tries reached, send password reset and lock
        if left < 1:
            log_failed_login(request, login)
            # only send email the first time
            if profile is not None and left == 0:
                context.login_tries[login] = -1
                request_password_reset(user, profile, request)
            page_title = 'Access to %s is locked' % settings.get(
                'system_name', 'KARL')
            api = TemplateAPI(context, request, page_title)
            response = render_to_response('templates/locked.pt',
                                          dict(
                                              api=api,
                                              app_url=request.application_url),
                                          request=request)
            return response

        # authenticate
        reason = 'Bad username or password.'
        try:
            userid = _authenticate(context, login, password)
        except TypeError:
            userid = None

        # if not successful, try again
        if not userid:
            log_failed_login(request, login)
            reason = "%s You have %d attempts left." % (reason, left)
            context.login_tries[login] = left
            redirect = request.resource_url(request.root,
                                            'login.html',
                                            query={'reason': reason})
            return HTTPFound(location=redirect)

        # all ok, remember
        context.login_tries[login] = max_retries
        return login_user(request, profile, login, userid)

    page_title = 'Login to %s' % settings.get(
        'system_name', 'KARL')  # Per #366377, don't say what screen
    api = TemplateAPI(context, request, page_title)
    status_message = request.params.get('reason', None)
    if status_message != '@@@one-session-only@@@':
        api.status_message = status_message
        status_message = None
    response = render_to_response('templates/login.pt',
                                  dict(api=api,
                                       status_message=status_message,
                                       app_url=request.application_url),
                                  request=request)
    forget_headers = forget(request)
    response.headers.extend(forget_headers)
    return response
Exemple #13
0
def login_view(context, request):
    settings = request.registry.settings
    came_from = request.session.get('came_from', request.url)
    came_from = _fixup_came_from(request, came_from)
    request.session['came_from'] = came_from

    submitted = request.params.get('form.submitted', None)
    if submitted:
        # identify
        login = request.POST.get('login')
        password = request.POST.get('password')
        if login is None or password is None:
            return HTTPFound(location='%s/login.html'
                                        % request.application_url)
        max_age = request.registry.settings.get('login_cookie_max_age', '36000')
        max_age = int(max_age)

        max_retries = request.registry.settings.get('max_login_retries', 8)
        left = context.login_tries.get(login, max_retries)
        left = left - 1

        profiles = find_profiles(context)
        profile = profiles.get(login)
        # max tries almost reached, send email warning
        if left == 2 and profile is not None:
            reset_url = request.resource_url(profile, 'change_password.html')
            mail = Message()
            system_name = settings.get('system_name', 'KARL')
            admin_email = settings.get('admin_email')
            mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
            mail["To"] = "%s <%s>" % (profile.title, profile.email)
            mail["Subject"] = "Too many failed logins to %s" % system_name
            body = render(
                "templates/email_locked_warning.pt",
                dict(login=login,
                     reset_url=reset_url,
                     system_name=system_name),
                request=request,
            )
            if isinstance(body, unicode):
                body = body.encode("UTF-8")
            mail.set_payload(body, "UTF-8")
            mail.set_type("text/html")
            recipients = [profile.email]
            mailer = getUtility(IMailDelivery)
            mailer.send(recipients, mail)

        # if max tries reached, send password reset and lock
        if left < 1:
            # only send email the first time
            if profile is not None and left == 0:
                context.login_tries[login] = -1
                users = find_users(context)
                user = users.get_by_id(login)
                request_password_reset(user, profile, request)
            page_title = 'Access to %s is locked' % settings.get('system_name', 'KARL')
            api = TemplateAPI(context, request, page_title)
            response = render_to_response(
                'templates/locked.pt',
                dict(
                    api=api,
                    app_url=request.application_url),
                request=request)
            return response

        # authenticate
        reason = 'Bad username or password.'
        userid = _authenticate(context, login, password)

        # if not successful, try again
        if not userid:
            reason = "%s You have %d attempts left." % (reason, left)
            context.login_tries[login] = left
            redirect = request.resource_url(
                request.root, 'login.html', query={'reason': reason})
            return HTTPFound(location=redirect)

        device_cookie_name = request.registry.settings.get('device_cookie',
                                                           'CxR61DzG3P0Ae1')

        # all ok, remember
        admin_only = asbool(request.registry.settings.get('admin_only', ''))
        admins = aslist(request.registry.settings.get('admin_userids', ''))
        if not admin_only or userid in admins:
            context.login_tries[login] = max_retries
            response = remember_login(context, request, userid, max_age)
            # have we logged in from this computer & browser before?
            active_device = request.cookies.get(device_cookie_name, None)
            if active_device is None:
                # if not, send email
                reset_url = request.resource_url(profile, 'change_password.html')
                mail = Message()
                system_name = settings.get('system_name', 'KARL')
                admin_email = settings.get('admin_email')
                mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
                mail["To"] = "%s <%s>" % (profile.title, profile.email)
                mail["Subject"] = "New %s Login Notification" % system_name
                # TODO Carlos needs to come back and get this working
                # https://bugs.launchpad.net/karl4/+bug/1648569/comments/10
                # user_agent = user_agents.parse(request.user_agent)
                body = render(
                    "templates/email_suspicious_login.pt",
                    dict(login=login,
                         reset_url=reset_url,
                         device_info=request.user_agent),
                    request=request,
                )
                if isinstance(body, unicode):
                    body = body.encode("UTF-8")
                mail.set_payload(body, "UTF-8")
                mail.set_type("text/html")
                recipients = [profile.email]
                mailer = getUtility(IMailDelivery)
                mailer.send(recipients, mail)

                # set cookie to avoid further notifications for this device
                active_device = ''.join(random.choice(string.ascii_uppercase +
                    string.digits) for _ in range(16))
                response.set_cookie(device_cookie_name, active_device,
                    max_age=315360000)

            profile.active_device = active_device
            request.session['logout_reason'] = None
            return response

        else:
            return site_down_view(context, request)

    page_title = 'Login to %s' % settings.get('system_name', 'KARL') # Per #366377, don't say what screen
    api = TemplateAPI(context, request, page_title)
    status_message = request.params.get('reason', None)
    if status_message != '@@@one-session-only@@@':
        api.status_message = status_message
        status_message = None
    response = render_to_response(
        'templates/login.pt',
        dict(
            api=api,
            status_message = status_message,
            app_url=request.application_url),
        request=request)
    forget_headers = forget(request)
    response.headers.extend(forget_headers)
    return response
Exemple #14
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, 'Admin UI: Send Email')
        admin_email = get_setting(context, 'admin_email')
        system_name = get_setting(context, 'system_name')
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ('self', '%s <%s>' % (admin.title, admin.email)),
            ('admin', '%s Administrator <%s>' % (system_name, admin_email)),
        ]

        if 'send_email' in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params['to_group']
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, 'security_state', None) == 'inactive':
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params['from_email'] == 'self':
                    message['From'] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message['From'] = from_emails[1][1]
                    message_from = admin_email
                message['To'] = '%s <%s>' % (profile.title, profile.email)
                message['Subject'] = request.params['subject']
                body = u'<html><body>%s</body></html>' % (
                    request.params['text'])
                message.set_payload(body.encode('UTF-8'), 'UTF-8')
                message.set_type('text/html')

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = resource_url(
                    context,
                    request,
                    'admin.html',
                    query=dict(status_message=status_message))
            else:
                redirect_to = resource_url(
                    find_communities(context),
                    request,
                    'all_communities.html',
                    query=dict(status_message=status_message))

            return HTTPFound(location=redirect_to)

        return dict(
            api=api,
            menu=_menu_macro(),
            to_groups=self.to_groups,
            from_emails=from_emails,
        )
Exemple #15
0
def make_non_staff(profile, inform_moderators=True):
    """
    When a user is removed from the KarlStaff role, their community
    memberships are removed. Moderators of their communities are optionally
    informed via email.
    """
    id = profile.__name__
    moderators = {}
    users = find_users(profile)
    profile.categories = {}
    for group in list(users.get_by_id(id)['groups']):
        if group.startswith('group.community'):
            # Remove user from group
            users.remove_user_from_group(id, group)
            if not inform_moderators:
                continue

            # Keep track of moderators we need to email making sure
            # each moderator is emailed only once and each community is
            # only mentioned once in any given email.
            community_name = group.split(':')[1]
            moderators_group = ('group.community:%s:moderators' %
                                community_name)
            for moderator in users.users_in_group(moderators_group):
                if moderator == id:
                    continue  # Really should only come up in unittests
                if moderator not in moderators:
                    moderators[moderator] = set()
                moderators[moderator].add(community_name)

    if not inform_moderators:
        return

    communities = find_communities(profile)
    profiles = profile.__parent__
    mailer = getUtility(IMailDelivery)
    for moderator_id in moderators:
        moderator = profiles[moderator_id]
        msg = Message()
        msg['From'] = get_setting(profile, 'admin_email')
        msg['To'] = '%s <%s>' % (moderator.title, moderator.email)
        msg['Subject'] = 'Notice that %s is now former staff' % profile.title
        former_communities = sorted(
            [communities[c] for c in moderators[moderator_id]],
            key=lambda x: x.title)
        app_url = get_setting(profile, 'offline_app_url')
        communities_info = [
            dict(title=c.title,
                 unremove_url='%s%s?user_id=%s' %
                 (app_url, model_path(c, 'members', 'add_existing.html'), id))
            for c in former_communities
        ]
        body = render(
            'templates/email_notify_former_staff.pt',
            dict(name=profile.title, communities=communities_info),
        )
        if isinstance(body, unicode):
            body = body.encode('UTF-8')
        msg.set_payload(body, 'UTF-8')
        msg.set_type('text/html')

        mailer.send([msg['To']], msg)