Beispiel #1
0
    def handle(self, **options):
        # type: (**str) -> None
        if options["domain"] is None and options["users"] is None:
            self.print_help("python manage.py", "turn_off_digests")
            exit(1)

        if options["domain"]:
            realm = get_realm(options["domain"])
            user_profiles = UserProfile.objects.filter(realm=realm)
        else:
            emails = set(
                [email.strip() for email in options["users"].split(",")])
            user_profiles = []
            for email in emails:
                user_profiles.append(get_user_profile_by_email(email))

        print("Turned off digest emails for:")
        for user_profile in user_profiles:
            already_disabled_prefix = ""
            if user_profile.enable_digest_emails:
                do_change_enable_digest_emails(user_profile, False)
            else:
                already_disabled_prefix = "(already off) "
            print("%s%s <%s>" % (already_disabled_prefix,
                                 user_profile.full_name, user_profile.email))
Beispiel #2
0
def json_change_notify_settings(request, user_profile,
                                enable_stream_desktop_notifications=REQ(validator=check_bool,
                                                                        default=None),
                                enable_stream_sounds=REQ(validator=check_bool,
                                                         default=None),
                                enable_desktop_notifications=REQ(validator=check_bool,
                                                                 default=None),
                                enable_sounds=REQ(validator=check_bool,
                                                  default=None),
                                enable_offline_email_notifications=REQ(validator=check_bool,
                                                                       default=None),
                                enable_offline_push_notifications=REQ(validator=check_bool,
                                                                      default=None),
                                enable_digest_emails=REQ(validator=check_bool,
                                                         default=None)):
    # type: (HttpRequest, UserProfile, Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool]) -> HttpResponse
    result = {}

    # Stream notification settings.

    if enable_stream_desktop_notifications is not None and \
            user_profile.enable_stream_desktop_notifications != enable_stream_desktop_notifications:
        do_change_enable_stream_desktop_notifications(
            user_profile, enable_stream_desktop_notifications)
        result['enable_stream_desktop_notifications'] = enable_stream_desktop_notifications

    if enable_stream_sounds is not None and \
            user_profile.enable_stream_sounds != enable_stream_sounds:
        do_change_enable_stream_sounds(user_profile, enable_stream_sounds)
        result['enable_stream_sounds'] = enable_stream_sounds

    # PM and @-mention settings.

    if enable_desktop_notifications is not None and \
            user_profile.enable_desktop_notifications != enable_desktop_notifications:
        do_change_enable_desktop_notifications(user_profile, enable_desktop_notifications)
        result['enable_desktop_notifications'] = enable_desktop_notifications

    if enable_sounds is not None and \
            user_profile.enable_sounds != enable_sounds:
        do_change_enable_sounds(user_profile, enable_sounds)
        result['enable_sounds'] = enable_sounds

    if enable_offline_email_notifications is not None and \
            user_profile.enable_offline_email_notifications != enable_offline_email_notifications:
        do_change_enable_offline_email_notifications(user_profile, enable_offline_email_notifications)
        result['enable_offline_email_notifications'] = enable_offline_email_notifications

    if enable_offline_push_notifications is not None and \
            user_profile.enable_offline_push_notifications != enable_offline_push_notifications:
        do_change_enable_offline_push_notifications(user_profile, enable_offline_push_notifications)
        result['enable_offline_push_notifications'] = enable_offline_push_notifications

    if enable_digest_emails is not None and \
            user_profile.enable_digest_emails != enable_digest_emails:
        do_change_enable_digest_emails(user_profile, enable_digest_emails)
        result['enable_digest_emails'] = enable_digest_emails

    return json_success(result)
