def test_bounce_over_limit(self): """ Tests that all the user's subscriptions are dropped when too many bounces are received. """ # Set up some prior bounces - one each day. date = timezone.now().date() for days in range(1, settings.PTS_MAX_DAYS_TOLERATE_BOUNCE): self.add_sent(self.user, date - timedelta(days=days)) self.add_bounce(self.user, date - timedelta(days=days)) # Set up a sent mail today. self.add_sent(self.user, date) # Make sure there were at least some subscriptions packages_subscribed_to = [ subscription.package.name for subscription in self.user.subscription_set.all() ] self.assertTrue(len(packages_subscribed_to) > 0) # Receive a bounce message. self.run_dispatch(self.create_bounce_address(self.user.email)) # Assert that the user's subscriptions have been dropped. self.assertEqual(self.user.subscription_set.count(), 0) # A notification was sent to the user. self.assertEqual(len(mail.outbox), 1) self.assertIn(self.user.email, mail.outbox[0].to) # Check that the content of the email is correct. self.assertEqual(mail.outbox[0].body, pts_render_to_string( 'dispatch/unsubscribed-due-to-bounces-email.txt', { 'email': self.user.email, 'packages': packages_subscribed_to } ))
def handle(self): self.reply(pts_render_to_string('control/help.txt', { 'descriptions': [ command.META.get('description', '') for command in UNIQUE_COMMANDS ], }))
def get_confirmation_message(self): """ :returns: A message giving additional information about unsubscribing from all packages. :rtype: string """ return pts_render_to_string( 'control/email-unsubscribeall-confirmation.txt' )
def get_confirmation_message(self): """ :returns: A message giving additional information about subscribing to a package. :rtype: string """ return pts_render_to_string( 'control/email-subscription-confirmation.txt', { 'package': self.package, } )
def handle_bounces(sent_to_address): """ 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})@" + PTS_FQDN, bounce_email) if not match: # Invalid bounce address logger.error("Invalid bounce address " + bounce_email) return try: date = datetime.strptime(match.group(1), "%Y%m%d") except ValueError: # Invalid bounce address logger.error("Invalid bounce address " + bounce_email) return EmailUserBounceStats.objects.add_bounce_for_user(email=user_email, date=date) logger.info("Logged bounce for {email} on {date}".format(email=user_email, date=date)) user = EmailUserBounceStats.objects.get(user_email__email=user_email) if user.has_too_many_bounces(): logger.info("{email} has too many bounces".format(email=user_email)) email_body = pts_render_to_string( "dispatch/unsubscribed-due-to-bounces-email.txt", {"email": user_email, "packages": user.packagename_set.all()}, ) EmailMessage( subject="All your subscriptions from the PTS have been cancelled", from_email=settings.PTS_BOUNCES_LIKELY_SPAM_EMAIL, to=[user_email], cc=[settings.PTS_CONTACT_EMAIL], body=email_body, headers={"From": settings.PTS_CONTACT_EMAIL}, ).send() user.unsubscribe_all()
def post(self, request, slug): self.team = get_object_or_404(Team, slug=slug) if self.team.owner != request.user: raise PermissionDenied form = AddTeamMemberForm(request.POST) if form.is_valid(): email = form.cleaned_data['email'] # Emails that do not exist should be created user, _ = EmailUser.objects.get_or_create(email=email) # The membership is muted by default until the user confirms it membership = self.team.add_members([user], muted=True)[0] confirmation = MembershipConfirmation.objects.create_confirmation( membership=membership) send_mail( 'PTS Team Membership Confirmation', pts_render_to_string('core/email-team-membership-confirmation.txt', { 'confirmation': confirmation, 'team': self.team, }), from_email=settings.PTS_CONTACT_EMAIL, recipient_list=[email]) return redirect('pts-team-manage', slug=self.team.slug)
def _ask_confirmation(self, email, commands, messages): """ Sends a confirmation mail to a single user. Includes all commands that the user needs to confirm. """ command_confirmation = CommandConfirmation.objects.create_for_commands( commands=commands) message = pts_render_to_string( 'control/email-confirmation-required.txt', { 'command_confirmation': command_confirmation, 'confirmation_messages': self.confirmation_messages[email], } ) subject = 'CONFIRM ' + command_confirmation.confirmation_key EmailMessage( subject=subject, to=[email], from_email=PTS_BOUNCES_EMAIL, headers={ 'From': PTS_CONTROL_EMAIL, }, body=message, ).send()
def get_confirmation_email_content(self, confirmation): return pts_render_to_string(self.confirmation_email_template, { 'confirmation': confirmation, })