We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Broken link on weekly mails
The link used to unsubscribe from the mail is broken, because `frontend_url` is undefined. Probably due to the weekly mails being handled differently than all other notifications.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lego/apps/email/tasks.py`
Content:
```
1 from datetime import timedelta
2 
3 from django.conf import settings
4 from django.template.loader import render_to_string
5 from django.utils import timezone
6 
7 from premailer import transform
8 from structlog import get_logger
9 
10 from lego import celery_app
11 from lego.apps.events.constants import EVENT_TYPE_TRANSLATIONS
12 from lego.apps.events.models import Event
13 from lego.apps.joblistings.constants import JOB_TYPE_TRANSLATIONS
14 from lego.apps.joblistings.models import Joblisting
15 from lego.apps.notifications.constants import EMAIL, WEEKLY_MAIL
16 from lego.apps.notifications.models import NotificationSetting
17 from lego.apps.permissions.utils import get_permission_handler
18 from lego.apps.restricted.message_processor import MessageProcessor
19 from lego.apps.tags.models import Tag
20 from lego.apps.users.models import AbakusGroup
21 from lego.utils.tasks import AbakusTask
22 
23 log = get_logger()
24 
25 
26 def create_weekly_mail(user):
27     three_days_ago_timestamp = timezone.now() - timedelta(days=3)
28     last_sunday_timestamp = timezone.now() - timedelta(days=7)
29 
30     weekly_tag = Tag.objects.filter(tag="weekly").first()
31     # Check if weekly tag exists so it does not crash if some idiot deletes the weekly tag
32     todays_weekly = (
33         weekly_tag.article_set.filter(created_at__gt=three_days_ago_timestamp).first()
34         if weekly_tag
35         else None
36     )
37 
38     events_next_week = Event.objects.filter(
39         pools__activation_date__gt=timezone.now(),
40         pools__activation_date__lt=timezone.now() + timedelta(days=7),
41     ).distinct()
42 
43     permission_handler = get_permission_handler(events_next_week.model)
44     filtered_events = permission_handler.filter_queryset(user, events_next_week)
45 
46     filtered_events = filter(
47         lambda event: event.get_possible_pools(user, True) or event.is_admitted(user),
48         filtered_events,
49     )
50 
51     joblistings_last_week = Joblisting.objects.filter(
52         created_at__gt=last_sunday_timestamp, visible_from__lt=timezone.now()
53     )
54 
55     joblistings = []
56     for joblisting in joblistings_last_week:
57         joblistings.append(
58             {
59                 "id": joblisting.id,
60                 "company_name": joblisting.company.name,
61                 "type": JOB_TYPE_TRANSLATIONS[joblisting.job_type],
62                 "title": joblisting.title,
63             }
64         )
65 
66     events = []
67     for event in filtered_events:
68         pools = []
69         for pool in event.pools.all():
70             pools.append(
71                 {
72                     "name": pool.name,
73                     "activation_date": pool.activation_date.strftime("%d/%m kl. %H:%M"),
74                 }
75             )
76 
77         events.append(
78             {
79                 "title": event.title,
80                 "id": event.id,
81                 "pools": pools,
82                 "start_time": event.start_time.strftime("%d/%m kl %H:%M"),
83                 "url": event.get_absolute_url(),
84                 "type": EVENT_TYPE_TRANSLATIONS[event.event_type],
85             }
86         )
87 
88     html_body = render_to_string(
89         "email/email/weekly_mail.html",
90         {
91             "events": events,
92             "todays_weekly": ""
93             if todays_weekly is None
94             else todays_weekly.get_absolute_url(),
95             "joblistings": joblistings,
96         },
97     )
98     if events or joblistings or todays_weekly:
99         return html_body
100     return None
101 
102 
103 @celery_app.task(serializer="json", bind=True, base=AbakusTask)
104 def send_weekly_email(self, logger_context=None):
105     self.setup_logger(logger_context)
106 
107     week_number = timezone.now().isocalendar().week
108 
109     # Set to just PR and Webkom for testing purposes
110     all_users = set(
111         AbakusGroup.objects.get(name="Webkom").restricted_lookup()[0]
112         + AbakusGroup.objects.get(name="PR").restricted_lookup()[0]
113     )
114     recipients = []
115 
116     for user in all_users:
117         if not user.email_lists_enabled:
118             # Don't send emails to users that don't want mail.
119             continue
120 
121         if EMAIL not in NotificationSetting.active_channels(user, WEEKLY_MAIL):
122             continue
123         recipients.append(user)
124 
125     datatuple = (
126         (
127             f"Ukesmail uke {week_number}",
128             transform(html) if (html := create_weekly_mail(user)) is not None else None,
129             settings.DEFAULT_FROM_EMAIL,
130             [user.email],
131         )
132         for user in recipients
133     )
134     datatuple = tuple(tuppel for tuppel in datatuple if tuppel[1] is not None)
135     if datatuple:
136         MessageProcessor.send_mass_mail_html(datatuple)
137
```
--- 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/lego/apps/email/tasks.py b/lego/apps/email/tasks.py
--- a/lego/apps/email/tasks.py
+++ b/lego/apps/email/tasks.py
@@ -93,6 +93,7 @@
             if todays_weekly is None
             else todays_weekly.get_absolute_url(),
             "joblistings": joblistings,
+            "frontend_url": settings.FRONTEND_URL,
         },
     )
     if events or joblistings or todays_weekly:

{"golden_diff": "diff --git a/lego/apps/email/tasks.py b/lego/apps/email/tasks.py\n--- a/lego/apps/email/tasks.py\n+++ b/lego/apps/email/tasks.py\n@@ -93,6 +93,7 @@\n             if todays_weekly is None\n             else todays_weekly.get_absolute_url(),\n             \"joblistings\": joblistings,\n+            \"frontend_url\": settings.FRONTEND_URL,\n         },\n     )\n     if events or joblistings or todays_weekly:\n", "issue": "Broken link on weekly mails\nThe link used to unsubscribe from the mail is broken, because `frontend_url` is undefined. Probably due to the weekly mails being handled differently than all other notifications.\n", "before_files": [{"content": "from datetime import timedelta\n\nfrom django.conf import settings\nfrom django.template.loader import render_to_string\nfrom django.utils import timezone\n\nfrom premailer import transform\nfrom structlog import get_logger\n\nfrom lego import celery_app\nfrom lego.apps.events.constants import EVENT_TYPE_TRANSLATIONS\nfrom lego.apps.events.models import Event\nfrom lego.apps.joblistings.constants import JOB_TYPE_TRANSLATIONS\nfrom lego.apps.joblistings.models import Joblisting\nfrom lego.apps.notifications.constants import EMAIL, WEEKLY_MAIL\nfrom lego.apps.notifications.models import NotificationSetting\nfrom lego.apps.permissions.utils import get_permission_handler\nfrom lego.apps.restricted.message_processor import MessageProcessor\nfrom lego.apps.tags.models import Tag\nfrom lego.apps.users.models import AbakusGroup\nfrom lego.utils.tasks import AbakusTask\n\nlog = get_logger()\n\n\ndef create_weekly_mail(user):\n    three_days_ago_timestamp = timezone.now() - timedelta(days=3)\n    last_sunday_timestamp = timezone.now() - timedelta(days=7)\n\n    weekly_tag = Tag.objects.filter(tag=\"weekly\").first()\n    # Check if weekly tag exists so it does not crash if some idiot deletes the weekly tag\n    todays_weekly = (\n        weekly_tag.article_set.filter(created_at__gt=three_days_ago_timestamp).first()\n        if weekly_tag\n        else None\n    )\n\n    events_next_week = Event.objects.filter(\n        pools__activation_date__gt=timezone.now(),\n        pools__activation_date__lt=timezone.now() + timedelta(days=7),\n    ).distinct()\n\n    permission_handler = get_permission_handler(events_next_week.model)\n    filtered_events = permission_handler.filter_queryset(user, events_next_week)\n\n    filtered_events = filter(\n        lambda event: event.get_possible_pools(user, True) or event.is_admitted(user),\n        filtered_events,\n    )\n\n    joblistings_last_week = Joblisting.objects.filter(\n        created_at__gt=last_sunday_timestamp, visible_from__lt=timezone.now()\n    )\n\n    joblistings = []\n    for joblisting in joblistings_last_week:\n        joblistings.append(\n            {\n                \"id\": joblisting.id,\n                \"company_name\": joblisting.company.name,\n                \"type\": JOB_TYPE_TRANSLATIONS[joblisting.job_type],\n                \"title\": joblisting.title,\n            }\n        )\n\n    events = []\n    for event in filtered_events:\n        pools = []\n        for pool in event.pools.all():\n            pools.append(\n                {\n                    \"name\": pool.name,\n                    \"activation_date\": pool.activation_date.strftime(\"%d/%m kl. %H:%M\"),\n                }\n            )\n\n        events.append(\n            {\n                \"title\": event.title,\n                \"id\": event.id,\n                \"pools\": pools,\n                \"start_time\": event.start_time.strftime(\"%d/%m kl %H:%M\"),\n                \"url\": event.get_absolute_url(),\n                \"type\": EVENT_TYPE_TRANSLATIONS[event.event_type],\n            }\n        )\n\n    html_body = render_to_string(\n        \"email/email/weekly_mail.html\",\n        {\n            \"events\": events,\n            \"todays_weekly\": \"\"\n            if todays_weekly is None\n            else todays_weekly.get_absolute_url(),\n            \"joblistings\": joblistings,\n        },\n    )\n    if events or joblistings or todays_weekly:\n        return html_body\n    return None\n\n\n@celery_app.task(serializer=\"json\", bind=True, base=AbakusTask)\ndef send_weekly_email(self, logger_context=None):\n    self.setup_logger(logger_context)\n\n    week_number = timezone.now().isocalendar().week\n\n    # Set to just PR and Webkom for testing purposes\n    all_users = set(\n        AbakusGroup.objects.get(name=\"Webkom\").restricted_lookup()[0]\n        + AbakusGroup.objects.get(name=\"PR\").restricted_lookup()[0]\n    )\n    recipients = []\n\n    for user in all_users:\n        if not user.email_lists_enabled:\n            # Don't send emails to users that don't want mail.\n            continue\n\n        if EMAIL not in NotificationSetting.active_channels(user, WEEKLY_MAIL):\n            continue\n        recipients.append(user)\n\n    datatuple = (\n        (\n            f\"Ukesmail uke {week_number}\",\n            transform(html) if (html := create_weekly_mail(user)) is not None else None,\n            settings.DEFAULT_FROM_EMAIL,\n            [user.email],\n        )\n        for user in recipients\n    )\n    datatuple = tuple(tuppel for tuppel in datatuple if tuppel[1] is not None)\n    if datatuple:\n        MessageProcessor.send_mass_mail_html(datatuple)\n", "path": "lego/apps/email/tasks.py"}], "after_files": [{"content": "from datetime import timedelta\n\nfrom django.conf import settings\nfrom django.template.loader import render_to_string\nfrom django.utils import timezone\n\nfrom premailer import transform\nfrom structlog import get_logger\n\nfrom lego import celery_app\nfrom lego.apps.events.constants import EVENT_TYPE_TRANSLATIONS\nfrom lego.apps.events.models import Event\nfrom lego.apps.joblistings.constants import JOB_TYPE_TRANSLATIONS\nfrom lego.apps.joblistings.models import Joblisting\nfrom lego.apps.notifications.constants import EMAIL, WEEKLY_MAIL\nfrom lego.apps.notifications.models import NotificationSetting\nfrom lego.apps.permissions.utils import get_permission_handler\nfrom lego.apps.restricted.message_processor import MessageProcessor\nfrom lego.apps.tags.models import Tag\nfrom lego.apps.users.models import AbakusGroup\nfrom lego.utils.tasks import AbakusTask\n\nlog = get_logger()\n\n\ndef create_weekly_mail(user):\n    three_days_ago_timestamp = timezone.now() - timedelta(days=3)\n    last_sunday_timestamp = timezone.now() - timedelta(days=7)\n\n    weekly_tag = Tag.objects.filter(tag=\"weekly\").first()\n    # Check if weekly tag exists so it does not crash if some idiot deletes the weekly tag\n    todays_weekly = (\n        weekly_tag.article_set.filter(created_at__gt=three_days_ago_timestamp).first()\n        if weekly_tag\n        else None\n    )\n\n    events_next_week = Event.objects.filter(\n        pools__activation_date__gt=timezone.now(),\n        pools__activation_date__lt=timezone.now() + timedelta(days=7),\n    ).distinct()\n\n    permission_handler = get_permission_handler(events_next_week.model)\n    filtered_events = permission_handler.filter_queryset(user, events_next_week)\n\n    filtered_events = filter(\n        lambda event: event.get_possible_pools(user, True) or event.is_admitted(user),\n        filtered_events,\n    )\n\n    joblistings_last_week = Joblisting.objects.filter(\n        created_at__gt=last_sunday_timestamp, visible_from__lt=timezone.now()\n    )\n\n    joblistings = []\n    for joblisting in joblistings_last_week:\n        joblistings.append(\n            {\n                \"id\": joblisting.id,\n                \"company_name\": joblisting.company.name,\n                \"type\": JOB_TYPE_TRANSLATIONS[joblisting.job_type],\n                \"title\": joblisting.title,\n            }\n        )\n\n    events = []\n    for event in filtered_events:\n        pools = []\n        for pool in event.pools.all():\n            pools.append(\n                {\n                    \"name\": pool.name,\n                    \"activation_date\": pool.activation_date.strftime(\"%d/%m kl. %H:%M\"),\n                }\n            )\n\n        events.append(\n            {\n                \"title\": event.title,\n                \"id\": event.id,\n                \"pools\": pools,\n                \"start_time\": event.start_time.strftime(\"%d/%m kl %H:%M\"),\n                \"url\": event.get_absolute_url(),\n                \"type\": EVENT_TYPE_TRANSLATIONS[event.event_type],\n            }\n        )\n\n    html_body = render_to_string(\n        \"email/email/weekly_mail.html\",\n        {\n            \"events\": events,\n            \"todays_weekly\": \"\"\n            if todays_weekly is None\n            else todays_weekly.get_absolute_url(),\n            \"joblistings\": joblistings,\n            \"frontend_url\": settings.FRONTEND_URL,\n        },\n    )\n    if events or joblistings or todays_weekly:\n        return html_body\n    return None\n\n\n@celery_app.task(serializer=\"json\", bind=True, base=AbakusTask)\ndef send_weekly_email(self, logger_context=None):\n    self.setup_logger(logger_context)\n\n    week_number = timezone.now().isocalendar().week\n\n    # Set to just PR and Webkom for testing purposes\n    all_users = set(\n        AbakusGroup.objects.get(name=\"Webkom\").restricted_lookup()[0]\n        + AbakusGroup.objects.get(name=\"PR\").restricted_lookup()[0]\n    )\n    recipients = []\n\n    for user in all_users:\n        if not user.email_lists_enabled:\n            # Don't send emails to users that don't want mail.\n            continue\n\n        if EMAIL not in NotificationSetting.active_channels(user, WEEKLY_MAIL):\n            continue\n        recipients.append(user)\n\n    datatuple = (\n        (\n            f\"Ukesmail uke {week_number}\",\n            transform(html) if (html := create_weekly_mail(user)) is not None else None,\n            settings.DEFAULT_FROM_EMAIL,\n            [user.email],\n        )\n        for user in recipients\n    )\n    datatuple = tuple(tuppel for tuppel in datatuple if tuppel[1] is not None)\n    if datatuple:\n        MessageProcessor.send_mass_mail_html(datatuple)\n", "path": "lego/apps/email/tasks.py"}]}