diff --git a/changelog.d/17849.feature b/changelog.d/17849.feature
new file mode 100644
index 0000000000000000000000000000000000000000..4de580f9edb62b6090e4c46266f862653a643df3
--- /dev/null
+++ b/changelog.d/17849.feature
@@ -0,0 +1 @@
+Added the `email.tlsname` config option.  This allows specifying the domain name used to validate the SMTP server's TLS certificate separately from the `email.smtp_host` to connect to.
diff --git a/docs/usage/configuration/config_documentation.md b/docs/usage/configuration/config_documentation.md
index 98ceb878e2557833f229b147d63f7774e45a4585..74522a1e4e5089cc71075eb35a0b5382fb742b3b 100644
--- a/docs/usage/configuration/config_documentation.md
+++ b/docs/usage/configuration/config_documentation.md
@@ -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
@@ -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
diff --git a/synapse/config/emailconfig.py b/synapse/config/emailconfig.py
index 8033fa2e52604dc6a2971196ed8758700f71a59c..c3a3e05a825a258074b7d89dc36b10c389e9c143 100644
--- a/synapse/config/emailconfig.py
+++ b/synapse/config/emailconfig.py
@@ -110,6 +110,7 @@ class EmailConfig(Config):
             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"]
diff --git a/synapse/handlers/send_email.py b/synapse/handlers/send_email.py
index 70cdb0721c996dda7d4bb00c788cc9656e658434..8cf8d2badabf149bb6573848586397f81a513911 100644
--- a/synapse/handlers/send_email.py
+++ b/synapse/handlers/send_email.py
@@ -47,15 +47,45 @@ logger = logging.getLogger(__name__)
 _is_old_twisted = parse_version(twisted.__version__) < parse_version("21")
 
 
-class _NoTLSESMTPSender(ESMTPSender):
-    """Extend ESMTPSender to disable TLS
+class _BackportESMTPSender(ESMTPSender):
+    """Extend old versions of ESMTPSender to configure TLS.
 
-    Unfortunately, before Twisted 21.2, ESMTPSender doesn't give an easy way to disable
-    TLS, so we override its internal method which it uses to generate a context factory.
+    Unfortunately, before Twisted 21.2, ESMTPSender doesn't give an easy way to
+    disable TLS, or to configure the hostname used for TLS certificate validation.
+    This backports the `hostname` parameter for that functionality.
     """
 
+    __hostname: Optional[str]
+
+    def __init__(self, *args: Any, **kwargs: Any) -> None:
+        """"""
+        self.__hostname = kwargs.pop("hostname", None)
+        super().__init__(*args, **kwargs)
+
     def _getContextFactory(self) -> Optional[IOpenSSLContextFactory]:
-        return None
+        if self.context is not None:
+            return self.context
+        elif self.__hostname is None:
+            return None  # disable TLS if hostname is None
+        return optionsForClientTLS(self.__hostname)
+
+
+class _BackportESMTPSenderFactory(ESMTPSenderFactory):
+    """An ESMTPSenderFactory for _BackportESMTPSender.
+
+    This backports the `hostname` parameter, to disable or configure TLS.
+    """
+
+    __hostname: Optional[str]
+
+    def __init__(self, *args: Any, **kwargs: Any) -> None:
+        self.__hostname = kwargs.pop("hostname", None)
+        super().__init__(*args, **kwargs)
+
+    def protocol(self, *args: Any, **kwargs: Any) -> ESMTPSender:  # type: ignore
+        # this overrides ESMTPSenderFactory's `protocol` attribute, with a Callable
+        # instantiating our _BackportESMTPSender, providing the hostname parameter
+        return _BackportESMTPSender(*args, **kwargs, hostname=self.__hostname)
 
 
 async def _sendmail(
@@ -71,6 +101,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
 
@@ -88,39 +119,33 @@ 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()
-
-    def build_sender_factory(**kwargs: Any) -> ESMTPSenderFactory:
-        return ESMTPSenderFactory(
-            username,
-            password,
-            from_addr,
-            to_addr,
-            msg,
-            d,
-            heloFallback=True,
-            requireAuthentication=require_auth,
-            requireTransportSecurity=require_tls,
-            **kwargs,
-        )
-
-    factory: IProtocolFactory
-    if _is_old_twisted:
-        # before twisted 21.2, we have to override the ESMTPSender protocol to disable
-        # TLS
-        factory = build_sender_factory()
-
-        if not enable_tls:
-            factory.protocol = _NoTLSESMTPSender
-    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)
+    if not enable_tls:
+        tlsname = None
+    elif tlsname is None:
+        tlsname = smtphost
+
+    factory: IProtocolFactory = (
+        _BackportESMTPSenderFactory if _is_old_twisted else ESMTPSenderFactory
+    )(
+        username,
+        password,
+        from_addr,
+        to_addr,
+        msg,
+        d,
+        heloFallback=True,
+        requireAuthentication=require_auth,
+        requireTransportSecurity=require_tls,
+        hostname=tlsname,
+    )
 
     if force_tls:
-        factory = TLSMemoryBIOFactory(optionsForClientTLS(smtphost), True, factory)
+        factory = TLSMemoryBIOFactory(optionsForClientTLS(tlsname), True, factory)
 
     endpoint = HostnameEndpoint(
         reactor, smtphost, smtpport, timeout=30, bindAddress=None
@@ -148,6 +173,7 @@ class SendEmailHandler:
         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
 
@@ -227,4 +253,5 @@ class SendEmailHandler:
             require_tls=self._require_transport_security,
             enable_tls=self._enable_tls,
             force_tls=self._force_tls,
+            tlsname=self._tlsname,
         )
diff --git a/tests/handlers/test_send_email.py b/tests/handlers/test_send_email.py
index cedcea27d93cc24ab004077f116c9d0e11633397..5f7839c82c18b5f6406eb0dbb4db26bbd478a376 100644
--- a/tests/handlers/test_send_email.py
+++ b/tests/handlers/test_send_email.py
@@ -163,6 +163,7 @@ class SendEmailHandlerTestCaseIPv4(HomeserverTestCase):
             "email": {
                 "notif_from": "noreply@test",
                 "force_tls": True,
+                "tlsname": "example.org",
             },
         }
     )
@@ -186,10 +187,9 @@ class SendEmailHandlerTestCaseIPv4(HomeserverTestCase):
         self.assertEqual(host, self.reactor.lookups["localhost"])
         self.assertEqual(port, 465)
         # We need to make sure that TLS is happenning
-        self.assertIsInstance(
-            client_factory._wrappedFactory._testingContextFactory,
-            ClientTLSOptions,
-        )
+        context_factory = client_factory._wrappedFactory._testingContextFactory
+        self.assertIsInstance(context_factory, ClientTLSOptions)
+        self.assertEqual(context_factory._hostname, "example.org")  # tlsname
         # And since we use endpoints, they go through reactor.connectTCP
         # which works differently to connectSSL on the testing reactor