Beispiel #3
0
def json_change_notify_settings(request, user_profile,
                                enable_stream_desktop_notifications=REQ(validator=check_bool,
                                                                        default=None),
                                enable_stream_sounds=REQ(validator=check_bool,
                                                         default=None),
                                enable_desktop_notifications=REQ(validator=check_bool,
                                                                 default=None),
                                enable_sounds=REQ(validator=check_bool,
                                                  default=None),
                                enable_offline_email_notifications=REQ(validator=check_bool,
                                                                       default=None),
                                enable_offline_push_notifications=REQ(validator=check_bool,
                                                                      default=None),
                                enable_digest_emails=REQ(validator=check_bool,
                                                         default=None)):

    result = {}

    # Stream notification settings.

    if enable_stream_desktop_notifications is not None and \
            user_profile.enable_stream_desktop_notifications != enable_stream_desktop_notifications:
        do_change_enable_stream_desktop_notifications(
            user_profile, enable_stream_desktop_notifications)
        result['enable_stream_desktop_notifications'] = enable_stream_desktop_notifications

    if enable_stream_sounds is not None and \
            user_profile.enable_stream_sounds != enable_stream_sounds:
        do_change_enable_stream_sounds(user_profile, enable_stream_sounds)
        result['enable_stream_sounds'] = enable_stream_sounds

    # PM and @-mention settings.

    if enable_desktop_notifications is not None and \
            user_profile.enable_desktop_notifications != enable_desktop_notifications:
        do_change_enable_desktop_notifications(user_profile, enable_desktop_notifications)
        result['enable_desktop_notifications'] = enable_desktop_notifications

    if enable_sounds is not None and \
            user_profile.enable_sounds != enable_sounds:
        do_change_enable_sounds(user_profile, enable_sounds)
        result['enable_sounds'] = enable_sounds

    if enable_offline_email_notifications is not None and \
            user_profile.enable_offline_email_notifications != enable_offline_email_notifications:
        do_change_enable_offline_email_notifications(user_profile, enable_offline_email_notifications)
        result['enable_offline_email_notifications'] = enable_offline_email_notifications

    if enable_offline_push_notifications is not None and \
            user_profile.enable_offline_push_notifications != enable_offline_push_notifications:
        do_change_enable_offline_push_notifications(user_profile, enable_offline_push_notifications)
        result['enable_offline_push_notifications'] = enable_offline_push_notifications

    if enable_digest_emails is not None and \
            user_profile.enable_digest_emails != enable_digest_emails:
        do_change_enable_digest_emails(user_profile, enable_digest_emails)
        result['enable_digest_emails'] = enable_digest_emails

    return json_success(result)
Beispiel #4
0
    def handle(self, **options):
        if options["domain"] is None and options["users"] is None:
            self.print_help("python manage.py", "turn_off_digests")
            exit(1)

        if options["domain"]:
            realm = get_realm(options["domain"])
            user_profiles = UserProfile.objects.filter(realm=realm)
        else:
            emails = set([email.strip() for email in options["users"].split(",")])
            user_profiles = []
            for email in emails:
                user_profiles.append(get_user_profile_by_email(email))

        print("Turned off digest emails for:")
        for user_profile in user_profiles:
            already_disabled_prefix = ""
            if user_profile.enable_digest_emails:
                do_change_enable_digest_emails(user_profile, False)
            else:
                already_disabled_prefix = "(already off) "
            print("%s%s <%s>" % (already_disabled_prefix, user_profile.full_name,
                                 user_profile.email))
Beispiel #5
0
def json_change_notify_settings(
    request,
    user_profile,
    enable_stream_desktop_notifications=REQ(validator=check_bool,
                                            default=None),
    enable_stream_sounds=REQ(validator=check_bool, default=None),
    enable_desktop_notifications=REQ(validator=check_bool, default=None),
    enable_sounds=REQ(validator=check_bool, default=None),
    enable_offline_email_notifications=REQ(validator=check_bool, default=None),
    enable_offline_push_notifications=REQ(validator=check_bool, default=None),
    enable_online_push_notifications=REQ(validator=check_bool, default=None),
    enable_digest_emails=REQ(validator=check_bool, default=None),
    pm_content_in_desktop_notifications=REQ(validator=check_bool,
                                            default=None)):
    # type: (HttpRequest, UserProfile, Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool], Optional[bool]) -> HttpResponse
    result = {}

    # Stream notification settings.

    if enable_stream_desktop_notifications is not None and \
            user_profile.enable_stream_desktop_notifications != enable_stream_desktop_notifications:
        do_change_enable_stream_desktop_notifications(
            user_profile, enable_stream_desktop_notifications)
        result[
            'enable_stream_desktop_notifications'] = enable_stream_desktop_notifications

    if enable_stream_sounds is not None and \
            user_profile.enable_stream_sounds != enable_stream_sounds:
        do_change_enable_stream_sounds(user_profile, enable_stream_sounds)
        result['enable_stream_sounds'] = enable_stream_sounds

    # PM and @-mention settings.

    if enable_desktop_notifications is not None and \
            user_profile.enable_desktop_notifications != enable_desktop_notifications:
        do_change_enable_desktop_notifications(user_profile,
                                               enable_desktop_notifications)
        result['enable_desktop_notifications'] = enable_desktop_notifications

    if enable_sounds is not None and \
            user_profile.enable_sounds != enable_sounds:
        do_change_enable_sounds(user_profile, enable_sounds)
        result['enable_sounds'] = enable_sounds

    if enable_offline_email_notifications is not None and \
            user_profile.enable_offline_email_notifications != enable_offline_email_notifications:
        do_change_enable_offline_email_notifications(
            user_profile, enable_offline_email_notifications)
        result[
            'enable_offline_email_notifications'] = enable_offline_email_notifications

    if enable_offline_push_notifications is not None and \
            user_profile.enable_offline_push_notifications != enable_offline_push_notifications:
        do_change_enable_offline_push_notifications(
            user_profile, enable_offline_push_notifications)
        result[
            'enable_offline_push_notifications'] = enable_offline_push_notifications

    if enable_online_push_notifications is not None and \
            user_profile.enable_online_push_notifications != enable_online_push_notifications:
        do_change_enable_online_push_notifications(
            user_profile, enable_online_push_notifications)
        result[
            'enable_online_push_notifications'] = enable_online_push_notifications

    if enable_digest_emails is not None and \
            user_profile.enable_digest_emails != enable_digest_emails:
        do_change_enable_digest_emails(user_profile, enable_digest_emails)
        result['enable_digest_emails'] = enable_digest_emails

    if pm_content_in_desktop_notifications is not None and \
            user_profile.pm_content_in_desktop_notifications != pm_content_in_desktop_notifications:
        do_change_pm_content_in_desktop_notifications(
            user_profile, pm_content_in_desktop_notifications)
        result[
            'pm_content_in_desktop_notifications'] = pm_content_in_desktop_notifications

    return json_success(result)
