mirror of
https://github.com/quantum5/qlinks.git
synced 2025-04-24 10:41:57 -04:00
Implement broken link email handling
This commit is contained in:
parent
f065351dda
commit
637069c4e7
30
qlinks/email.py
Normal file
30
qlinks/email.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from django.conf import settings
|
||||
from django.core.mail import send_mail
|
||||
from django.template import Context
|
||||
from django.template.loader import get_template
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from qlinks.models import Link
|
||||
|
||||
template = get_template('qlinks/broken_email.txt')
|
||||
|
||||
|
||||
def send_broken_email(link: Link):
|
||||
if link.created_by and link.created_by.email:
|
||||
emails = [link.created_by.email]
|
||||
name = link.created_by.get_full_name()
|
||||
else:
|
||||
emails = [email for name, email in settings.ADMINS]
|
||||
if not emails:
|
||||
return
|
||||
name = _('Admin')
|
||||
|
||||
send_mail(
|
||||
subject=_('Broken link: %s') % link.short_url,
|
||||
message=template.render({
|
||||
'name': name,
|
||||
'link': link,
|
||||
}),
|
||||
from_email=None,
|
||||
recipient_list=emails,
|
||||
)
|
|
@ -6,6 +6,7 @@ from django.core.management import BaseCommand
|
|||
from django.db.models import Min
|
||||
from django.utils import timezone
|
||||
|
||||
from qlinks.email import send_broken_email
|
||||
from qlinks.models import Link
|
||||
|
||||
logger = logging.getLogger('qlinks.checker')
|
||||
|
@ -50,5 +51,6 @@ class Command(BaseCommand):
|
|||
link.check_url()
|
||||
if was_working and not link.is_working:
|
||||
self.stdout.write(f'URL for {link.short} just broke: {link.long}')
|
||||
send_broken_email(link)
|
||||
|
||||
time.sleep(settings.QLINKS_CHECK_THROTTLE)
|
||||
|
|
|
@ -91,3 +91,4 @@ QLINKS_CDN_CACHE = None
|
|||
QLINKS_CHECK_MIN = timedelta(days=6)
|
||||
QLINKS_CHECK_MAX = timedelta(days=8)
|
||||
QLINKS_CHECK_THROTTLE = 1
|
||||
QLINKS_BROKEN_EMAIL = False
|
||||
|
|
|
@ -22,6 +22,35 @@ DATABASES = {
|
|||
STATIC_ROOT = '/srv/example'
|
||||
# STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
||||
|
||||
# Email
|
||||
# https://docs.djangoproject.com/en/4.0/topics/email/#email-backends
|
||||
# The email all broken links notifications will come from, among other things.
|
||||
# DEFAULT_FROM_MAIL = 'qlinks@example.com'
|
||||
|
||||
# A tuple of (name, email) pairs that specifies those who will be mailed
|
||||
# when the server experiences an error when DEBUG = False.
|
||||
# ADMINS = (
|
||||
# ('Your Name', 'your.email@example.com'),
|
||||
# )
|
||||
|
||||
# The following block is included for your convenience, if you want to use Gmail.
|
||||
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
# EMAIL_USE_TLS = True
|
||||
# EMAIL_HOST = 'smtp.gmail.com'
|
||||
# EMAIL_HOST_USER = '<your account>@gmail.com'
|
||||
# EMAIL_HOST_PASSWORD = '<your password>'
|
||||
# EMAIL_PORT = 587
|
||||
|
||||
# To use Mailgun, uncomment this block.
|
||||
# You will need to run `pip install django-mailgun` for to get `MailgunBackend`.
|
||||
# EMAIL_BACKEND = 'django_mailgun.MailgunBackend'
|
||||
# MAILGUN_ACCESS_KEY = '<your Mailgun access key>'
|
||||
# MAILGUN_SERVER_NAME = '<your Mailgun domain>'
|
||||
|
||||
# You can also use Sendgrid, with `pip install sendgrid-django`.
|
||||
# EMAIL_BACKEND = 'sgbackend.SendGridBackend'
|
||||
# SENDGRID_API_KEY = '<Your SendGrid API Key>'
|
||||
|
||||
# qlinks configuration
|
||||
QLINKS_ADMIN_HOST = r'admin'
|
||||
|
||||
|
@ -42,3 +71,6 @@ QLINKS_CANONICAL = None
|
|||
|
||||
# Minimum time in seconds between two consecutive checks.
|
||||
# QLINKS_CHECK_THROTTLE = 1
|
||||
|
||||
# Enable emails.
|
||||
# QLINKS_BROKEN_EMAIL = True
|
||||
|
|
8
qlinks/templates/qlinks/broken_email.txt
Normal file
8
qlinks/templates/qlinks/broken_email.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
{% load i18n %}{% blocktranslate %}Dear {{ name }},{% endblocktranslate %}
|
||||
|
||||
{% translate "QLinks has found a broken link:" %}
|
||||
|
||||
* {% translate "short link" %}: {{ link.short_url }}
|
||||
* {% translate "destination" %}: {{ link.long }}
|
||||
|
||||
{% translate "Please log onto the admin site and fix this." %}
|
45
qlinks/tests/test_email.py
Normal file
45
qlinks/tests/test_email.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from django.contrib.auth.models import User
|
||||
from django.core import mail
|
||||
from django.test import TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from qlinks.email import send_broken_email
|
||||
from qlinks.models import Link
|
||||
|
||||
|
||||
class EmailTest(TestCase):
|
||||
def create_link(self, user) -> Link:
|
||||
return Link.objects.create(
|
||||
short='short',
|
||||
long='https://long.example.com',
|
||||
created_by=user,
|
||||
is_working=False,
|
||||
last_check=timezone.now(),
|
||||
)
|
||||
|
||||
def assert_email(self, link: Link, name: str, to: str):
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual([to], mail.outbox[0].to)
|
||||
self.assertIn(link.short_url, mail.outbox[0].subject)
|
||||
self.assertIn(link.short_url, mail.outbox[0].body)
|
||||
self.assertIn(link.long, mail.outbox[0].body)
|
||||
self.assertIn(f'Dear {name},', mail.outbox[0].body)
|
||||
|
||||
def test_send_no_user(self):
|
||||
link = self.create_link(None)
|
||||
with self.settings(ADMINS=[('someone', 'someone@example.com')]):
|
||||
send_broken_email(link=link)
|
||||
self.assert_email(link, 'Admin', 'someone@example.com')
|
||||
|
||||
def test_send_user(self):
|
||||
link = self.create_link(User.objects.create_user(
|
||||
'test', email='user@example.com', first_name='Test', last_name='User'
|
||||
))
|
||||
send_broken_email(link=link)
|
||||
self.assert_email(link, 'Test User', 'user@example.com')
|
||||
|
||||
def test_send_user_no_email(self):
|
||||
link = self.create_link(User.objects.create_user('test', first_name='Test', last_name='User'))
|
||||
with self.settings(ADMINS=[('someone', 'someone@example.com')]):
|
||||
send_broken_email(link=link)
|
||||
self.assert_email(link, 'Admin', 'someone@example.com')
|
Loading…
Reference in a new issue