• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

liqd / adhocracy-plus / 18908688697

29 Oct 2025 12:59PM UTC coverage: 44.622% (-44.5%) from 89.135%
18908688697

Pull #2986

github

web-flow
Merge 1dfde8ee7 into 445e1d498
Pull Request #2986: Draft: Speed up Github Ci Tests

3012 of 6750 relevant lines covered (44.62%)

0.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

29.23
/apps/users/emails.py
1
from email.mime.image import MIMEImage
1✔
2

3
import magic
1✔
4
from django.conf import settings
1✔
5
from django.template.loader import get_template
1✔
6
from django.urls import reverse
1✔
7
from django.utils import translation
1✔
8
from django.utils.translation import gettext_lazy as _
1✔
9
from sentry_sdk import capture_message
1✔
10

11
from adhocracy4.emails import Email
1✔
12

13
from .models import User
1✔
14

15
ACCOUNT_LINK_TEXT = _(
1✔
16
    "If you no longer want to receive any notifications, "
17
    "change the settings for your {}account{}."
18
)
19
PROJECT_LINK_TEXT = _(
1✔
20
    "If you no longer want to receive notifications about "
21
    "this project, unsubscribe from the {}project{}."
22
)
23

24

25
class EmailAplus(Email):
1✔
26
    def get_languages(self, receiver):
1✔
27
        languages = super().get_languages(receiver)
×
28
        organisation = self.get_organisation()
×
29
        if User.objects.filter(email=receiver).exists():
×
30
            languages.insert(0, User.objects.get(email=receiver).language)
×
31
        elif organisation is not None:
×
32
            languages.insert(0, organisation.language)
×
33
        elif hasattr(settings, "DEFAULT_USER_LANGUAGE_CODE"):
×
34
            languages.insert(0, settings.DEFAULT_USER_LANGUAGE_CODE)
×
35

36
        return languages
×
37

38
    def get_receiver_language(self, receiver):
1✔
39
        return self.get_languages(receiver)[0]
×
40

41
    def get_context(self):
1✔
42
        context = super().get_context()
×
43
        context["organisation"] = self.get_organisation()
×
44
        return context
×
45

46
    def get_attachments(self):
1✔
47
        attachments = super().get_attachments()
×
48

49
        organisation = self.get_organisation()
×
50
        if organisation and organisation.logo:
×
51
            logo = None
×
52
            with open(organisation.logo.path, "rb") as f:
×
53
                data = f.read()
×
54
                try:
×
55
                    logo = MIMEImage(data)
×
56
                except TypeError:
×
57
                    capture_message(
×
58
                        "warning: MIMEImage failed to detect mime type:\n"
59
                        "organisation:"
60
                        + organisation.name
61
                        + "\nfile:"
62
                        + organisation.logo.path
63
                    )
64
                    mime_type = magic.from_buffer(data, mime=True)
×
65
                    logo = MIMEImage(data, _subtype=mime_type)
×
66
            if logo:
×
67
                logo.add_header("Content-ID", "<{}>".format("organisation_logo"))
×
68
                attachments += [logo]
×
69
            # need to remove standard email logo bc some email clients
70
            # display all attachments, even if not used
71
            attachments = [a for a in attachments if a["Content-Id"] != "<logo>"]
×
72

73
        return attachments
×
74

75
    def render(self, template_name, context):
1✔
76
        template = get_template(template_name + ".en.email")
×
77
        language = self.get_receiver_language(context["receiver"])
×
78
        with translation.override(language):
×
79
            context["account_link"] = self.get_html_link(
×
80
                ACCOUNT_LINK_TEXT, reverse("account")
81
            )
82
            if "action" in context:
×
83
                project = context["action"].project
×
84
                if project:
×
85
                    context["project_link"] = self.get_html_link(
×
86
                        PROJECT_LINK_TEXT, project.get_absolute_url()
87
                    )
88

89
            parts = []
×
90
            for part_type in ("subject", "txt", "html"):
×
91
                context["part_type"] = part_type
×
92
                parts.append(template.render(context))
×
93
                context.pop("part_type")
×
94
        return tuple(parts)
×
95

96
    def get_html_link(self, link_text, url):
1✔
97

98
        link = link_text.format(
×
99
            '<a href="' + self.get_host() + url + '" target="_blank">', "</a>"
100
        )
101
        return link
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc