def test_open_tracking(self): campaign = Campaign.objects.create(message_content_html=HTML_MESSAGE, message_content_text="Test") subscriber = Subscriber.objects.get(email="*****@*****.**") event = campaign.get_event_for_subscriber(subscriber) message = message_for_event(event) tracking_id = event.tracking_id tracking_url = reverse("nuntius_track_open", kwargs={"tracking_id": tracking_id}) self.assertIn( '<img src="{}" width="1" height="1" alt="nt">'.format( IMAGES_URL + tracking_url), str(message.message()), ) for i in range(2): self.client.get(tracking_url) self.assertEqual( 2, CampaignSentEvent.objects.get(email="*****@*****.**").open_count, campaign.get_open_count(), ) self.assertEqual(1, campaign.get_unique_open_count())
def email_campaign_manager_process( *, campaign: Campaign, queue: mp.Queue, quit_event: mp.Event ): """ Main function of the process responsible for scheduling the sending of campaigns :param campaign: the campaign for which messages must be sent :type campaign: :class:`nuntius.models.Campaign` :param queue: the work queue on which email messages are put :type queue: : class:`multiprocessing.Queue` :param quit_event: an event that may be used by the main process to tell the manager it needs to quit :type quit_event: class:`multiprocessing.Event` """ queryset = campaign.get_subscribers_queryset() # eliminate people who already received the message queryset = queryset.annotate( already_sent=Exists( CampaignSentEvent.objects.filter( subscriber_id=OuterRef("pk"), campaign_id=campaign.id ).exclude(result=CampaignSentStatusType.PENDING) ) ).filter(already_sent=False) campaign_finished = False for subscriber in queryset.iterator(): if quit_event.is_set(): break if subscriber.get_subscriber_status() != AbstractSubscriber.STATUS_SUBSCRIBED: continue sent_event = campaign.get_event_for_subscriber(subscriber) # just in case there is another nuntius_worker started, but this should not happen if sent_event.result != CampaignSentStatusType.PENDING: continue message = message_for_event(sent_event) try: put_in_queue_or_quit( queue, (message, sent_event.id), event=quit_event, polling_period=app_settings.POLLING_INTERVAL, ) except GracefulExit: break else: campaign_finished = True queue.close() queue.join_thread() # everything has been scheduled for sending: if campaign_finished: campaign.status = Campaign.STATUS_SENT campaign.save()
def test_send_emails(self): segment = Segment.objects.get(id="subscribed") campaign = Campaign.objects.create( segment=segment, message_from_email="*****@*****.**", message_from_name="Test sender", message_subject="Subject", message_content_text="test {{email}} test", ) subscribers = segment.get_subscribers_queryset() events = [campaign.get_event_for_subscriber(s) for s in subscribers] messages = [message_for_event(e) for e in events] run_sender_process_sync(zip(messages, (e.id for e in events))) self.assertEqual(len(events), len(mail.outbox)) self.assertEqual(len(events), campaign.get_sent_count())
def test_correctly_generate_text_only_message_from_subscriber(self): campaign = Campaign.objects.create( message_from_email="*****@*****.**", message_subject="Nice campaign", message_content_text="Here's some text for you {{ email }} !", ) subscriber = Subscriber.objects.get(email="*****@*****.**") event = campaign.get_event_for_subscriber(subscriber) message = message_for_event(event) self.assertIsInstance(message, EmailMessage) self.assertEqual(message.subject, "Nice campaign") self.assertEqual(message.from_email, "*****@*****.**") self.assertEqual(message.to, [subscriber.email]) self.assertEqual(message.body, "Here's some text for you [email protected] !") self.assertEqual(message.content_subtype, "plain")
def test_link_tracking(self): campaign = Campaign.objects.create( message_content_html=HTML_MESSAGE, message_content_text="Test", utm_name="tracked_campaign", ) subscriber = Subscriber.objects.get(email="*****@*****.**") event = campaign.get_event_for_subscriber(subscriber) message = message_for_event(event) tracking_id = event.tracking_id encoded_tracking_query = "?utm_content=link-0&utm_term=" tracking_url = reverse( "nuntius_track_click", kwargs={ "tracking_id": tracking_id, "signature": sign_url(campaign, EXTERNAL_LINK + encoded_tracking_query), "link": url_quote(EXTERNAL_LINK + encoded_tracking_query, safe=""), }, ) self.assertIn( '<a href="{}">Link</a>'.format(LINKS_URL + tracking_url), str(message.message()), ) for i in range(2): res = self.client.get(tracking_url) self.assertRedirects( res, EXTERNAL_LINK + "?utm_campaign=tracked_campaign&utm_content=link-0&utm_source=nuntius&utm_medium=email", fetch_redirect_response=False, ) self.assertEqual( 2, CampaignSentEvent.objects.get(email="*****@*****.**").click_count, campaign.get_click_count(), )