# Copyright 2024 UW-IT, University of Washington
# SPDX-License-Identifier: Apache-2.0


from django.core.mail import EmailMultiAlternatives
from django.test import TestCase
from saferecipient import EmailBackend
import ssl


class TestEmailBackend(TestCase):
    SAFE_EMAIL = 'safe@example.com'

    def test_ssl_context(self):
        backend = EmailBackend()
        ssl_context = backend.ssl_context
        self.assertFalse(ssl_context.check_hostname)
        self.assertEqual(ssl_context.verify_mode, ssl.CERT_NONE)

    def test_safeguard(self):
        with self.settings(SAFE_EMAIL_RECIPIENT=self.SAFE_EMAIL):
            message = self._setup_message()
            EmailBackend()._safeguard(message)
            self.assertEqual(message.from_email, 'safe@example.com')
            self.assertEqual(message.to, ['safe@example.com'])
            self.assertEqual(message.cc, ['safe@example.com'])
            self.assertEqual(
                message.attachments[0].get_payload(),
                ("Original From: sender@example.com\nOriginal To: "
                 "['recipient@example.com']\nOriginal CC: "
                 "['cc_recipient@example.com']\nOriginal BCC: []\n"))

    def test_safeguard_with_safelist(self):
        with self.settings(SAFE_EMAIL_RECIPIENT=self.SAFE_EMAIL), \
             self.settings(SAFE_EMAIL_SAFELIST=[r".*@example\.com",
                                                r"safe.*@example\.org"]):
            message = self._setup_message(from_email='sender@example.com',
                                          to=['recipient@example.com'],
                                          cc=["safe+safe@example.org"],
                                          bcc=["unsafe@example.net"])
            EmailBackend()._safeguard(message)
            self.assertEqual(message.from_email, 'sender@example.com')
            self.assertEqual(message.to, ['recipient@example.com'])
            self.assertEqual(message.cc, ["safe+safe@example.org"])
            self.assertEqual(message.attachments[0].get_payload(),
                             ("Original From: sender@example.com\n"
                              "Original To: ['recipient@example.com']\n"
                              "Original CC: ['safe+safe@example.org']\n"
                              "Original BCC: ['unsafe@example.net']\n"))

    def test_no_setting(self):
        message = self._setup_message()
        self.assertRaises(
            AttributeError, EmailBackend()._safeguard, message)

    def test_only_safe_emails(self):
        with self.settings(SAFE_EMAIL_RECIPIENT=self.SAFE_EMAIL), \
             self.settings(SAFE_EMAIL_SAFELIST=[r".*@example\.com",
                                                r"safe.*@example\.org"]):
            eb = EmailBackend()
            self.assertEqual(([], False), eb._only_safe_emails([]))
            self.assertEqual(([self.SAFE_EMAIL], True),
                             eb._only_safe_emails(["unsafe@example.org"]))
            self.assertEqual(([self.SAFE_EMAIL], True),
                             eb._only_safe_emails(["unsafe@example.org",
                                                   "unsafe2@example.org"]))
            self.assertEqual(([self.SAFE_EMAIL], True),
                             eb._only_safe_emails([self.SAFE_EMAIL,
                                                   "unsafe@example.org",
                                                   "unsafe2@example.org"]))
            self.assertEqual((["safe+2@example.com", self.SAFE_EMAIL], True),
                             eb._only_safe_emails(["safe+2@example.com",
                                                   self.SAFE_EMAIL,
                                                   "unsafe@example.org",
                                                   "unsafe2@example.org"]))
            self.assertEqual((["safe+2@example.com",
                               self.SAFE_EMAIL,
                               "safe@example.org"],
                              True),
                             eb._only_safe_emails(["safe+2@example.com",
                                                   self.SAFE_EMAIL,
                                                   "unsafe@example.org",
                                                   "unsafe2@example.org",
                                                   "safe@example.org"]))

    def test_safelist(self):
        with self.settings(SAFE_EMAIL_SAFELIST=[r".*@example\.com",
                                                r"safe.*@example\.org"]):
            eb = EmailBackend()
            self.assertTrue(eb._is_safelisted("example@example.com"))
            self.assertTrue(eb._is_safelisted("example2@example.com"))
            self.assertTrue(eb._is_safelisted("safe@example.org"))
            self.assertTrue(eb._is_safelisted("safe+2@example.org"))
            self.assertFalse(eb._is_safelisted("unsafe@example.org"))

    def _setup_message(self, from_email='sender@example.com', to=None,
                       cc=None, bcc=None):
        if to is None:
            to = ['recipient@example.com']
        if cc is None:
            cc = ['cc_recipient@example.com']
        if bcc is None:
            bcc = []
        return EmailMultiAlternatives(from_email=from_email, to=to, cc=cc,
                                      bcc=bcc, subject='test', body='TEST')
