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])