Exemplo n.º 1
0
	def _unsubscribe(request):

		email = request.POST["data[email]"]

		try:
			email_address = EmailAddress.objects.get(email=email)
			user = email_address.user
			user_exists = True
			primary_email = find_best_email_for_user(user)

			# If the user exists and the subscription update was related to their primary
			# email address, update their marketing contact preference. (We don't want to
			# update the preference if their non-primary email address was unsubscribed,
			# because that won't really reflect the actual state of their preference.)

			if "email" in user.settings and primary_email and primary_email.email == email:
				user.settings["email"]["marketing"] = False
				user.save()

		except EmailAddress.DoesNotExist:
			user_exists = False
			primary_email = False

		influx_metric(
			"mailchimp_webhook_request",
			{"value": 1},
			reason=request.POST.get("data[reason]"),
			type="unsubscribe",
			primary_email=primary_email,
			user_exists=user_exists
		)
Exemplo n.º 2
0
	def _subscribe(request):

		email = request.POST["data[email]"]

		try:
			email_address = EmailAddress.objects.get(email=email)
			user = email_address.user
			user_exists = True
			primary_email = find_best_email_for_user(user)

			# If the user exists and the subscription webhook was about their primary email,
			# update their marketing contact preference to reflect that.

			if primary_email and primary_email.email == email:
				if "email" not in user.settings:
					user.settings["email"] = {"marketing": True}
				else:
					user.settings["email"]["marketing"] = True

				user.save()

		except EmailAddress.DoesNotExist:
			user_exists = False
			primary_email = False

		influx_metric(
			"mailchimp_webhook_request",
			{"value": 1},
			type="subscribe",
			primary_email=primary_email,
			user_exists=user_exists
		)
Exemplo n.º 3
0
def test_find_best_email_for_user_primary(user):
	EmailAddress.objects.add_email(None, user, "*****@*****.**")
	email2 = EmailAddress.objects.add_email(None, user, "*****@*****.**")

	email2.set_as_primary()

	assert find_best_email_for_user(user) == email2
Exemplo n.º 4
0
    def post(self, request):
        marketing_prefs = request.POST.get("marketing", "") == "on"

        request.user.settings["email"] = {
            "marketing": marketing_prefs,
            "updated": timezone.now().isoformat(),
        }
        request.user.save()

        try:
            client = get_mailchimp_client()
            email = find_best_email_for_user(request.user)
            client.lists.members.create_or_update(
                settings.MAILCHIM_LIST_KEY_ID,
                get_subscriber_hash(email.email), {
                    "email_address":
                    email.email,
                    "status_if_new":
                    get_mailchimp_subscription_status(request.user)
                })
        except Exception as e:
            log.warning("Failed to contact MailChimp API: %s" % e)
            influx_metric("mailchimp_request_failures", {"count": 1})

        messages.info(request, _("Your email preferences have been saved."))
        return redirect(self.success_url)
Exemplo n.º 5
0
    def _process_page(self, page, options):
        user_tags = []
        for user in page:
            pct_before = self._percent(self.user_count, self.total_users)
            self.user_count += 1
            pct_after = self._percent(self.user_count, self.total_users)

            if pct_before != pct_after:
                print(f"Working... {pct_after}% complete.", flush=True)

            email = find_best_email_for_user(user)
            if email:
                tags_to_add = []
                tags_to_remove = []

                for tag in TAGS:
                    if tag.should_apply_to(user):
                        tags_to_add.append(tag)
                    else:
                        tags_to_remove.append(tag)

                user_tags.append((user, email, tags_to_add, tags_to_remove))

        # After we've read all the data from the page, go back and make modifications; this
        # part clears the prefetch cache so it has to happen as a second pass.

        with transaction.atomic():
            for user, email, tags_to_add, tags_to_remove in user_tags:
                mailchimp_tags_to_add = []
                mailchimp_tags_to_remove = []
                needs_publish = False

                for tag in tags_to_add:
                    if tag.add_user_to_tag_group(user):
                        mailchimp_tags_to_add.append(tag)
                        needs_publish = True

                for tag in tags_to_remove:
                    if tag.remove_user_from_tag_group(user):
                        mailchimp_tags_to_remove.append(tag)
                        needs_publish = True

                if needs_publish:
                    self.users_with_tag_changes += 1

                    if options["publish_remote"]:
                        self._publish_tag_changes(user,
                                                  email.email,
                                                  mailchimp_tags_to_add,
                                                  mailchimp_tags_to_remove,
                                                  verbose=options["verbose"])
