We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix SMTP STARTTLS for Twisted >= 21.2.0
## Summary

The [Mail settings](https://docs.scrapy.org/en/latest/topics/email.html#topics-email-settings) don't have an option to choose a TLS version. Only to enforce upgrading connections to use SSL/TLS.
Mail servers like smtp.office365.com dropped support for TLS1.0 and TLS1.1 and now require TLS1.2: https://techcommunity.microsoft.com/t5/exchange-team-blog/new-opt-in-endpoint-available-for-smtp-auth-clients-still/ba-p/2659652 

It seems that scrapy mail doesn't support TLS1.2. The error message (with `MAIL_TLS = True`):

`[scrapy.mail] Unable to send mail: To=['user@gmail.com'] Cc=[] Subject="Test" Attachs=0- 421 b'4.7.66 TLS 1.0 and 1.1 are not supported. Please upgrade/update your client to support TLS 1.2. Visit https://aka.ms/smtp_auth_tls. [AM6P194CA0047.EURP194.PROD.OUTLOOK.COM]'` 

## Motivation

Without TLS1.2 it's not possible anymore to send mails via smtp.office365.com. An option to use TLS1.2 would fix this issue


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scrapy/mail.py`
Content:
```
1 """
2 Mail sending helpers
3 
4 See documentation in docs/topics/email.rst
5 """
6 import logging
7 from email import encoders as Encoders
8 from email.mime.base import MIMEBase
9 from email.mime.multipart import MIMEMultipart
10 from email.mime.nonmultipart import MIMENonMultipart
11 from email.mime.text import MIMEText
12 from email.utils import formatdate
13 from io import BytesIO
14 
15 from twisted.internet import defer, ssl
16 
17 from scrapy.utils.misc import arg_to_iter
18 from scrapy.utils.python import to_bytes
19 
20 
21 logger = logging.getLogger(__name__)
22 
23 
24 # Defined in the email.utils module, but undocumented:
25 # https://github.com/python/cpython/blob/v3.9.0/Lib/email/utils.py#L42
26 COMMASPACE = ", "
27 
28 
29 def _to_bytes_or_none(text):
30     if text is None:
31         return None
32     return to_bytes(text)
33 
34 
35 class MailSender:
36     def __init__(
37         self, smtphost='localhost', mailfrom='scrapy@localhost', smtpuser=None,
38         smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False
39     ):
40         self.smtphost = smtphost
41         self.smtpport = smtpport
42         self.smtpuser = _to_bytes_or_none(smtpuser)
43         self.smtppass = _to_bytes_or_none(smtppass)
44         self.smtptls = smtptls
45         self.smtpssl = smtpssl
46         self.mailfrom = mailfrom
47         self.debug = debug
48 
49     @classmethod
50     def from_settings(cls, settings):
51         return cls(
52             smtphost=settings['MAIL_HOST'],
53             mailfrom=settings['MAIL_FROM'],
54             smtpuser=settings['MAIL_USER'],
55             smtppass=settings['MAIL_PASS'],
56             smtpport=settings.getint('MAIL_PORT'),
57             smtptls=settings.getbool('MAIL_TLS'),
58             smtpssl=settings.getbool('MAIL_SSL'),
59         )
60 
61     def send(self, to, subject, body, cc=None, attachs=(), mimetype='text/plain', charset=None, _callback=None):
62         from twisted.internet import reactor
63         if attachs:
64             msg = MIMEMultipart()
65         else:
66             msg = MIMENonMultipart(*mimetype.split('/', 1))
67 
68         to = list(arg_to_iter(to))
69         cc = list(arg_to_iter(cc))
70 
71         msg['From'] = self.mailfrom
72         msg['To'] = COMMASPACE.join(to)
73         msg['Date'] = formatdate(localtime=True)
74         msg['Subject'] = subject
75         rcpts = to[:]
76         if cc:
77             rcpts.extend(cc)
78             msg['Cc'] = COMMASPACE.join(cc)
79 
80         if charset:
81             msg.set_charset(charset)
82 
83         if attachs:
84             msg.attach(MIMEText(body, 'plain', charset or 'us-ascii'))
85             for attach_name, mimetype, f in attachs:
86                 part = MIMEBase(*mimetype.split('/'))
87                 part.set_payload(f.read())
88                 Encoders.encode_base64(part)
89                 part.add_header('Content-Disposition', 'attachment', filename=attach_name)
90                 msg.attach(part)
91         else:
92             msg.set_payload(body)
93 
94         if _callback:
95             _callback(to=to, subject=subject, body=body, cc=cc, attach=attachs, msg=msg)
96 
97         if self.debug:
98             logger.debug('Debug mail sent OK: To=%(mailto)s Cc=%(mailcc)s '
99                          'Subject="%(mailsubject)s" Attachs=%(mailattachs)d',
100                          {'mailto': to, 'mailcc': cc, 'mailsubject': subject,
101                           'mailattachs': len(attachs)})
102             return
103 
104         dfd = self._sendmail(rcpts, msg.as_string().encode(charset or 'utf-8'))
105         dfd.addCallbacks(
106             callback=self._sent_ok,
107             errback=self._sent_failed,
108             callbackArgs=[to, cc, subject, len(attachs)],
109             errbackArgs=[to, cc, subject, len(attachs)],
110         )
111         reactor.addSystemEventTrigger('before', 'shutdown', lambda: dfd)
112         return dfd
113 
114     def _sent_ok(self, result, to, cc, subject, nattachs):
115         logger.info('Mail sent OK: To=%(mailto)s Cc=%(mailcc)s '
116                     'Subject="%(mailsubject)s" Attachs=%(mailattachs)d',
117                     {'mailto': to, 'mailcc': cc, 'mailsubject': subject,
118                      'mailattachs': nattachs})
119 
120     def _sent_failed(self, failure, to, cc, subject, nattachs):
121         errstr = str(failure.value)
122         logger.error('Unable to send mail: To=%(mailto)s Cc=%(mailcc)s '
123                      'Subject="%(mailsubject)s" Attachs=%(mailattachs)d'
124                      '- %(mailerr)s',
125                      {'mailto': to, 'mailcc': cc, 'mailsubject': subject,
126                       'mailattachs': nattachs, 'mailerr': errstr})
127 
128     def _sendmail(self, to_addrs, msg):
129         # Import twisted.mail here because it is not available in python3
130         from twisted.internet import reactor
131         from twisted.mail.smtp import ESMTPSenderFactory
132         msg = BytesIO(msg)
133         d = defer.Deferred()
134         factory = ESMTPSenderFactory(
135             self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d,
136             heloFallback=True, requireAuthentication=False, requireTransportSecurity=self.smtptls,
137         )
138         factory.noisy = False
139 
140         if self.smtpssl:
141             reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory())
142         else:
143             reactor.connectTCP(self.smtphost, self.smtpport, factory)
144 
145         return d
146
```
--- 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/scrapy/mail.py b/scrapy/mail.py
--- a/scrapy/mail.py
+++ b/scrapy/mail.py
@@ -12,7 +12,9 @@
 from email.utils import formatdate
 from io import BytesIO
 
+from twisted.python.versions import Version
 from twisted.internet import defer, ssl
+from twisted import version as twisted_version
 
 from scrapy.utils.misc import arg_to_iter
 from scrapy.utils.python import to_bytes
@@ -126,16 +128,11 @@
                       'mailattachs': nattachs, 'mailerr': errstr})
 
     def _sendmail(self, to_addrs, msg):
-        # Import twisted.mail here because it is not available in python3
         from twisted.internet import reactor
-        from twisted.mail.smtp import ESMTPSenderFactory
         msg = BytesIO(msg)
         d = defer.Deferred()
-        factory = ESMTPSenderFactory(
-            self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d,
-            heloFallback=True, requireAuthentication=False, requireTransportSecurity=self.smtptls,
-        )
-        factory.noisy = False
+
+        factory = self._create_sender_factory(to_addrs, msg, d)
 
         if self.smtpssl:
             reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory())
@@ -143,3 +140,20 @@
             reactor.connectTCP(self.smtphost, self.smtpport, factory)
 
         return d
+
+    def _create_sender_factory(self, to_addrs, msg, d):
+        from twisted.mail.smtp import ESMTPSenderFactory
+
+        factory_keywords = {
+            'heloFallback': True,
+            'requireAuthentication': False,
+            'requireTransportSecurity': self.smtptls
+        }
+
+        # Newer versions of twisted require the hostname to use STARTTLS
+        if twisted_version >= Version('twisted', 21, 2, 0):
+            factory_keywords['hostname'] = self.smtphost
+
+        factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d, **factory_keywords)
+        factory.noisy = False
+        return factory

{"golden_diff": "diff --git a/scrapy/mail.py b/scrapy/mail.py\n--- a/scrapy/mail.py\n+++ b/scrapy/mail.py\n@@ -12,7 +12,9 @@\n from email.utils import formatdate\n from io import BytesIO\n \n+from twisted.python.versions import Version\n from twisted.internet import defer, ssl\n+from twisted import version as twisted_version\n \n from scrapy.utils.misc import arg_to_iter\n from scrapy.utils.python import to_bytes\n@@ -126,16 +128,11 @@\n                       'mailattachs': nattachs, 'mailerr': errstr})\n \n     def _sendmail(self, to_addrs, msg):\n-        # Import twisted.mail here because it is not available in python3\n         from twisted.internet import reactor\n-        from twisted.mail.smtp import ESMTPSenderFactory\n         msg = BytesIO(msg)\n         d = defer.Deferred()\n-        factory = ESMTPSenderFactory(\n-            self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d,\n-            heloFallback=True, requireAuthentication=False, requireTransportSecurity=self.smtptls,\n-        )\n-        factory.noisy = False\n+\n+        factory = self._create_sender_factory(to_addrs, msg, d)\n \n         if self.smtpssl:\n             reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory())\n@@ -143,3 +140,20 @@\n             reactor.connectTCP(self.smtphost, self.smtpport, factory)\n \n         return d\n+\n+    def _create_sender_factory(self, to_addrs, msg, d):\n+        from twisted.mail.smtp import ESMTPSenderFactory\n+\n+        factory_keywords = {\n+            'heloFallback': True,\n+            'requireAuthentication': False,\n+            'requireTransportSecurity': self.smtptls\n+        }\n+\n+        # Newer versions of twisted require the hostname to use STARTTLS\n+        if twisted_version >= Version('twisted', 21, 2, 0):\n+            factory_keywords['hostname'] = self.smtphost\n+\n+        factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d, **factory_keywords)\n+        factory.noisy = False\n+        return factory\n", "issue": "Fix SMTP STARTTLS for Twisted >= 21.2.0\n## Summary\r\n\r\nThe [Mail settings](https://docs.scrapy.org/en/latest/topics/email.html#topics-email-settings) don't have an option to choose a TLS version. Only to enforce upgrading connections to use SSL/TLS.\r\nMail servers like smtp.office365.com dropped support for TLS1.0 and TLS1.1 and now require TLS1.2: https://techcommunity.microsoft.com/t5/exchange-team-blog/new-opt-in-endpoint-available-for-smtp-auth-clients-still/ba-p/2659652 \r\n\r\nIt seems that scrapy mail doesn't support TLS1.2. The error message (with `MAIL_TLS = True`):\r\n\r\n`[scrapy.mail] Unable to send mail: To=['user@gmail.com'] Cc=[] Subject=\"Test\" Attachs=0- 421 b'4.7.66 TLS 1.0 and 1.1 are not supported. Please upgrade/update your client to support TLS 1.2. Visit https://aka.ms/smtp_auth_tls. [AM6P194CA0047.EURP194.PROD.OUTLOOK.COM]'` \r\n\r\n## Motivation\r\n\r\nWithout TLS1.2 it's not possible anymore to send mails via smtp.office365.com. An option to use TLS1.2 would fix this issue\r\n\n", "before_files": [{"content": "\"\"\"\nMail sending helpers\n\nSee documentation in docs/topics/email.rst\n\"\"\"\nimport logging\nfrom email import encoders as Encoders\nfrom email.mime.base import MIMEBase\nfrom email.mime.multipart import MIMEMultipart\nfrom email.mime.nonmultipart import MIMENonMultipart\nfrom email.mime.text import MIMEText\nfrom email.utils import formatdate\nfrom io import BytesIO\n\nfrom twisted.internet import defer, ssl\n\nfrom scrapy.utils.misc import arg_to_iter\nfrom scrapy.utils.python import to_bytes\n\n\nlogger = logging.getLogger(__name__)\n\n\n# Defined in the email.utils module, but undocumented:\n# https://github.com/python/cpython/blob/v3.9.0/Lib/email/utils.py#L42\nCOMMASPACE = \", \"\n\n\ndef _to_bytes_or_none(text):\n    if text is None:\n        return None\n    return to_bytes(text)\n\n\nclass MailSender:\n    def __init__(\n        self, smtphost='localhost', mailfrom='scrapy@localhost', smtpuser=None,\n        smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False\n    ):\n        self.smtphost = smtphost\n        self.smtpport = smtpport\n        self.smtpuser = _to_bytes_or_none(smtpuser)\n        self.smtppass = _to_bytes_or_none(smtppass)\n        self.smtptls = smtptls\n        self.smtpssl = smtpssl\n        self.mailfrom = mailfrom\n        self.debug = debug\n\n    @classmethod\n    def from_settings(cls, settings):\n        return cls(\n            smtphost=settings['MAIL_HOST'],\n            mailfrom=settings['MAIL_FROM'],\n            smtpuser=settings['MAIL_USER'],\n            smtppass=settings['MAIL_PASS'],\n            smtpport=settings.getint('MAIL_PORT'),\n            smtptls=settings.getbool('MAIL_TLS'),\n            smtpssl=settings.getbool('MAIL_SSL'),\n        )\n\n    def send(self, to, subject, body, cc=None, attachs=(), mimetype='text/plain', charset=None, _callback=None):\n        from twisted.internet import reactor\n        if attachs:\n            msg = MIMEMultipart()\n        else:\n            msg = MIMENonMultipart(*mimetype.split('/', 1))\n\n        to = list(arg_to_iter(to))\n        cc = list(arg_to_iter(cc))\n\n        msg['From'] = self.mailfrom\n        msg['To'] = COMMASPACE.join(to)\n        msg['Date'] = formatdate(localtime=True)\n        msg['Subject'] = subject\n        rcpts = to[:]\n        if cc:\n            rcpts.extend(cc)\n            msg['Cc'] = COMMASPACE.join(cc)\n\n        if charset:\n            msg.set_charset(charset)\n\n        if attachs:\n            msg.attach(MIMEText(body, 'plain', charset or 'us-ascii'))\n            for attach_name, mimetype, f in attachs:\n                part = MIMEBase(*mimetype.split('/'))\n                part.set_payload(f.read())\n                Encoders.encode_base64(part)\n                part.add_header('Content-Disposition', 'attachment', filename=attach_name)\n                msg.attach(part)\n        else:\n            msg.set_payload(body)\n\n        if _callback:\n            _callback(to=to, subject=subject, body=body, cc=cc, attach=attachs, msg=msg)\n\n        if self.debug:\n            logger.debug('Debug mail sent OK: To=%(mailto)s Cc=%(mailcc)s '\n                         'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                         {'mailto': to, 'mailcc': cc, 'mailsubject': subject,\n                          'mailattachs': len(attachs)})\n            return\n\n        dfd = self._sendmail(rcpts, msg.as_string().encode(charset or 'utf-8'))\n        dfd.addCallbacks(\n            callback=self._sent_ok,\n            errback=self._sent_failed,\n            callbackArgs=[to, cc, subject, len(attachs)],\n            errbackArgs=[to, cc, subject, len(attachs)],\n        )\n        reactor.addSystemEventTrigger('before', 'shutdown', lambda: dfd)\n        return dfd\n\n    def _sent_ok(self, result, to, cc, subject, nattachs):\n        logger.info('Mail sent OK: To=%(mailto)s Cc=%(mailcc)s '\n                    'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                    {'mailto': to, 'mailcc': cc, 'mailsubject': subject,\n                     'mailattachs': nattachs})\n\n    def _sent_failed(self, failure, to, cc, subject, nattachs):\n        errstr = str(failure.value)\n        logger.error('Unable to send mail: To=%(mailto)s Cc=%(mailcc)s '\n                     'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d'\n                     '- %(mailerr)s',\n                     {'mailto': to, 'mailcc': cc, 'mailsubject': subject,\n                      'mailattachs': nattachs, 'mailerr': errstr})\n\n    def _sendmail(self, to_addrs, msg):\n        # Import twisted.mail here because it is not available in python3\n        from twisted.internet import reactor\n        from twisted.mail.smtp import ESMTPSenderFactory\n        msg = BytesIO(msg)\n        d = defer.Deferred()\n        factory = ESMTPSenderFactory(\n            self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d,\n            heloFallback=True, requireAuthentication=False, requireTransportSecurity=self.smtptls,\n        )\n        factory.noisy = False\n\n        if self.smtpssl:\n            reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory())\n        else:\n            reactor.connectTCP(self.smtphost, self.smtpport, factory)\n\n        return d\n", "path": "scrapy/mail.py"}], "after_files": [{"content": "\"\"\"\nMail sending helpers\n\nSee documentation in docs/topics/email.rst\n\"\"\"\nimport logging\nfrom email import encoders as Encoders\nfrom email.mime.base import MIMEBase\nfrom email.mime.multipart import MIMEMultipart\nfrom email.mime.nonmultipart import MIMENonMultipart\nfrom email.mime.text import MIMEText\nfrom email.utils import formatdate\nfrom io import BytesIO\n\nfrom twisted.python.versions import Version\nfrom twisted.internet import defer, ssl\nfrom twisted import version as twisted_version\n\nfrom scrapy.utils.misc import arg_to_iter\nfrom scrapy.utils.python import to_bytes\n\n\nlogger = logging.getLogger(__name__)\n\n\n# Defined in the email.utils module, but undocumented:\n# https://github.com/python/cpython/blob/v3.9.0/Lib/email/utils.py#L42\nCOMMASPACE = \", \"\n\n\ndef _to_bytes_or_none(text):\n    if text is None:\n        return None\n    return to_bytes(text)\n\n\nclass MailSender:\n    def __init__(\n        self, smtphost='localhost', mailfrom='scrapy@localhost', smtpuser=None,\n        smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False\n    ):\n        self.smtphost = smtphost\n        self.smtpport = smtpport\n        self.smtpuser = _to_bytes_or_none(smtpuser)\n        self.smtppass = _to_bytes_or_none(smtppass)\n        self.smtptls = smtptls\n        self.smtpssl = smtpssl\n        self.mailfrom = mailfrom\n        self.debug = debug\n\n    @classmethod\n    def from_settings(cls, settings):\n        return cls(\n            smtphost=settings['MAIL_HOST'],\n            mailfrom=settings['MAIL_FROM'],\n            smtpuser=settings['MAIL_USER'],\n            smtppass=settings['MAIL_PASS'],\n            smtpport=settings.getint('MAIL_PORT'),\n            smtptls=settings.getbool('MAIL_TLS'),\n            smtpssl=settings.getbool('MAIL_SSL'),\n        )\n\n    def send(self, to, subject, body, cc=None, attachs=(), mimetype='text/plain', charset=None, _callback=None):\n        from twisted.internet import reactor\n        if attachs:\n            msg = MIMEMultipart()\n        else:\n            msg = MIMENonMultipart(*mimetype.split('/', 1))\n\n        to = list(arg_to_iter(to))\n        cc = list(arg_to_iter(cc))\n\n        msg['From'] = self.mailfrom\n        msg['To'] = COMMASPACE.join(to)\n        msg['Date'] = formatdate(localtime=True)\n        msg['Subject'] = subject\n        rcpts = to[:]\n        if cc:\n            rcpts.extend(cc)\n            msg['Cc'] = COMMASPACE.join(cc)\n\n        if charset:\n            msg.set_charset(charset)\n\n        if attachs:\n            msg.attach(MIMEText(body, 'plain', charset or 'us-ascii'))\n            for attach_name, mimetype, f in attachs:\n                part = MIMEBase(*mimetype.split('/'))\n                part.set_payload(f.read())\n                Encoders.encode_base64(part)\n                part.add_header('Content-Disposition', 'attachment', filename=attach_name)\n                msg.attach(part)\n        else:\n            msg.set_payload(body)\n\n        if _callback:\n            _callback(to=to, subject=subject, body=body, cc=cc, attach=attachs, msg=msg)\n\n        if self.debug:\n            logger.debug('Debug mail sent OK: To=%(mailto)s Cc=%(mailcc)s '\n                         'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                         {'mailto': to, 'mailcc': cc, 'mailsubject': subject,\n                          'mailattachs': len(attachs)})\n            return\n\n        dfd = self._sendmail(rcpts, msg.as_string().encode(charset or 'utf-8'))\n        dfd.addCallbacks(\n            callback=self._sent_ok,\n            errback=self._sent_failed,\n            callbackArgs=[to, cc, subject, len(attachs)],\n            errbackArgs=[to, cc, subject, len(attachs)],\n        )\n        reactor.addSystemEventTrigger('before', 'shutdown', lambda: dfd)\n        return dfd\n\n    def _sent_ok(self, result, to, cc, subject, nattachs):\n        logger.info('Mail sent OK: To=%(mailto)s Cc=%(mailcc)s '\n                    'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                    {'mailto': to, 'mailcc': cc, 'mailsubject': subject,\n                     'mailattachs': nattachs})\n\n    def _sent_failed(self, failure, to, cc, subject, nattachs):\n        errstr = str(failure.value)\n        logger.error('Unable to send mail: To=%(mailto)s Cc=%(mailcc)s '\n                     'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d'\n                     '- %(mailerr)s',\n                     {'mailto': to, 'mailcc': cc, 'mailsubject': subject,\n                      'mailattachs': nattachs, 'mailerr': errstr})\n\n    def _sendmail(self, to_addrs, msg):\n        from twisted.internet import reactor\n        msg = BytesIO(msg)\n        d = defer.Deferred()\n\n        factory = self._create_sender_factory(to_addrs, msg, d)\n\n        if self.smtpssl:\n            reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory())\n        else:\n            reactor.connectTCP(self.smtphost, self.smtpport, factory)\n\n        return d\n\n    def _create_sender_factory(self, to_addrs, msg, d):\n        from twisted.mail.smtp import ESMTPSenderFactory\n\n        factory_keywords = {\n            'heloFallback': True,\n            'requireAuthentication': False,\n            'requireTransportSecurity': self.smtptls\n        }\n\n        # Newer versions of twisted require the hostname to use STARTTLS\n        if twisted_version >= Version('twisted', 21, 2, 0):\n            factory_keywords['hostname'] = self.smtphost\n\n        factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, to_addrs, msg, d, **factory_keywords)\n        factory.noisy = False\n        return factory\n", "path": "scrapy/mail.py"}]}