Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for authentication using client TLS certificates #162

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
14 changes: 14 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ options (each is explained later in the documentation):

* **MAIL_USE_SSL** : default **False**

* **MAIL_CLIENT_CERT** : default **None**

* **MAIL_CLIENT_KEY** : default **None**

* **MAIL_DEBUG** : default **app.debug**

* **MAIL_USERNAME** : default **None**
Expand Down Expand Up @@ -173,6 +177,16 @@ should be fine for any unicode character that can be decomposed by NFKD into one
or more ASCII characters. If you need romanization/transliteration (i.e `ß` →
`ss`) then your application should do it and pass a proper ASCII string.

Client certificate authentication
---------------------------------

In some situations it may be desirable for the mail sender to present a client TLS
certificate to the mail relay, for an extra layer of authentication beyond that provided
by a username and password. In this case, you should set the configuration variables
``MAIL_CLIENT_CERT`` and ``MAIL_CLIENT_KEY`` to the paths to your certificate and private
key, respectively, which will then be loaded when establishing a TLS connection (i.e. when
the ``MAIL_USE_TLS`` or ``MAIL_USE_SSL`` variables are set to **True**) with the mail
relay.

Unit tests and suppressing emails
---------------------------------
Expand Down
19 changes: 15 additions & 4 deletions flask_mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,22 @@ def __exit__(self, exc_type, exc_value, tb):
self.host.quit()

def configure_host(self):
client_cert = None
client_key = None

if self.mail.client_cert and self.mail.client_key:
client_cert = self.mail.client_cert
client_key = self.mail.client_key

if self.mail.use_ssl:
host = smtplib.SMTP_SSL(self.mail.server, self.mail.port)
host = smtplib.SMTP_SSL(self.mail.server, self.mail.port, certfile=client_cert, keyfile=client_key)
else:
host = smtplib.SMTP(self.mail.server, self.mail.port)

host.set_debuglevel(int(self.mail.debug))

if self.mail.use_tls:
host.starttls()
host.starttls(certfile=client_cert, keyfile=client_key)
if self.mail.username and self.mail.password:
host.login(self.mail.username, self.mail.password)

Expand Down Expand Up @@ -527,14 +534,16 @@ def connect(self):

class _Mail(_MailMixin):
def __init__(self, server, username, password, port, use_tls, use_ssl,
default_sender, debug, max_emails, suppress,
ascii_attachments=False):
client_cert, client_key, default_sender, debug, max_emails,
suppress, ascii_attachments=False):
self.server = server
self.username = username
self.password = password
self.port = port
self.use_tls = use_tls
self.use_ssl = use_ssl
self.client_cert = client_cert
self.client_key = client_key
self.default_sender = default_sender
self.debug = debug
self.max_emails = max_emails
Expand Down Expand Up @@ -563,6 +572,8 @@ def init_mail(self, config, debug=False, testing=False):
config.get('MAIL_PORT', 25),
config.get('MAIL_USE_TLS', False),
config.get('MAIL_USE_SSL', False),
config.get('MAIL_CLIENT_CERT'),
config.get('MAIL_CLIENT_KEY'),
config.get('MAIL_DEFAULT_SENDER'),
int(config.get('MAIL_DEBUG', debug)),
config.get('MAIL_MAX_EMAILS'),
Expand Down