Exemplo n.º 6
0
def _update_mailchimp_tags_for_premium_subscriber(user):
    email = find_best_email_for_user(user)

    if email:
        tag = PremiumSubscriberTag()
        if tag.should_apply_to(user) and tag.add_user_to_tag_group(user):

            client = get_mailchimp_client()
            list_key_id = settings.MAILCHIMP_LIST_KEY_ID
            email_hash = get_subscriber_hash(email.email)

            # At this point we have no idea whether the user's email address is already
            # registered with MailChimp, so do a defensive create-or-update to make sure
            # it's on the list before we give them the premium tag.

            try:
                client.lists.members.create_or_update(
                    list_key_id, email_hash, {
                        "email_address": email.email,
                        "status_if_new":
                        get_mailchimp_subscription_status(user),
                    })

                influx_metric("mailchimp_requests", {"count": 1},
                              method="create_or_update")

                # ...then assign the premium tag.

                client.lists.members.tags.add(list_key_id, email_hash,
                                              tag.name)
                influx_metric("mailchimp_requests", {"count": 1},
                              method="add_tags")

            except Exception as e:
                log.warning("Failed to contact MailChimp API: %s" % e)
                influx_metric("mailchimp_request_failures", {"count": 1})
Exemplo n.º 7
0
def test_find_best_email_for_user_no_primary(user):
	email1 = EmailAddress.objects.add_email(None, user, "*****@*****.**")
	EmailAddress.objects.add_email(None, user, "*****@*****.**")

	assert find_best_email_for_user(user) == email1
Exemplo n.º 8
0
def test_find_best_email_for_user_no_emails(user):
	assert find_best_email_for_user(user) is None
Exemplo n.º 9
0
    def post(self, request):
        marketing_prefs = request.POST.get("marketing", "") == "on"
        client = get_mailchimp_client()

        try:
            request.user.settings["email"] = {
                "marketing": marketing_prefs,
                "updated": timezone.now().isoformat(),
            }

            status = get_mailchimp_subscription_status(request.user)
            email = find_best_email_for_user(request.user)

            try:
                client.lists.members.create_or_update(
                    settings.MAILCHIMP_LIST_KEY_ID,
                    get_subscriber_hash(email.email), {
                        "email_address": email.email,
                        "status_if_new": status,
                        "status": status
                    })
            except MailChimpError as e:

                # The request to Mailchimp may fail if the user unsubscribed via the
                # Mailchimp interface (through a link in an email footer, e.g.). In this
                # case, they can only resubscribe through a confirmation email. Setting the
                # user's status to 'pending' will trigger the confirmation email to be sent.

                args = e.args[0]

                if (args.get("status") == 400
                        and args.get("title") == "Member In Compliance State"):
                    client.lists.members.update(
                        settings.MAILCHIMP_LIST_KEY_ID,
                        get_subscriber_hash(email.email), {
                            "email_address": email.email,
                            "status": "pending"
                        })
                    influx_metric("mailchimp_requests", {"count": 1},
                                  method="update")

                    return self._redirect_with_message(
                        request,
                        _("Check your inbox! We've sent an email to confirm your subscription preferences."
                          ))
                else:
                    self._log_mailchimp_error(e)
                    return self._redirect_with_message(
                        request,
                        _("Failed to save your email preferences. Please try again later!"
                          ))

        except Exception as e:
            self._log_mailchimp_error(e)
            return self._redirect_with_message(
                request,
                _("Failed to save your email preferences. Please try again later!"
                  ))

        # Only save the user record if we were actually able to sync the marketing
        # preferences with Mailchimp.

        request.user.save()

        influx_metric("mailchimp_requests", {"count": 1},
                      method="create_or_update")
        return self._redirect_with_message(
            request, _("Your email preferences have been saved."))