Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions jdav_web/jdav_web/settings/components/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
"rules",
"jet",
"oauth2_provider",
"rest_framework",
"rest_framework.authtoken",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
Expand Down Expand Up @@ -207,3 +209,14 @@
ADMINS = get_var("section", "admins", default=[])

LOGIN_URL = "/de/kompass/login/"

# Django REST Framework
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
],
}
2 changes: 2 additions & 0 deletions jdav_web/jdav_web/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from django.views.generic.base import RedirectView
from oauth2_provider import urls as oauth2_urls

from members.api import email_forward_lookup
from .views import media_access

admin.site.index_title = _("Startpage")
Expand All @@ -47,6 +48,7 @@

urlpatterns += [
re_path(r"^markdownx/", include("markdownx.urls")),
path("api/email-forward/", email_forward_lookup, name="email-forward-lookup"),
]

handler404 = "startpage.views.handler404"
Expand Down
88 changes: 88 additions & 0 deletions jdav_web/members/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from django.contrib.auth.models import User
from rest_framework import serializers, status
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from mailer.models import EmailAddress
from members.models import Member


class EmailForwardSerializer(serializers.Serializer):
"""Serializer for email forwarding request"""
email = serializers.EmailField(required=True)


class EmailForwardResponseSerializer(serializers.Serializer):
"""Serializer for email forwarding response"""
forward_to = serializers.ListField(child=serializers.EmailField())


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def email_forward_lookup(request):
"""
API endpoint to lookup email forwarding addresses.

Given an email address (username@domain.com), returns a list of email addresses
that the incoming mail should be forwarded to based on two rules:

1. If username matches a logindata user's username, forward to the associated member's email
2. If username matches an EmailAddress, forward to all members and members in groups
specified in the to_members and to_groups fields

Request body:
{
"email": "username@domain.com"
}

Response:
{
"forward_to": ["email1@example.com", "email2@example.com"]
}
"""
serializer = EmailForwardSerializer(data=request.data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

email = serializer.validated_data['email']
# Extract username from email (part before @)
username = email.split('@')[0]

forward_addresses = set()

# Rule 1: Check if username matches a User
try:
user = User.objects.get(username=username)
# Get the associated member
if hasattr(user, 'member'):
member = user.member
if member.email:
forward_addresses.add(member.email)
except User.DoesNotExist:
pass

# Rule 2: Check if username matches an EmailAddress
try:
email_address = EmailAddress.objects.get(name=username)
# Get all members from to_members
for member in email_address.to_members.all():
if member.email:
forward_addresses.add(member.email)

# Get all members from groups in to_groups
for group in email_address.to_groups.all():
for member in group.member_set.all():
if member.email:
forward_addresses.add(member.email)
except EmailAddress.DoesNotExist:
pass

# Convert set to sorted list for consistent output
response_data = {
'forward_to': sorted(list(forward_addresses))
}

return Response(response_data, status=status.HTTP_200_OK)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ cryptography==44.0.2
Deprecated==1.2.13
Django==4.2.20
django-appconf==1.0.5
djangorestframework==3.15.2
django-celery-beat==2.5.0
django-celery-email==3.0.0
django-jet-reboot==1.3.10
Expand Down
Loading