SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 1367e007 authored by Jean-Sébastien Caux's avatar Jean-Sébastien Caux
Browse files

Add facility for cc in mails app

parent 4fb6e391
No related branches found
No related tags found
No related merge requests found
......@@ -7,16 +7,12 @@ from django.contrib import admin
from .models import MailLog, MailLogRelation
@admin.action(
description="Render and send email"
)
@admin.action(description="Render and send email")
def send_email(modeladmin, request, queryset):
for mail_id in queryset.values_list("id", flat=True):
call_command("send_mails", id=mail_id)
class MailLogRelationInline(admin.TabularInline):
model = MailLogRelation
......@@ -26,8 +22,13 @@ class MailLogAdmin(admin.ModelAdmin):
list_display = ["__str__", "to_recipients", "created", "status"]
list_filter = ["status"]
readonly_fields = ["created", "latest_activity"]
search_fields = ["to_recipients", "bcc_recipients", "from_email", "subject", "body"]
search_fields = [
"to_recipients",
"cc_recipients",
"bcc_recipients",
"from_email",
"subject",
"body",
]
inlines = [MailLogRelationInline]
actions = [send_email]
......@@ -8,8 +8,10 @@ from ..models import MailLog, MailLogRelation
class EmailBackend(FileBackend):
def write_message(self, message):
cc_str = ", ".join(message.cc).encode()
bcc_str = ", ".join(message.bcc).encode()
self.stream.write(b"Extended Mail FileBasedBackend\n\n")
self.stream.write(b"Cc: " + cc_str + b"\n")
self.stream.write(b"Bcc: " + bcc_str + b"\n")
super().write_message(message)
......@@ -41,6 +43,9 @@ class ModelEmailBackend(FileBackend):
to_recipients = [
sanitize_address(addr, encoding) for addr in email_message.to if addr
]
cc_recipients = [
sanitize_address(addr, encoding) for addr in email_message.cc if addr
]
bcc_recipients = [
sanitize_address(addr, encoding) for addr in email_message.bcc if addr
]
......@@ -68,6 +73,7 @@ class ModelEmailBackend(FileBackend):
subject=subject,
body_html=body_html,
to_recipients=to_recipients,
cc_recipients=cc_recipients,
bcc_recipients=bcc_recipients,
from_email=from_email,
status=status,
......
......@@ -28,9 +28,10 @@ class MailEngine:
"subject",
"from_email",
"from_name",
"cc",
"bcc",
]
_email_fields = ["recipient_list", "from_email", "bcc"]
_email_fields = ["recipient_list", "from_email", "cc", "bcc"]
_processed_template = False
_mail_sent = False
......@@ -39,6 +40,7 @@ class MailEngine:
mail_code,
subject="",
recipient_list=[],
cc=[],
bcc=[],
from_email="",
from_name="",
......@@ -55,12 +57,14 @@ class MailEngine:
The following arguments overwrite the default values, set in the configuration files:
-- subject (str, optional)
-- recipient_list (str, optional): List of email addresses or db-relations.
-- cc (str, optional): List of email addresses or db-relations.
-- bcc (str, optional): List of email addresses or db-relations.
-- from_email (str, optional): Plain email address.
-- from_name (str, optional): Display name for from address.
"""
self.mail_code = mail_code
self.extra_config = {
"cc": cc,
"bcc": bcc,
"subject": subject,
"from_name": from_name,
......@@ -133,6 +137,7 @@ class MailEngine:
self.mail_data.get("from_email", "noreply@%s" % get_current_domain()),
),
self.mail_data["recipient_list"],
cc=self.mail_data["cc"],
bcc=self.mail_data["bcc"],
reply_to=[
self.mail_data.get("from_email", "noreply@%s" % get_current_domain())
......@@ -244,7 +249,7 @@ class MailEngine:
"key": email_key,
}
)
for email_key in ["recipient_list", "bcc"]:
for email_key in ["recipient_list", "cc", "bcc"]:
if email_key in self.mail_data and self.mail_data[email_key]:
if not isinstance(self.mail_data[email_key], list):
raise ConfigurationError(
......
......@@ -22,6 +22,7 @@ class MailLogFactory(factory.django.DjangoModelFactory):
mail_code = factory.Faker("slug")
subject = factory.Faker("word")
to_recipients = factory.List([factory.Faker("ascii_safe_email") for _ in range(2)])
cc_recipients = factory.List([factory.Faker("ascii_safe_email") for _ in range(2)])
bcc_recipients = factory.List([factory.Faker("ascii_safe_email") for _ in range(2)])
class Meta:
......
......@@ -19,7 +19,10 @@ class EmailForm(forms.Form):
subject = forms.CharField(max_length=255, label="Subject*")
text = forms.CharField(widget=SummernoteEditor, label="Text*")
mail_field = MultiEmailField(label="Optional: bcc this email to", required=False)
cc_mail_field = MultiEmailField(label="Optional: cc this email to", required=False)
bcc_mail_field = MultiEmailField(
label="Optional: bcc this email to", required=False
)
prefix = "mail_form"
extra_config = {}
......@@ -46,7 +49,10 @@ class EmailForm(forms.Form):
data = {
"%s-subject" % self.prefix: data.get("%s-subject" % self.prefix),
"%s-text" % self.prefix: data.get("%s-text" % self.prefix),
"%s-mail_field" % self.prefix: data.get("%s-mail_field" % self.prefix),
"%s-cc_mail_field"
% self.prefix: data.get("%s-cc_mail_field" % self.prefix),
"%s-bcc_mail_field"
% self.prefix: data.get("%s-bcc_mail_field" % self.prefix),
}
else:
# Reset to prevent having a false-bound form.
......@@ -75,7 +81,9 @@ class EmailForm(forms.Form):
def save(self):
self.engine.render_template(self.cleaned_data["text"])
self.engine.mail_data["subject"] = self.cleaned_data["subject"]
if bcc_mail_str := self.cleaned_data["mail_field"]:
if cc_mail_str := self.cleaned_data["cc_mail_field"]:
self.engine.mail_data["cc"] += [m.strip() for m in cc_mail_str.split(",")]
if bcc_mail_str := self.cleaned_data["bcc_mail_field"]:
self.engine.mail_data["bcc"] += [m.strip() for m in bcc_mail_str.split(",")]
self.engine.send_mail()
return self.engine.template_variables["object"]
......
......@@ -55,6 +55,7 @@ class Command(BaseCommand):
db_mail.body,
db_mail.from_email,
db_mail.to_recipients,
cc=db_mail.cc_recipients,
bcc=db_mail.bcc_recipients,
reply_to=(db_mail.from_email,),
connection=connection,
......
# Generated by Django 4.2.10 on 2024-03-26 16:59
import django.contrib.postgres.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("mails", "0007_alter_maillogrelation_value"),
]
operations = [
migrations.AddField(
model_name="maillog",
name="cc_recipients",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.EmailField(max_length=254),
blank=True,
null=True,
size=None,
),
),
]
......@@ -37,6 +37,7 @@ class MailLog(models.Model):
body_html = models.TextField(blank=True)
to_recipients = ArrayField(models.EmailField(), blank=True, null=True)
cc_recipients = ArrayField(models.EmailField(), blank=True, null=True)
bcc_recipients = ArrayField(models.EmailField(), blank=True, null=True)
from_email = models.CharField(max_length=254, blank=True)
......@@ -51,7 +52,11 @@ class MailLog(models.Model):
return "{id}. {subject} ({count} recipients)".format(
id=self.id,
subject=self.subject[:30],
count=len(self.to_recipients) + len(self.bcc_recipients),
count=(
len(self.to_recipients)
+ len(self.bcc_recipients)
+ (len(self.cc_recipients) if self.cc_recipients else 0)
),
)
def get_full_context(self):
......
......@@ -22,6 +22,7 @@ class ModelEmailBackendTests(TestCase):
"tests/test_mail_code_1",
subject="Test Subject Unique For Testing 93872",
recipient_list=["test1@scipost.org"],
cc=["testcc@scipost.org"],
bcc=["test2@scipost.org"],
from_email="test3@scipost.org",
from_name="Test Name",
......@@ -39,6 +40,7 @@ class ModelEmailBackendTests(TestCase):
self.assertEqual(mail_log.body, "")
self.assertEqual(mail_log.body_html, "")
self.assertIn("test1@scipost.org", mail_log.to_recipients)
self.assertIn("testcc@scipost.org", mail_log.cc_recipients)
self.assertIn("test2@scipost.org", mail_log.bcc_recipients)
self.assertEqual("Test Name <test3@scipost.org>", mail_log.from_email)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment