Skip to content

Commit

Permalink
Add email.tlsname config option
Browse files Browse the repository at this point in the history
The existing `email.smtp_host` config option is used for two distinct
purposes: it is resolved into the IP address to connect to, and used to
(request via SNI and) validate the server's certificate if TLS is
enabled.  This new option allows specifying a different name for the
second purpose.

This is especially helpful, if `email.smtp_host` isn't a global FQDN,
but something that resolves only locally (e.g. "localhost" to connect
through the loopback interface, or some other internally routed name),
that one cannot get a valid certificate for.
  • Loading branch information
cynhr committed Oct 18, 2024
1 parent 9512b84 commit 9cc3545
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 3 deletions.
4 changes: 3 additions & 1 deletion docs/usage/configuration/config_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -673,8 +673,9 @@ This setting has the following sub-options:
TLS via STARTTLS *if the SMTP server supports it*. If this option is set,
Synapse will refuse to connect unless the server supports STARTTLS.
* `enable_tls`: By default, if the server supports TLS, it will be used, and the server
must present a certificate that is valid for 'smtp_host'. If this option
must present a certificate that is valid for `tlsname`. If this option
is set to false, TLS will not be used.
* `tlsname`: The domain name the SMTP server's TLS certificate must be valid for, defaulting to `smtp_host`.
* `notif_from`: defines the "From" address to use when sending emails.
It must be set if email sending is enabled. The placeholder '%(app)s' will be replaced by the application name,
which is normally set in `app_name`, but may be overridden by the
Expand Down Expand Up @@ -741,6 +742,7 @@ email:
force_tls: true
require_transport_security: true
enable_tls: false
tlsname: mail.server.example.com
notif_from: "Your Friendly %(app)s homeserver <noreply@example.com>"
app_name: my_branded_matrix_server
enable_notifs: true
Expand Down
1 change: 1 addition & 0 deletions synapse/config/emailconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
raise ConfigError(
"email.require_transport_security requires email.enable_tls to be true"
)
self.email_tlsname = email_config.get("tlsname", None)

if "app_name" in email_config:
self.email_app_name = email_config["app_name"]
Expand Down
11 changes: 9 additions & 2 deletions synapse/handlers/send_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ async def _sendmail(
require_tls: bool = False,
enable_tls: bool = True,
force_tls: bool = False,
tlsname: Optional[str] = None,
) -> None:
"""A simple wrapper around ESMTPSenderFactory, to allow substitution in tests
Expand All @@ -88,9 +89,13 @@ async def _sendmail(
enable_tls: True to enable STARTTLS. If this is False and require_tls is True,
the request will fail.
force_tls: True to enable Implicit TLS.
tlsname: the domain name expected as the TLS certificate's commonname,
defaults to smtphost.
"""
msg = BytesIO(msg_bytes)
d: "Deferred[object]" = Deferred()
if tlsname is None:
tlsname = smtphost

def build_sender_factory(**kwargs: Any) -> ESMTPSenderFactory:
return ESMTPSenderFactory(
Expand All @@ -117,10 +122,10 @@ def build_sender_factory(**kwargs: Any) -> ESMTPSenderFactory:
else:
# for twisted 21.2 and later, there is a 'hostname' parameter which we should
# set to enable TLS.
factory = build_sender_factory(hostname=smtphost if enable_tls else None)
factory = build_sender_factory(hostname=tlsname if enable_tls else None)

if force_tls:
factory = TLSMemoryBIOFactory(optionsForClientTLS(smtphost), True, factory)
factory = TLSMemoryBIOFactory(optionsForClientTLS(tlsname), True, factory)

endpoint = HostnameEndpoint(
reactor, smtphost, smtpport, timeout=30, bindAddress=None
Expand Down Expand Up @@ -148,6 +153,7 @@ def __init__(self, hs: "HomeServer"):
self._require_transport_security = hs.config.email.require_transport_security
self._enable_tls = hs.config.email.enable_smtp_tls
self._force_tls = hs.config.email.force_tls
self._tlsname = hs.config.email.email_tlsname

self._sendmail = _sendmail

Expand Down Expand Up @@ -227,4 +233,5 @@ async def send_email(
require_tls=self._require_transport_security,
enable_tls=self._enable_tls,
force_tls=self._force_tls,
tlsname=self._tlsname,
)

0 comments on commit 9cc3545

Please sign in to comment.