We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Duplicate email to algorithm user that is also an editor when job fails
A tiny improvement request: When an algorithm job fails, the editors and the job creator are emailed (#1018), but there is apparently no check whether the job creator is one of the algorithm editor and would receive an email anyway - I was testing a new algorithm and always received two emails when a job failed.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `app/grandchallenge/algorithms/emails.py`
Content:
```
1 from django.conf import settings
2 from django.contrib.sites.models import Site
3 from django.core.mail import send_mail
4 
5 from grandchallenge.core.utils.email import send_templated_email
6 from grandchallenge.evaluation.templatetags.evaluation_extras import user_error
7 
8 
9 def send_permission_request_email(obj):
10     """
11     Emails the editors that someone has requested to view an algorithm.
12 
13     Parameters
14     ----------
15     obj:
16         AlgorithmPermissionRequest object containing info on which
17         user requested access to which algorithm.
18     """
19     title = f"[{obj.algorithm.title}] New access request"
20     kwargs = {
21         "user": obj.user,
22         "site": Site.objects.get_current(),
23         "algorithm": obj.algorithm,
24     }
25     for editor in obj.algorithm.editors_group.user_set.all():
26         kwargs["editor"] = editor
27         send_templated_email(
28             title,
29             "algorithms/emails/access_request.html",
30             kwargs,
31             [editor.email],
32         )
33 
34 
35 def send_permission_granted_email(obj):
36     """
37     Emails the requester that their request has been approved.
38 
39     Parameters
40     ----------
41     obj:
42         AlgorithmPermissionRequest object containing info on which
43         user requested access to which algorithm.
44     """
45     title = f"[{obj.algorithm.title}] Access granted"
46     kwargs = {
47         "user": obj.user,
48         "site": Site.objects.get_current(),
49         "algorithm": obj.algorithm,
50     }
51     send_templated_email(
52         title,
53         "algorithms/emails/access_granted.html",
54         kwargs,
55         [obj.user.email],
56     )
57 
58 
59 def send_permission_denied_email(obj):
60     """
61     Emails the requester that their request has been approved.
62 
63     Parameters
64     ----------
65     obj:
66         AlgorithmPermissionRequest object containing info on which
67         user requested access to which algorithm and optionally the
68         reason for rejection.
69     """
70     title = f"[{obj.algorithm.title}] Access denied"
71     kwargs = {
72         "user": obj.user,
73         "site": Site.objects.get_current(),
74         "algorithm": obj.algorithm,
75         "permission_request": obj,
76     }
77     send_templated_email(
78         title,
79         "algorithms/emails/access_denied.html",
80         kwargs,
81         [obj.user.email],
82     )
83 
84 
85 def send_failed_job_email(job):
86     algorithm = job.algorithm_image.algorithm
87     message = (
88         f"Unfortunately your job for algorithm "
89         f"'{algorithm.title}' failed with an error. "
90         f"The error message is:\n\n"
91         f"{user_error(job.output)}\n\n"
92         f"You may wish to try and correct this, or contact the challenge "
93         f"organizers. The following information may help them:\n"
94         f"User: {job.creator.username}\n"
95         f"Job ID: {job.pk}\n"
96         f"Submission ID: {job.pk}"
97     )
98     recipient_emails = [
99         o.email for o in algorithm.editors_group.user_set.all()
100     ]
101     recipient_emails.append(job.creator.email)
102     for email in recipient_emails:
103         send_mail(
104             subject=(
105                 f"[{Site.objects.get_current().domain.lower()}] "
106                 f"[{algorithm.title.lower()}] "
107                 f"Job Failed"
108             ),
109             message=message,
110             from_email=settings.DEFAULT_FROM_EMAIL,
111             recipient_list=[email],
112         )
113
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/app/grandchallenge/algorithms/emails.py b/app/grandchallenge/algorithms/emails.py
--- a/app/grandchallenge/algorithms/emails.py
+++ b/app/grandchallenge/algorithms/emails.py
@@ -99,7 +99,8 @@
         o.email for o in algorithm.editors_group.user_set.all()
     ]
     recipient_emails.append(job.creator.email)
-    for email in recipient_emails:
+
+    for email in {*recipient_emails}:
         send_mail(
             subject=(
                 f"[{Site.objects.get_current().domain.lower()}] "

{"golden_diff": "diff --git a/app/grandchallenge/algorithms/emails.py b/app/grandchallenge/algorithms/emails.py\n--- a/app/grandchallenge/algorithms/emails.py\n+++ b/app/grandchallenge/algorithms/emails.py\n@@ -99,7 +99,8 @@\n         o.email for o in algorithm.editors_group.user_set.all()\n     ]\n     recipient_emails.append(job.creator.email)\n-    for email in recipient_emails:\n+\n+    for email in {*recipient_emails}:\n         send_mail(\n             subject=(\n                 f\"[{Site.objects.get_current().domain.lower()}] \"\n", "issue": "Duplicate email to algorithm user that is also an editor when job fails\nA tiny improvement request: When an algorithm job fails, the editors and the job creator are emailed (#1018), but there is apparently no check whether the job creator is one of the algorithm editor and would receive an email anyway - I was testing a new algorithm and always received two emails when a job failed.\n", "before_files": [{"content": "from django.conf import settings\nfrom django.contrib.sites.models import Site\nfrom django.core.mail import send_mail\n\nfrom grandchallenge.core.utils.email import send_templated_email\nfrom grandchallenge.evaluation.templatetags.evaluation_extras import user_error\n\n\ndef send_permission_request_email(obj):\n    \"\"\"\n    Emails the editors that someone has requested to view an algorithm.\n\n    Parameters\n    ----------\n    obj:\n        AlgorithmPermissionRequest object containing info on which\n        user requested access to which algorithm.\n    \"\"\"\n    title = f\"[{obj.algorithm.title}] New access request\"\n    kwargs = {\n        \"user\": obj.user,\n        \"site\": Site.objects.get_current(),\n        \"algorithm\": obj.algorithm,\n    }\n    for editor in obj.algorithm.editors_group.user_set.all():\n        kwargs[\"editor\"] = editor\n        send_templated_email(\n            title,\n            \"algorithms/emails/access_request.html\",\n            kwargs,\n            [editor.email],\n        )\n\n\ndef send_permission_granted_email(obj):\n    \"\"\"\n    Emails the requester that their request has been approved.\n\n    Parameters\n    ----------\n    obj:\n        AlgorithmPermissionRequest object containing info on which\n        user requested access to which algorithm.\n    \"\"\"\n    title = f\"[{obj.algorithm.title}] Access granted\"\n    kwargs = {\n        \"user\": obj.user,\n        \"site\": Site.objects.get_current(),\n        \"algorithm\": obj.algorithm,\n    }\n    send_templated_email(\n        title,\n        \"algorithms/emails/access_granted.html\",\n        kwargs,\n        [obj.user.email],\n    )\n\n\ndef send_permission_denied_email(obj):\n    \"\"\"\n    Emails the requester that their request has been approved.\n\n    Parameters\n    ----------\n    obj:\n        AlgorithmPermissionRequest object containing info on which\n        user requested access to which algorithm and optionally the\n        reason for rejection.\n    \"\"\"\n    title = f\"[{obj.algorithm.title}] Access denied\"\n    kwargs = {\n        \"user\": obj.user,\n        \"site\": Site.objects.get_current(),\n        \"algorithm\": obj.algorithm,\n        \"permission_request\": obj,\n    }\n    send_templated_email(\n        title,\n        \"algorithms/emails/access_denied.html\",\n        kwargs,\n        [obj.user.email],\n    )\n\n\ndef send_failed_job_email(job):\n    algorithm = job.algorithm_image.algorithm\n    message = (\n        f\"Unfortunately your job for algorithm \"\n        f\"'{algorithm.title}' failed with an error. \"\n        f\"The error message is:\\n\\n\"\n        f\"{user_error(job.output)}\\n\\n\"\n        f\"You may wish to try and correct this, or contact the challenge \"\n        f\"organizers. The following information may help them:\\n\"\n        f\"User: {job.creator.username}\\n\"\n        f\"Job ID: {job.pk}\\n\"\n        f\"Submission ID: {job.pk}\"\n    )\n    recipient_emails = [\n        o.email for o in algorithm.editors_group.user_set.all()\n    ]\n    recipient_emails.append(job.creator.email)\n    for email in recipient_emails:\n        send_mail(\n            subject=(\n                f\"[{Site.objects.get_current().domain.lower()}] \"\n                f\"[{algorithm.title.lower()}] \"\n                f\"Job Failed\"\n            ),\n            message=message,\n            from_email=settings.DEFAULT_FROM_EMAIL,\n            recipient_list=[email],\n        )\n", "path": "app/grandchallenge/algorithms/emails.py"}], "after_files": [{"content": "from django.conf import settings\nfrom django.contrib.sites.models import Site\nfrom django.core.mail import send_mail\n\nfrom grandchallenge.core.utils.email import send_templated_email\nfrom grandchallenge.evaluation.templatetags.evaluation_extras import user_error\n\n\ndef send_permission_request_email(obj):\n    \"\"\"\n    Emails the editors that someone has requested to view an algorithm.\n\n    Parameters\n    ----------\n    obj:\n        AlgorithmPermissionRequest object containing info on which\n        user requested access to which algorithm.\n    \"\"\"\n    title = f\"[{obj.algorithm.title}] New access request\"\n    kwargs = {\n        \"user\": obj.user,\n        \"site\": Site.objects.get_current(),\n        \"algorithm\": obj.algorithm,\n    }\n    for editor in obj.algorithm.editors_group.user_set.all():\n        kwargs[\"editor\"] = editor\n        send_templated_email(\n            title,\n            \"algorithms/emails/access_request.html\",\n            kwargs,\n            [editor.email],\n        )\n\n\ndef send_permission_granted_email(obj):\n    \"\"\"\n    Emails the requester that their request has been approved.\n\n    Parameters\n    ----------\n    obj:\n        AlgorithmPermissionRequest object containing info on which\n        user requested access to which algorithm.\n    \"\"\"\n    title = f\"[{obj.algorithm.title}] Access granted\"\n    kwargs = {\n        \"user\": obj.user,\n        \"site\": Site.objects.get_current(),\n        \"algorithm\": obj.algorithm,\n    }\n    send_templated_email(\n        title,\n        \"algorithms/emails/access_granted.html\",\n        kwargs,\n        [obj.user.email],\n    )\n\n\ndef send_permission_denied_email(obj):\n    \"\"\"\n    Emails the requester that their request has been approved.\n\n    Parameters\n    ----------\n    obj:\n        AlgorithmPermissionRequest object containing info on which\n        user requested access to which algorithm and optionally the\n        reason for rejection.\n    \"\"\"\n    title = f\"[{obj.algorithm.title}] Access denied\"\n    kwargs = {\n        \"user\": obj.user,\n        \"site\": Site.objects.get_current(),\n        \"algorithm\": obj.algorithm,\n        \"permission_request\": obj,\n    }\n    send_templated_email(\n        title,\n        \"algorithms/emails/access_denied.html\",\n        kwargs,\n        [obj.user.email],\n    )\n\n\ndef send_failed_job_email(job):\n    algorithm = job.algorithm_image.algorithm\n    message = (\n        f\"Unfortunately your job for algorithm \"\n        f\"'{algorithm.title}' failed with an error. \"\n        f\"The error message is:\\n\\n\"\n        f\"{user_error(job.output)}\\n\\n\"\n        f\"You may wish to try and correct this, or contact the challenge \"\n        f\"organizers. The following information may help them:\\n\"\n        f\"User: {job.creator.username}\\n\"\n        f\"Job ID: {job.pk}\\n\"\n        f\"Submission ID: {job.pk}\"\n    )\n    recipient_emails = [\n        o.email for o in algorithm.editors_group.user_set.all()\n    ]\n    recipient_emails.append(job.creator.email)\n\n    for email in {*recipient_emails}:\n        send_mail(\n            subject=(\n                f\"[{Site.objects.get_current().domain.lower()}] \"\n                f\"[{algorithm.title.lower()}] \"\n                f\"Job Failed\"\n            ),\n            message=message,\n            from_email=settings.DEFAULT_FROM_EMAIL,\n            recipient_list=[email],\n        )\n", "path": "app/grandchallenge/algorithms/emails.py"}]}