Beispiel #6
0
def send_future_email(recipients,
                      email_html,
                      email_text,
                      subject,
                      delay=datetime.timedelta(0),
                      sender=None,
                      tags=[],
                      mail_client=None):
    # type: (List[Dict[str, Any]], Text, Text, Text, datetime.timedelta, Optional[Dict[str, Text]], Iterable[Text], Optional[mandrill.Mandrill]) -> None
    """
    Sends email via Mandrill, with optional delay

    'mail_client' is filled in by the decorator
    """
    # When sending real emails while testing locally, don't accidentally send
    # emails to non-zulip.com users.
    if settings.DEVELOPMENT and \
       settings.EMAIL_BACKEND != 'django.core.mail.backends.console.EmailBackend':
        for recipient in recipients:
            email = recipient.get("email")
            if get_user_profile_by_email(email).realm.string_id != "zulip":
                raise ValueError(
                    "digest: refusing to send emails to non-zulip.com users.")

    # message = {"from_email": "*****@*****.**",
    #            "from_name": "Othello",
    #            "html": "<p>hello</p> there",
    #            "tags": ["signup-reminders"],
    #            "to": [{'email':"*****@*****.**", 'name': "thingamajig"}]
    #            }

    # SMTP mail delivery implementation
    if not mail_client:
        if sender is None:
            # This may likely overridden by settings.DEFAULT_FROM_EMAIL
            sender = {'email': settings.NOREPLY_EMAIL_ADDRESS, 'name': 'Zulip'}
        for recipient in recipients:
            email_fields = {
                'email_html': email_html,
                'email_subject': subject,
                'email_text': email_text,
                'recipient_email': recipient.get('email'),
                'recipient_name': recipient.get('name'),
                'sender_email': sender['email'],
                'sender_name': sender['name']
            }
            ScheduledJob.objects.create(type=ScheduledJob.EMAIL,
                                        filter_string=recipient.get('email'),
                                        data=ujson.dumps(email_fields),
                                        scheduled_timestamp=timezone.now() +
                                        delay)
        return

    # Mandrill implementation
    if sender is None:
        sender = {'email': settings.NOREPLY_EMAIL_ADDRESS, 'name': 'Zulip'}

    message = {
        'from_email': sender['email'],
        'from_name': sender['name'],
        'to': recipients,
        'subject': subject,
        'html': email_html,
        'text': email_text,
        'tags': tags,
    }
    # ignore any delays smaller than 1-minute because it's cheaper just to sent them immediately
    if not isinstance(delay, datetime.timedelta):
        raise TypeError("specified delay is of the wrong type: %s" %
                        (type(delay), ))
    # Note: In the next section we hackishly use **{"async": False} to
    # work around https://github.com/python/mypy/issues/2959 "# type: ignore" doesn't work
    if delay < datetime.timedelta(minutes=1):
        results = mail_client.messages.send(message=message,
                                            ip_pool="Main Pool",
                                            **{"async": False})
    else:
        send_time = (timezone.now() + delay).__format__("%Y-%m-%d %H:%M:%S")
        results = mail_client.messages.send(message=message,
                                            ip_pool="Main Pool",
                                            send_at=send_time,
                                            **{"async": False})
    problems = [
        result for result in results
        if (result['status'] in ('rejected', 'invalid'))
    ]

    if problems:
        for problem in problems:
            if problem["status"] == "rejected":
                if problem["reject_reason"] == "hard-bounce":
                    # A hard bounce means the address doesn't exist or the
                    # recipient mail server is completely blocking
                    # delivery. Don't try to send further emails.
                    if "digest-emails" in tags:
                        from zerver.lib.actions import do_change_enable_digest_emails
                        bounce_email = problem["email"]
                        user_profile = get_user_profile_by_email(bounce_email)
                        do_change_enable_digest_emails(user_profile, False)
                        log_digest_event(
                            "%s\nTurned off digest emails for %s" %
                            (str(problems), bounce_email))
                        continue
                elif problem["reject_reason"] == "soft-bounce":
                    # A soft bounce is temporary; let it try to resolve itself.
                    continue
            raise Exception(
                "While sending email (%s), encountered problems with these recipients: %r"
                % (subject, problems))
    return
Beispiel #7
0
def send_future_email(recipients, email_html, email_text, subject,
                      delay=datetime.timedelta(0), sender=None,
                      tags=[], mail_client=None):
    """
    Sends email via Mandrill, with optional delay

    'mail_client' is filled in by the decorator
    """
    # When sending real emails while testing locally, don't accidentally send
    # emails to non-zulip.com users.
    if settings.DEVELOPMENT and \
       settings.EMAIL_BACKEND != 'django.core.mail.backends.console.EmailBackend':
        for recipient in recipients:
            email = recipient.get("email")
            if get_user_profile_by_email(email).realm.domain != "zulip.com":
                raise ValueError("digest: refusing to send emails to non-zulip.com users.")

    # message = {"from_email": "*****@*****.**",
    #            "from_name": "Othello",
    #            "html": "<p>hello</p> there",
    #            "tags": ["signup-reminders"],
    #            "to": [{'email':"*****@*****.**", 'name': "thingamajig"}]
    #            }

    # SMTP mail delivery implementation
    if not mail_client:
        if sender is None:
            # This may likely overridden by settings.DEFAULT_FROM_EMAIL
            sender = {'email': settings.NOREPLY_EMAIL_ADDRESS, 'name': 'Zulip'}
        for recipient in recipients:
            email_fields = {'email_html': email_html,
                            'email_subject': subject,
                            'email_text': email_text,
                            'recipient_email': recipient.get('email'),
                            'recipient_name': recipient.get('name'),
                            'sender_email': sender['email'],
                            'sender_name': sender['name']}
            ScheduledJob.objects.create(type=ScheduledJob.EMAIL, filter_string=recipient.get('email'),
                                        data=ujson.dumps(email_fields),
                                        scheduled_timestamp=datetime.datetime.utcnow() + delay)
        return

    # Mandrill implementation
    if sender is None:
        sender = {'email': settings.NOREPLY_EMAIL_ADDRESS, 'name': 'Zulip'}

    message = {'from_email': sender['email'],
               'from_name': sender['name'],
               'to': recipients,
               'subject': subject,
               'html': email_html,
               'text': email_text,
               'tags': tags,
               }
    # ignore any delays smaller than 1-minute because it's cheaper just to sent them immediately
    if type(delay) is not datetime.timedelta:
        raise TypeError("specified delay is of the wrong type: %s" % (type(delay),))
    if delay < datetime.timedelta(minutes=1):
        results = mail_client.messages.send(message=message, async=False, ip_pool="Main Pool")
    else:
        send_time = (datetime.datetime.utcnow() + delay).__format__("%Y-%m-%d %H:%M:%S")
        results = mail_client.messages.send(message=message, async=False, ip_pool="Main Pool", send_at=send_time)
    problems = [result for result in results if (result['status'] in ('rejected', 'invalid'))]

    if problems:
        for problem in problems:
            if problem["status"] == "rejected":
                if problem["reject_reason"] == "hard-bounce":
                    # A hard bounce means the address doesn't exist or the
                    # recipient mail server is completely blocking
                    # delivery. Don't try to send further emails.
                    if "digest-emails" in tags:
                        from zerver.lib.actions import do_change_enable_digest_emails
                        bounce_email = problem["email"]
                        user_profile = get_user_profile_by_email(bounce_email)
                        do_change_enable_digest_emails(user_profile, False)
                        log_digest_event("%s\nTurned off digest emails for %s" % (
                                str(problems), bounce_email))
                        continue
                elif problem["reject_reason"] == "soft-bounce":
                    # A soft bounce is temporary; let it try to resolve itself.
                    continue
            raise Exception(
                "While sending email (%s), encountered problems with these recipients: %r"
                % (subject, problems))
    return
Beispiel #8
0
def do_digest_unsubscribe(user_profile):
    # type: (UserProfile) -> None
    do_change_enable_digest_emails(user_profile, False)
Beispiel #9
0
def do_digest_unsubscribe(user_profile):
    # type: (UserProfile) -> None
    do_change_enable_digest_emails(user_profile, False)