We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Email cannot be sent if CTF name has an accent
<!--
If this is a bug report please fill out the template below.

If this is a feature request please describe the behavior that you'd like to see.
-->

**Environment**:

  - CTFd Version/Commit: 2.3.2
  - Operating System: Debian 10.3, Python 3.7.3
  - Web Browser and Version: Firefox Nightly, 76.0a1 (2020-04-06)

**What happened?**

After a fresh install of CTFd we set the competition name to "Inté CTF". We configure the email server to use our Postfix relay, and test it with the "forgotten password" feature.
The email never arrives and is bounced by relay servers because the `From` header is invalid.

The actual issue is because the `From` header has the form "CTF name <email address>" (see [here](https://github.com/CTFd/CTFd/blob/master/CTFd/utils/email/smtp.py#L25)). Once encoded in the `msg.as_string()` ([there](https://github.com/CTFd/CTFd/blob/master/CTFd/utils/email/smtp.py#L55)) it is entirely encoded in UTF-8 looking like this `=?utf-8?q?Int=C3=A9_CTF_=3Cctf-noreply=40example=2Ecom=3E?=`, which is invalid against RFC 2407 section 5 ("An 'encoded-word' MUST NOT appear in any portion of an 'addr-spec'"). A correct form would be `=?utf-8?q?Int=C3=A9?= CTF <ctf-noreply@example.com>`.

I have a patch ready but it uses `from email.message import EmailMessage` which is available in Python 3.6+. I'll be happy to open a PR if you confirm me that support for lower Python version can be dropped ^^

<details>
<summary>Patch for `CTFd/utils/email/smtp.py`</summary>

```diff
-from email.mime.text import MIMEText
+from email.message import EmailMessage


# around line 50
-        msg = MIMEText(text)
+        msg = EmailMessage()
+        msg.set_content(text)
         msg["Subject"] = subject
         msg["From"] = mailfrom_addr
         msg["To"] = addr
 
-        smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())
+        smtp.send_message(msg)
```

</details>

**How to reproduce your issue**

- setup a new instance of CTFd
- configure the competition name with non-ascii characters
- configure the email server to use a "real" mail server (not Mailgun)
- try to send an email (with the "forgotten password" for example)
- see the mail server logs

<details>
<summary>
You can see the difference between both methods (`MIMEText` and `EmailMessage`) with the following snippet
</summary>

```python
from email.mime.text import MIMEText
msg = MIMEText("This is a message with accents éèçà")
msg["From"] = "René Côti <rene.coti@example.com>"
msg["To"] = "recipient@example.com"
msg.as_string()

from email.message import EmailMessage
msg = EmailMessage()
msg.set_content("This is a message with accents éèçà")
msg["From"] = "René Côti <rene.coti@example.com>"
msg["To"] = "recipient@example.com"
msg.as_string()
```

</details>

**Any associated stack traces or error logs**
```
# Sent to a gmail recipient
opendkim[839]: 278839FE69: can't parse From: header value ' =?utf-8?q?Int=C3=A9_CTF_=3Cctf-noreply=40example=2Ecom=3E?='
postfix/smtp[8076]: 278839FE69: to=<recipient@gmail.com>, relay=gmail-smtp-in.l.google.com[74.125.206.27]:25, delay=0.75, delays=0.31/0/0.23/0.21, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[74.125.206.27] said: 550-5.7.1 [185.132.74.134      14] Messages missing a valid address in From: 550 5.7.1 header, or having no From: header, are not accepted. p64si4801636wmp.124 - gsmtp (in reply to end of DATA command))

# Sent to another recipient, with another relay server
postfix/smtpd[7858]: NOQUEUE: reject: RCPT from mailcube2.domain.fr[193.51.52.6]: 550 5.1.1 <ctf-noreply@example.com>: Recipient address rejected: User unknown
 in virtual mailbox table; from=<> to=<ctf-noreply@example.com> proto=ESMTP helo=<mailcube2.domain.fr>
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `CTFd/utils/email/smtp.py`
Content:
```
1 import smtplib
2 from email.mime.text import MIMEText
3 from socket import timeout
4 
5 from CTFd.utils import get_app_config, get_config
6 
7 
8 def get_smtp(host, port, username=None, password=None, TLS=None, SSL=None, auth=None):
9     if SSL is None:
10         smtp = smtplib.SMTP(host, port, timeout=3)
11     else:
12         smtp = smtplib.SMTP_SSL(host, port, timeout=3)
13 
14     if TLS:
15         smtp.starttls()
16 
17     if auth:
18         smtp.login(username, password)
19     return smtp
20 
21 
22 def sendmail(addr, text, subject):
23     ctf_name = get_config("ctf_name")
24     mailfrom_addr = get_config("mailfrom_addr") or get_app_config("MAILFROM_ADDR")
25     mailfrom_addr = "{} <{}>".format(ctf_name, mailfrom_addr)
26 
27     data = {
28         "host": get_config("mail_server") or get_app_config("MAIL_SERVER"),
29         "port": int(get_config("mail_port") or get_app_config("MAIL_PORT")),
30     }
31     username = get_config("mail_username") or get_app_config("MAIL_USERNAME")
32     password = get_config("mail_password") or get_app_config("MAIL_PASSWORD")
33     TLS = get_config("mail_tls") or get_app_config("MAIL_TLS")
34     SSL = get_config("mail_ssl") or get_app_config("MAIL_SSL")
35     auth = get_config("mail_useauth") or get_app_config("MAIL_USEAUTH")
36 
37     if username:
38         data["username"] = username
39     if password:
40         data["password"] = password
41     if TLS:
42         data["TLS"] = TLS
43     if SSL:
44         data["SSL"] = SSL
45     if auth:
46         data["auth"] = auth
47 
48     try:
49         smtp = get_smtp(**data)
50         msg = MIMEText(text)
51         msg["Subject"] = subject
52         msg["From"] = mailfrom_addr
53         msg["To"] = addr
54 
55         smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())
56         smtp.quit()
57         return True, "Email sent"
58     except smtplib.SMTPException as e:
59         return False, str(e)
60     except timeout:
61         return False, "SMTP server connection timed out"
62     except Exception as e:
63         return False, str(e)
64
```

Path: `CTFd/utils/config/__init__.py`
Content:
```
1 import os
2 import time
3 
4 from flask import current_app as app
5 
6 from CTFd.utils import get_config
7 from CTFd.utils.modes import TEAMS_MODE, USERS_MODE
8 
9 
10 def ctf_name():
11     name = get_config("ctf_name")
12     return name if name else "CTFd"
13 
14 
15 def user_mode():
16     return get_config("user_mode")
17 
18 
19 def is_users_mode():
20     return user_mode() == USERS_MODE
21 
22 
23 def is_teams_mode():
24     return user_mode() == TEAMS_MODE
25 
26 
27 def ctf_logo():
28     return get_config("ctf_logo")
29 
30 
31 def ctf_theme():
32     theme = get_config("ctf_theme")
33     return theme if theme else ""
34 
35 
36 def is_setup():
37     return bool(get_config("setup")) is True
38 
39 
40 def is_scoreboard_frozen():
41     freeze = get_config("freeze")
42 
43     if freeze:
44         freeze = int(freeze)
45         if freeze < time.time():
46             return True
47 
48     return False
49 
50 
51 def can_send_mail():
52     return mailserver() or mailgun()
53 
54 
55 def get_mail_provider():
56     if app.config.get("MAIL_SERVER") and app.config.get("MAIL_PORT"):
57         return "smtp"
58     if get_config("mail_server") and get_config("mail_port"):
59         return "smtp"
60     if app.config.get("MAILGUN_API_KEY") and app.config.get("MAILGUN_BASE_URL"):
61         return "mailgun"
62     if get_config("mailgun_api_key") and get_config("mailgun_base_url"):
63         return "mailgun"
64 
65 
66 def mailgun():
67     if app.config.get("MAILGUN_API_KEY") and app.config.get("MAILGUN_BASE_URL"):
68         return True
69     if get_config("mailgun_api_key") and get_config("mailgun_base_url"):
70         return True
71     return False
72 
73 
74 def mailserver():
75     if app.config.get("MAIL_SERVER") and app.config.get("MAIL_PORT"):
76         return True
77     if get_config("mail_server") and get_config("mail_port"):
78         return True
79     return False
80 
81 
82 def get_themes():
83     dir = os.path.join(app.root_path, "themes")
84     return [
85         name
86         for name in os.listdir(dir)
87         if os.path.isdir(os.path.join(dir, name)) and name != "admin"
88     ]
89
```
--- 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/CTFd/utils/config/__init__.py b/CTFd/utils/config/__init__.py
--- a/CTFd/utils/config/__init__.py
+++ b/CTFd/utils/config/__init__.py
@@ -53,14 +53,14 @@
 
 
 def get_mail_provider():
-    if app.config.get("MAIL_SERVER") and app.config.get("MAIL_PORT"):
-        return "smtp"
     if get_config("mail_server") and get_config("mail_port"):
         return "smtp"
-    if app.config.get("MAILGUN_API_KEY") and app.config.get("MAILGUN_BASE_URL"):
-        return "mailgun"
     if get_config("mailgun_api_key") and get_config("mailgun_base_url"):
         return "mailgun"
+    if app.config.get("MAIL_SERVER") and app.config.get("MAIL_PORT"):
+        return "smtp"
+    if app.config.get("MAILGUN_API_KEY") and app.config.get("MAILGUN_BASE_URL"):
+        return "mailgun"
 
 
 def mailgun():
diff --git a/CTFd/utils/email/smtp.py b/CTFd/utils/email/smtp.py
--- a/CTFd/utils/email/smtp.py
+++ b/CTFd/utils/email/smtp.py
@@ -1,5 +1,9 @@
+import six
 import smtplib
 from email.mime.text import MIMEText
+
+if six.PY3:
+    from email.message import EmailMessage
 from socket import timeout
 
 from CTFd.utils import get_app_config, get_config
@@ -47,12 +51,22 @@
 
     try:
         smtp = get_smtp(**data)
-        msg = MIMEText(text)
+
+        if six.PY2:
+            msg = MIMEText(text)
+        else:
+            msg = EmailMessage()
+            msg.set_content(text)
+
         msg["Subject"] = subject
         msg["From"] = mailfrom_addr
         msg["To"] = addr
 
-        smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())
+        if six.PY2:
+            smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())
+        else:
+            smtp.send_message(msg)
+
         smtp.quit()
         return True, "Email sent"
     except smtplib.SMTPException as e:

{"golden_diff": "diff --git a/CTFd/utils/config/__init__.py b/CTFd/utils/config/__init__.py\n--- a/CTFd/utils/config/__init__.py\n+++ b/CTFd/utils/config/__init__.py\n@@ -53,14 +53,14 @@\n \n \n def get_mail_provider():\n-    if app.config.get(\"MAIL_SERVER\") and app.config.get(\"MAIL_PORT\"):\n-        return \"smtp\"\n     if get_config(\"mail_server\") and get_config(\"mail_port\"):\n         return \"smtp\"\n-    if app.config.get(\"MAILGUN_API_KEY\") and app.config.get(\"MAILGUN_BASE_URL\"):\n-        return \"mailgun\"\n     if get_config(\"mailgun_api_key\") and get_config(\"mailgun_base_url\"):\n         return \"mailgun\"\n+    if app.config.get(\"MAIL_SERVER\") and app.config.get(\"MAIL_PORT\"):\n+        return \"smtp\"\n+    if app.config.get(\"MAILGUN_API_KEY\") and app.config.get(\"MAILGUN_BASE_URL\"):\n+        return \"mailgun\"\n \n \n def mailgun():\ndiff --git a/CTFd/utils/email/smtp.py b/CTFd/utils/email/smtp.py\n--- a/CTFd/utils/email/smtp.py\n+++ b/CTFd/utils/email/smtp.py\n@@ -1,5 +1,9 @@\n+import six\n import smtplib\n from email.mime.text import MIMEText\n+\n+if six.PY3:\n+    from email.message import EmailMessage\n from socket import timeout\n \n from CTFd.utils import get_app_config, get_config\n@@ -47,12 +51,22 @@\n \n     try:\n         smtp = get_smtp(**data)\n-        msg = MIMEText(text)\n+\n+        if six.PY2:\n+            msg = MIMEText(text)\n+        else:\n+            msg = EmailMessage()\n+            msg.set_content(text)\n+\n         msg[\"Subject\"] = subject\n         msg[\"From\"] = mailfrom_addr\n         msg[\"To\"] = addr\n \n-        smtp.sendmail(msg[\"From\"], [msg[\"To\"]], msg.as_string())\n+        if six.PY2:\n+            smtp.sendmail(msg[\"From\"], [msg[\"To\"]], msg.as_string())\n+        else:\n+            smtp.send_message(msg)\n+\n         smtp.quit()\n         return True, \"Email sent\"\n     except smtplib.SMTPException as e:\n", "issue": "Email cannot be sent if CTF name has an accent\n<!--\r\nIf this is a bug report please fill out the template below.\r\n\r\nIf this is a feature request please describe the behavior that you'd like to see.\r\n-->\r\n\r\n**Environment**:\r\n\r\n  - CTFd Version/Commit: 2.3.2\r\n  - Operating System: Debian 10.3, Python 3.7.3\r\n  - Web Browser and Version: Firefox Nightly, 76.0a1 (2020-04-06)\r\n\r\n**What happened?**\r\n\r\nAfter a fresh install of CTFd we set the competition name to \"Int\u00e9 CTF\". We configure the email server to use our Postfix relay, and test it with the \"forgotten password\" feature.\r\nThe email never arrives and is bounced by relay servers because the `From` header is invalid.\r\n\r\nThe actual issue is because the `From` header has the form \"CTF name <email address>\" (see [here](https://github.com/CTFd/CTFd/blob/master/CTFd/utils/email/smtp.py#L25)). Once encoded in the `msg.as_string()` ([there](https://github.com/CTFd/CTFd/blob/master/CTFd/utils/email/smtp.py#L55)) it is entirely encoded in UTF-8 looking like this `=?utf-8?q?Int=C3=A9_CTF_=3Cctf-noreply=40example=2Ecom=3E?=`, which is invalid against RFC 2407 section 5 (\"An 'encoded-word' MUST NOT appear in any portion of an 'addr-spec'\"). A correct form would be `=?utf-8?q?Int=C3=A9?= CTF <ctf-noreply@example.com>`.\r\n\r\nI have a patch ready but it uses `from email.message import EmailMessage` which is available in Python 3.6+. I'll be happy to open a PR if you confirm me that support for lower Python version can be dropped ^^\r\n\r\n<details>\r\n<summary>Patch for `CTFd/utils/email/smtp.py`</summary>\r\n\r\n```diff\r\n-from email.mime.text import MIMEText\r\n+from email.message import EmailMessage\r\n\r\n\r\n# around line 50\r\n-        msg = MIMEText(text)\r\n+        msg = EmailMessage()\r\n+        msg.set_content(text)\r\n         msg[\"Subject\"] = subject\r\n         msg[\"From\"] = mailfrom_addr\r\n         msg[\"To\"] = addr\r\n \r\n-        smtp.sendmail(msg[\"From\"], [msg[\"To\"]], msg.as_string())\r\n+        smtp.send_message(msg)\r\n```\r\n\r\n</details>\r\n\r\n**How to reproduce your issue**\r\n\r\n- setup a new instance of CTFd\r\n- configure the competition name with non-ascii characters\r\n- configure the email server to use a \"real\" mail server (not Mailgun)\r\n- try to send an email (with the \"forgotten password\" for example)\r\n- see the mail server logs\r\n\r\n<details>\r\n<summary>\r\nYou can see the difference between both methods (`MIMEText` and `EmailMessage`) with the following snippet\r\n</summary>\r\n\r\n```python\r\nfrom email.mime.text import MIMEText\r\nmsg = MIMEText(\"This is a message with accents \u00e9\u00e8\u00e7\u00e0\")\r\nmsg[\"From\"] = \"Ren\u00e9 C\u00f4ti <rene.coti@example.com>\"\r\nmsg[\"To\"] = \"recipient@example.com\"\r\nmsg.as_string()\r\n\r\nfrom email.message import EmailMessage\r\nmsg = EmailMessage()\r\nmsg.set_content(\"This is a message with accents \u00e9\u00e8\u00e7\u00e0\")\r\nmsg[\"From\"] = \"Ren\u00e9 C\u00f4ti <rene.coti@example.com>\"\r\nmsg[\"To\"] = \"recipient@example.com\"\r\nmsg.as_string()\r\n```\r\n\r\n</details>\r\n\r\n**Any associated stack traces or error logs**\r\n```\r\n# Sent to a gmail recipient\r\nopendkim[839]: 278839FE69: can't parse From: header value ' =?utf-8?q?Int=C3=A9_CTF_=3Cctf-noreply=40example=2Ecom=3E?='\r\npostfix/smtp[8076]: 278839FE69: to=<recipient@gmail.com>, relay=gmail-smtp-in.l.google.com[74.125.206.27]:25, delay=0.75, delays=0.31/0/0.23/0.21, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[74.125.206.27] said: 550-5.7.1 [185.132.74.134      14] Messages missing a valid address in From: 550 5.7.1 header, or having no From: header, are not accepted. p64si4801636wmp.124 - gsmtp (in reply to end of DATA command))\r\n\r\n# Sent to another recipient, with another relay server\r\npostfix/smtpd[7858]: NOQUEUE: reject: RCPT from mailcube2.domain.fr[193.51.52.6]: 550 5.1.1 <ctf-noreply@example.com>: Recipient address rejected: User unknown\r\n in virtual mailbox table; from=<> to=<ctf-noreply@example.com> proto=ESMTP helo=<mailcube2.domain.fr>\r\n```\n", "before_files": [{"content": "import smtplib\nfrom email.mime.text import MIMEText\nfrom socket import timeout\n\nfrom CTFd.utils import get_app_config, get_config\n\n\ndef get_smtp(host, port, username=None, password=None, TLS=None, SSL=None, auth=None):\n    if SSL is None:\n        smtp = smtplib.SMTP(host, port, timeout=3)\n    else:\n        smtp = smtplib.SMTP_SSL(host, port, timeout=3)\n\n    if TLS:\n        smtp.starttls()\n\n    if auth:\n        smtp.login(username, password)\n    return smtp\n\n\ndef sendmail(addr, text, subject):\n    ctf_name = get_config(\"ctf_name\")\n    mailfrom_addr = get_config(\"mailfrom_addr\") or get_app_config(\"MAILFROM_ADDR\")\n    mailfrom_addr = \"{} <{}>\".format(ctf_name, mailfrom_addr)\n\n    data = {\n        \"host\": get_config(\"mail_server\") or get_app_config(\"MAIL_SERVER\"),\n        \"port\": int(get_config(\"mail_port\") or get_app_config(\"MAIL_PORT\")),\n    }\n    username = get_config(\"mail_username\") or get_app_config(\"MAIL_USERNAME\")\n    password = get_config(\"mail_password\") or get_app_config(\"MAIL_PASSWORD\")\n    TLS = get_config(\"mail_tls\") or get_app_config(\"MAIL_TLS\")\n    SSL = get_config(\"mail_ssl\") or get_app_config(\"MAIL_SSL\")\n    auth = get_config(\"mail_useauth\") or get_app_config(\"MAIL_USEAUTH\")\n\n    if username:\n        data[\"username\"] = username\n    if password:\n        data[\"password\"] = password\n    if TLS:\n        data[\"TLS\"] = TLS\n    if SSL:\n        data[\"SSL\"] = SSL\n    if auth:\n        data[\"auth\"] = auth\n\n    try:\n        smtp = get_smtp(**data)\n        msg = MIMEText(text)\n        msg[\"Subject\"] = subject\n        msg[\"From\"] = mailfrom_addr\n        msg[\"To\"] = addr\n\n        smtp.sendmail(msg[\"From\"], [msg[\"To\"]], msg.as_string())\n        smtp.quit()\n        return True, \"Email sent\"\n    except smtplib.SMTPException as e:\n        return False, str(e)\n    except timeout:\n        return False, \"SMTP server connection timed out\"\n    except Exception as e:\n        return False, str(e)\n", "path": "CTFd/utils/email/smtp.py"}, {"content": "import os\nimport time\n\nfrom flask import current_app as app\n\nfrom CTFd.utils import get_config\nfrom CTFd.utils.modes import TEAMS_MODE, USERS_MODE\n\n\ndef ctf_name():\n    name = get_config(\"ctf_name\")\n    return name if name else \"CTFd\"\n\n\ndef user_mode():\n    return get_config(\"user_mode\")\n\n\ndef is_users_mode():\n    return user_mode() == USERS_MODE\n\n\ndef is_teams_mode():\n    return user_mode() == TEAMS_MODE\n\n\ndef ctf_logo():\n    return get_config(\"ctf_logo\")\n\n\ndef ctf_theme():\n    theme = get_config(\"ctf_theme\")\n    return theme if theme else \"\"\n\n\ndef is_setup():\n    return bool(get_config(\"setup\")) is True\n\n\ndef is_scoreboard_frozen():\n    freeze = get_config(\"freeze\")\n\n    if freeze:\n        freeze = int(freeze)\n        if freeze < time.time():\n            return True\n\n    return False\n\n\ndef can_send_mail():\n    return mailserver() or mailgun()\n\n\ndef get_mail_provider():\n    if app.config.get(\"MAIL_SERVER\") and app.config.get(\"MAIL_PORT\"):\n        return \"smtp\"\n    if get_config(\"mail_server\") and get_config(\"mail_port\"):\n        return \"smtp\"\n    if app.config.get(\"MAILGUN_API_KEY\") and app.config.get(\"MAILGUN_BASE_URL\"):\n        return \"mailgun\"\n    if get_config(\"mailgun_api_key\") and get_config(\"mailgun_base_url\"):\n        return \"mailgun\"\n\n\ndef mailgun():\n    if app.config.get(\"MAILGUN_API_KEY\") and app.config.get(\"MAILGUN_BASE_URL\"):\n        return True\n    if get_config(\"mailgun_api_key\") and get_config(\"mailgun_base_url\"):\n        return True\n    return False\n\n\ndef mailserver():\n    if app.config.get(\"MAIL_SERVER\") and app.config.get(\"MAIL_PORT\"):\n        return True\n    if get_config(\"mail_server\") and get_config(\"mail_port\"):\n        return True\n    return False\n\n\ndef get_themes():\n    dir = os.path.join(app.root_path, \"themes\")\n    return [\n        name\n        for name in os.listdir(dir)\n        if os.path.isdir(os.path.join(dir, name)) and name != \"admin\"\n    ]\n", "path": "CTFd/utils/config/__init__.py"}], "after_files": [{"content": "import six\nimport smtplib\nfrom email.mime.text import MIMEText\n\nif six.PY3:\n    from email.message import EmailMessage\nfrom socket import timeout\n\nfrom CTFd.utils import get_app_config, get_config\n\n\ndef get_smtp(host, port, username=None, password=None, TLS=None, SSL=None, auth=None):\n    if SSL is None:\n        smtp = smtplib.SMTP(host, port, timeout=3)\n    else:\n        smtp = smtplib.SMTP_SSL(host, port, timeout=3)\n\n    if TLS:\n        smtp.starttls()\n\n    if auth:\n        smtp.login(username, password)\n    return smtp\n\n\ndef sendmail(addr, text, subject):\n    ctf_name = get_config(\"ctf_name\")\n    mailfrom_addr = get_config(\"mailfrom_addr\") or get_app_config(\"MAILFROM_ADDR\")\n    mailfrom_addr = \"{} <{}>\".format(ctf_name, mailfrom_addr)\n\n    data = {\n        \"host\": get_config(\"mail_server\") or get_app_config(\"MAIL_SERVER\"),\n        \"port\": int(get_config(\"mail_port\") or get_app_config(\"MAIL_PORT\")),\n    }\n    username = get_config(\"mail_username\") or get_app_config(\"MAIL_USERNAME\")\n    password = get_config(\"mail_password\") or get_app_config(\"MAIL_PASSWORD\")\n    TLS = get_config(\"mail_tls\") or get_app_config(\"MAIL_TLS\")\n    SSL = get_config(\"mail_ssl\") or get_app_config(\"MAIL_SSL\")\n    auth = get_config(\"mail_useauth\") or get_app_config(\"MAIL_USEAUTH\")\n\n    if username:\n        data[\"username\"] = username\n    if password:\n        data[\"password\"] = password\n    if TLS:\n        data[\"TLS\"] = TLS\n    if SSL:\n        data[\"SSL\"] = SSL\n    if auth:\n        data[\"auth\"] = auth\n\n    try:\n        smtp = get_smtp(**data)\n\n        if six.PY2:\n            msg = MIMEText(text)\n        else:\n            msg = EmailMessage()\n            msg.set_content(text)\n\n        msg[\"Subject\"] = subject\n        msg[\"From\"] = mailfrom_addr\n        msg[\"To\"] = addr\n\n        if six.PY2:\n            smtp.sendmail(msg[\"From\"], [msg[\"To\"]], msg.as_string())\n        else:\n            smtp.send_message(msg)\n\n        smtp.quit()\n        return True, \"Email sent\"\n    except smtplib.SMTPException as e:\n        return False, str(e)\n    except timeout:\n        return False, \"SMTP server connection timed out\"\n    except Exception as e:\n        return False, str(e)\n", "path": "CTFd/utils/email/smtp.py"}, {"content": "import os\nimport time\n\nfrom flask import current_app as app\n\nfrom CTFd.utils import get_config\nfrom CTFd.utils.modes import TEAMS_MODE, USERS_MODE\n\n\ndef ctf_name():\n    name = get_config(\"ctf_name\")\n    return name if name else \"CTFd\"\n\n\ndef user_mode():\n    return get_config(\"user_mode\")\n\n\ndef is_users_mode():\n    return user_mode() == USERS_MODE\n\n\ndef is_teams_mode():\n    return user_mode() == TEAMS_MODE\n\n\ndef ctf_logo():\n    return get_config(\"ctf_logo\")\n\n\ndef ctf_theme():\n    theme = get_config(\"ctf_theme\")\n    return theme if theme else \"\"\n\n\ndef is_setup():\n    return bool(get_config(\"setup\")) is True\n\n\ndef is_scoreboard_frozen():\n    freeze = get_config(\"freeze\")\n\n    if freeze:\n        freeze = int(freeze)\n        if freeze < time.time():\n            return True\n\n    return False\n\n\ndef can_send_mail():\n    return mailserver() or mailgun()\n\n\ndef get_mail_provider():\n    if get_config(\"mail_server\") and get_config(\"mail_port\"):\n        return \"smtp\"\n    if get_config(\"mailgun_api_key\") and get_config(\"mailgun_base_url\"):\n        return \"mailgun\"\n    if app.config.get(\"MAIL_SERVER\") and app.config.get(\"MAIL_PORT\"):\n        return \"smtp\"\n    if app.config.get(\"MAILGUN_API_KEY\") and app.config.get(\"MAILGUN_BASE_URL\"):\n        return \"mailgun\"\n\n\ndef mailgun():\n    if app.config.get(\"MAILGUN_API_KEY\") and app.config.get(\"MAILGUN_BASE_URL\"):\n        return True\n    if get_config(\"mailgun_api_key\") and get_config(\"mailgun_base_url\"):\n        return True\n    return False\n\n\ndef mailserver():\n    if app.config.get(\"MAIL_SERVER\") and app.config.get(\"MAIL_PORT\"):\n        return True\n    if get_config(\"mail_server\") and get_config(\"mail_port\"):\n        return True\n    return False\n\n\ndef get_themes():\n    dir = os.path.join(app.root_path, \"themes\")\n    return [\n        name\n        for name in os.listdir(dir)\n        if os.path.isdir(os.path.join(dir, name)) and name != \"admin\"\n    ]\n", "path": "CTFd/utils/config/__init__.py"}]}