-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Org: Collect inactive email addresses daily and indicate delivery fai…
…lures for newsletter recipients TYPE: Feature LINK: ogc-1896
- Loading branch information
1 parent
c0942af
commit 821ff43
Showing
12 changed files
with
209 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
import json | ||
import os | ||
from pathlib import Path | ||
from unittest.mock import patch, Mock | ||
|
||
import pytest | ||
import requests | ||
import transaction | ||
from datetime import datetime, timedelta | ||
from freezegun import freeze_time | ||
|
@@ -1069,6 +1071,7 @@ def test_delete_content_marked_deletable__directory_entries(org_app, handlers): | |
grundeigentumer_in='Berta Bertinio', | ||
publication_start=datetime(2024, 4, 1, tzinfo=tz), | ||
publication_end=datetime(2024, 4, 10, tzinfo=tz), | ||
# delete_when_expired=True, | ||
)) | ||
event.delete_when_expired = True | ||
|
||
|
@@ -1442,3 +1445,82 @@ def count_recipients(): | |
assert message['To'] == john.address | ||
assert sport_clubs().title in message['Subject'] | ||
assert entry_2.name in message['TextBody'] | ||
|
||
|
||
def test_update_newsletter_email_bounce_statistics(org_app, handlers): | ||
register_echo_handler(handlers) | ||
register_directory_handler(handlers) | ||
|
||
# fake postmark mailer | ||
org_app.mail['marketing']['mailer'] = 'postmark' | ||
|
||
client = Client(org_app) | ||
job = get_cronjob_by_name(org_app, | ||
'update_newsletter_email_bounce_statistics') | ||
job.app = org_app | ||
# tz = ensure_timezone('Europe/Zurich') | ||
|
||
transaction.begin() | ||
|
||
# create recipients Franz and Heinz | ||
recipients = RecipientCollection(org_app.session()) | ||
recipients.add('[email protected]', confirmed=True) | ||
recipients.add('[email protected]', confirmed=True) | ||
recipients.add('[email protected]', confirmed=True) | ||
|
||
transaction.commit() | ||
close_all_sessions() | ||
|
||
with patch('requests.get') as mock_get: | ||
mock_get.return_value = Bunch( | ||
status_code=200, | ||
json=lambda: { | ||
'TotalCount': 2, | ||
'Bounces': [ | ||
{'RecordType': 'Bounce', 'ID': 3719297970, | ||
'Inactive': False, 'Email': '[email protected]'}, | ||
{'RecordType': 'Bounce', 'ID': 4739297971, | ||
'Inactive': True, 'Email': '[email protected]'} | ||
] | ||
}, | ||
raise_for_status=Mock(return_value=None), | ||
) | ||
|
||
# execute cronjob | ||
client.get(get_cronjob_url(job)) | ||
|
||
# check if the statistics are updated | ||
assert mock_get.called | ||
assert RecipientCollection(org_app.session()).by_address( | ||
'[email protected]').is_inactive is False | ||
assert RecipientCollection(org_app.session()).by_address( | ||
'[email protected]').is_inactive is True | ||
assert RecipientCollection(org_app.session()).by_address( | ||
'[email protected]').is_inactive is False | ||
|
||
# test raising runtime warning exception for status code 401 | ||
with patch('requests.get') as mock_get: | ||
mock_get.return_value = Bunch( | ||
status_code=401, | ||
json=lambda: {}, | ||
raise_for_status=Mock( | ||
side_effect=requests.exceptions.HTTPError('401 Unauthorized')), | ||
) | ||
|
||
# execute cronjob | ||
with pytest.raises(RuntimeWarning): | ||
client.get(get_cronjob_url(job)) | ||
|
||
# for other 30x and 40x status codes, the cronjob shall raise an exception | ||
for status_code in [301, 302, 303, 400, 402, 403, 404, 405]: | ||
with patch('requests.get') as mock_get: | ||
mock_get.return_value = Bunch( | ||
status_code=status_code, | ||
json=lambda: {}, | ||
raise_for_status=Mock( | ||
side_effect=requests.exceptions.HTTPError()), | ||
) | ||
|
||
# execute cronjob | ||
with pytest.raises(requests.exceptions.HTTPError): | ||
client.get(get_cronjob_url(job)) |
821ff43
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Tschuppi81 I think it would be nice if you also tried to sync recently reactivated recipients, otherwise a recipient will be eternally marked as inactive, even if it has been reactivated on Postmark's end.
We could even go one step further and add a button so people can reactivate the address in this list. There should be an API call to reactivate recipients. https://postmarkapp.com/developer/api/suppressions-api
The Suppressions API is probably better than the bounce API anyways, since you get exactly what we care about, so a time filter is probably not needed either, since that list shouldn't be as large. So you can do a full-sync and remove the inactive flag from any address that isn't on the list.
We could also try using the webhook instead, so we don't need a cronjob. Although that would be a bit more tricky to setup.
821ff43
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although if we do add a reactivate button, we should only allow it for "HardBounce" and maybe "Manual", but definitely not "SpamComplaint".