Files
colio/mail/views.py
2026-01-12 23:13:22 +09:00

113 lines
4.0 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import re
import subprocess
from django.conf import settings
from django.shortcuts import render
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import NotFound
LOCAL_RE = re.compile(r"^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$")
def _require_enabled():
# settings.py에 MAIL_SIGNUP_ENABLED 토글이 있으면 사용
if not getattr(settings, "MAIL_SIGNUP_ENABLED", False):
raise NotFound("Not Found") # 숨김(404)
def _run_setup(cmd_args):
"""
./setup.sh -c dms-mailserver email add|list ...
"""
setup_sh = getattr(settings, "MAIL_SETUP_SH", None) or os.getenv("MAIL_SETUP_SH", "./setup.sh")
workdir = getattr(settings, "MAIL_SETUP_WORKDIR", None) or os.getenv("MAIL_SETUP_WORKDIR", os.getcwd())
container = getattr(settings, "MAIL_DMS_CONTAINER", None) or os.getenv("MAIL_DMS_CONTAINER", "dms-mailserver")
if not os.path.exists(setup_sh):
raise RuntimeError(f"setup.sh not found: {setup_sh}")
full = [setup_sh, "-c", container] + cmd_args
p = subprocess.run(full, cwd=workdir, capture_output=True, text=True)
out = (p.stdout or "").strip()
err = (p.stderr or "").strip()
if p.returncode != 0:
raise ValueError(err or out or "setup.sh failed")
return out
def _email_list():
out = _run_setup(["email", "list"])
return [ln.strip() for ln in out.splitlines() if ln.strip()]
def signup_page(request):
_require_enabled()
return render(request, "mail/signup.html")
@api_view(["POST"])
@permission_classes([AllowAny])
def request_account(request):
_require_enabled()
invite_expected = getattr(settings, "MAIL_INVITE_CODE", None) or os.getenv("MAIL_INVITE_CODE", "")
dms_domain = getattr(settings, "MAIL_DMS_DOMAIN", None) or os.getenv("MAIL_DMS_DOMAIN", "")
local = (request.data.get("local") or "").strip().lower()
password = request.data.get("password") or ""
invite = (request.data.get("invite") or "").strip()
if not invite_expected or invite != invite_expected:
return Response({"detail": "초대코드가 올바르지 않습니다."}, status=status.HTTP_403_FORBIDDEN)
if not dms_domain:
return Response({"detail": "서버 설정(MAIL_DMS_DOMAIN)이 비어있습니다."},
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if not LOCAL_RE.match(local):
return Response({"detail": "아이디 형식이 올바르지 않습니다. (영문소문자/숫자/._- 허용)"},
status=status.HTTP_400_BAD_REQUEST)
if len(password) < 10:
return Response({"detail": "비밀번호는 10자 이상으로 설정하세요."},
status=status.HTTP_400_BAD_REQUEST)
address = f"{local}@{dms_domain}"
try:
emails = _email_list()
if address in emails:
return Response({"message": f" {address} 는 이미 존재합니다. (email list에서 확인됨)"})
_run_setup(["email", "add", address, password])
emails2 = _email_list()
if address in emails2:
return Response({"message": f"{address} 계정이 잘 만들어졌습니다! (email list에서 확인됨)"})
return Response({"detail": "계정 생성 후 list에서 확인이 안 됩니다."},
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
except ValueError as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return Response({"detail": f"서버 오류: {e}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(["GET"])
@permission_classes([IsAdminUser])
def admin_list(request):
_require_enabled()
try:
emails = _email_list()
return Response({"count": len(emails), "emails": emails})
except Exception as e:
return Response({"detail": f"서버 오류: {e}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)