Example #1
0
def handle_bounces(sent_to_address, message):
    """
    Handles a received bounce message.

    :param sent_to_address: The envelope-to (return path) address to which the
        bounced email was returned.
    :type sent_to_address: string
    """
    bounce_email, user_email = verp.decode(sent_to_address)
    match = re.match(r'^bounces\+(\d{8})@' + DISTRO_TRACKER_FQDN, bounce_email)
    if not match:
        logger.warning('bounces :: invalid address %s', bounce_email)
        return
    try:
        date = datetime.strptime(match.group(1), '%Y%m%d')
    except ValueError:
        logger.warning('bounces :: invalid date in address %s', bounce_email)
        return

    logger.info('bounces :: received one for %s/%s', user_email, date)
    try:
        user = UserEmailBounceStats.objects.get(email__iexact=user_email)
    except UserEmailBounceStats.DoesNotExist:
        logger.warning('bounces :: unknown user email %s', user_email)
        return

    if bounce_is_for_spam(message):
        logger.info('bounces :: discarded spam bounce for %s/%s',
                    user_email, date)
        return

    UserEmailBounceStats.objects.add_bounce_for_user(email=user_email,
                                                     date=date)

    if user.has_too_many_bounces():
        logger.info('bounces => %s has too many bounces', user_email)

        packages = [p.name for p in user.emailsettings.packagename_set.all()]
        email_body = distro_tracker_render_to_string(
            'dispatch/unsubscribed-due-to-bounces-email.txt', {
                'email': user_email,
                'packages': packages,
            })
        EmailMessage(
            subject='All your package subscriptions have been cancelled',
            from_email=settings.DISTRO_TRACKER_BOUNCES_LIKELY_SPAM_EMAIL,
            to=[user_email],
            cc=[settings.DISTRO_TRACKER_CONTACT_EMAIL],
            body=email_body,
            headers={
                'From': settings.DISTRO_TRACKER_CONTACT_EMAIL,
            },
        ).send()

        user.emailsettings.unsubscribe_all()
        for package in packages:
            logger.info('bounces :: removed %s from %s', user_email, package)
    def test_envelope_from_address(self):
        """
        Tests that the envelope from address is created specially for each user
        in order to track their bounced messages.
        """
        self.subscribe_user_to_package('*****@*****.**', self.package_name)

        self.run_forward()

        msg = mail.outbox[0]
        bounce_address, user_address = verp.decode(msg.from_email)
        self.assertTrue(bounce_address.startswith('bounces+'))
        self.assertEqual(user_address, msg.to[0])