Changeset - 3cccc3bdd90e
[Not reviewed]
0 4 1
Ben Sturmfels (bsturmfels) - 3 months ago 2024-01-26 06:49:03
ben@sturm.com.au
Email announcement about new UTS candidate
5 files changed with 81 insertions and 10 deletions:
0 comments (0 inline, 0 general)
conservancy/usethesource/admin.py
Show inline comments
...
 
@@ -2,2 +2,3 @@ from django.contrib import admin
 

	
 
from .emails import make_candidate_email
 
from .models import Candidate, Comment
...
 
@@ -27 +28,9 @@ class CandidateAdmin(admin.ModelAdmin):
 
    prepopulated_fields = {'slug': ['name']}
 

	
 
    def save_model(self, request, obj, form, change):
 
        send_email = obj.id is None
 
        super().save_model(request, obj, form, change)
 
        if send_email:
 
            # Announce the new candidate
 
            email = make_candidate_email(obj, request.user)
 
            email.send()
conservancy/usethesource/emails.py
Show inline comments
 
from django.core.mail import EmailMessage
 
from django.shortcuts import reverse
 

	
 
SENDER = 'compliance@sfconservancy.org'
 
LIST_RECIPIENT = 'nutbush@lists.sfconservancy.org'
 

	
 

	
 
def make_candidate_email(candidate, user):
 
    """The initial email announcing the new candidate."""
 
    subject = candidate.name
 
    signature = user.get_full_name() or user.username
 
    sender = f'{signature} <{SENDER}>'
 
    to = [LIST_RECIPIENT]
 
    body = f'''\
 
We've just published the following new candidate:
 

	
 
{candidate.name}
 
Vendor: {candidate.vendor}
 
Device: {candidate.device}
 
Released: {candidate.release_date}
 

	
 
{candidate.description}
 

	
 
To download this candidate's source and binary image, visit:
 
https://sfconservancy.org{reverse('usethesource:candidate', kwargs={'slug': candidate.slug})}
 

	
 
--
 
{signature}
 
'''
 
    headers = {'Message-ID': candidate.email_message_id}
 
    return EmailMessage(subject, body, sender, to, headers=headers)
 

	
...
 
@@ -4,6 +34,7 @@ from django.core.mail import EmailMessage
 
def make_comment_email(comment):
 
    """Email when a comment is added to a candidate."""
 
    subject = f'Re: {comment.candidate.name}'
 
    signature = comment.user.get_full_name() or comment.user.username
 
    sender = f'{signature} <compliance@sfconservancy.org>'
 
    to = ['nutbush@lists.sfconservancy.org']
 
    sender = f'{signature} <{SENDER}>'
 
    to = [LIST_RECIPIENT]
 
    body = f'{comment.message}\n\n--\n{signature}'
conservancy/usethesource/migrations/0005_candidate_email_message_id.py
Show inline comments
 
new file 100644
 
# Generated by Django 3.2.19 on 2024-01-26 01:36
 

	
 
import conservancy.usethesource.models
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('usethesource', '0004_auto_20240125_2352'),
 
    ]
 

	
 
    operations = [
 
        migrations.AddField(
 
            model_name='candidate',
 
            name='email_message_id',
 
            field=models.CharField(default=conservancy.usethesource.models.gen_message_id, max_length=255),
 
        ),
 
    ]
conservancy/usethesource/models.py
Show inline comments
...
 
@@ -6,2 +6,7 @@ from django.db import models
 

	
 
def gen_message_id():
 
    """Generate a time-based identifier for use in "In-Reply-To" header."""
 
    return f'<{uuid.uuid1()}@sfconservancy.org>'
 

	
 

	
 
class Candidate(models.Model):
...
 
@@ -18,2 +23,3 @@ class Candidate(models.Model):
 
    ordering = models.SmallIntegerField(default=0)
 
    email_message_id = models.CharField(max_length=255, default=gen_message_id)
 

	
...
 
@@ -26,7 +32,2 @@ class Candidate(models.Model):
 

	
 
def gen_message_id():
 
    """Generate a time-based identifier for use in "In-Reply-To" header."""
 
    return f'<{uuid.uuid1()}@sfconservancy.org>'
 

	
 

	
 
class Comment(models.Model):
...
 
@@ -50,3 +51,3 @@ class Comment(models.Model):
 
    def in_reply_to(self):
 
        """Determine the message_id of the previous comment.
 
        """Determine the message_id of the previous comment or the candidate.
 

	
...
 
@@ -57,3 +58,3 @@ class Comment(models.Model):
 
        else:
 
            return None
 
            return self.candidate.email_message_id
 

	
conservancy/usethesource/tests.py
Show inline comments
...
 
@@ -7,3 +7,3 @@ import pytest
 
from . import models
 
from .emails import make_comment_email
 
from .emails import make_candidate_email, make_comment_email
 
from .models import Candidate, Comment
...
 
@@ -30,2 +30,13 @@ def test_message_id():
 

	
 
@pytest.mark.django_db
 
def test_candidate_email():
 
    user = User.objects.create(first_name='Test', last_name='User')
 
    candidate = make_candidate(name='Test Candidate', save=True)
 
    email = make_candidate_email(candidate, user)
 
    assert 'Message-ID' in email.extra_headers
 
    assert email.subject == 'Test Candidate'
 
    assert 'Test Candidate' in email.body
 
    assert 'Test User' in email.body
 

	
 

	
 
@pytest.mark.django_db
0 comments (0 inline, 0 general)