We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Allow sending HTML emails with scrapy.mail.MailSender
I've patched this locally by changing the `send` method:

```
def send(self, to, subject, body, cc=None, attachs=(), mime='text/plain', _callback=None):
    if attachs:
        msg = MIMEMultipart()
    else:
        msg = MIMENonMultipart(*mime.split('/'))
```

But it seems fragile. Any thoughts?

Allow sending HTML emails with scrapy.mail.MailSender
I've patched this locally by changing the `send` method:

```
def send(self, to, subject, body, cc=None, attachs=(), mime='text/plain', _callback=None):
    if attachs:
        msg = MIMEMultipart()
    else:
        msg = MIMENonMultipart(*mime.split('/'))
```

But it seems fragile. Any thoughts?


--- 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 from cStringIO import StringIO
7 from email.MIMEMultipart import MIMEMultipart
8 from email.MIMENonMultipart import MIMENonMultipart
9 from email.MIMEBase import MIMEBase
10 from email.MIMEText import MIMEText
11 from email.Utils import COMMASPACE, formatdate
12 from email import Encoders
13 
14 from twisted.internet import defer, reactor, ssl
15 from twisted.mail.smtp import ESMTPSenderFactory
16 
17 from scrapy import log
18 
19 class MailSender(object):
20 
21     def __init__(self, smtphost='localhost', mailfrom='scrapy@localhost',
22             smtpuser=None, smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False):
23         self.smtphost = smtphost
24         self.smtpport = smtpport
25         self.smtpuser = smtpuser
26         self.smtppass = smtppass
27         self.smtptls = smtptls
28         self.smtpssl = smtpssl
29         self.mailfrom = mailfrom
30         self.debug = debug
31 
32     @classmethod
33     def from_settings(cls, settings):
34         return cls(settings['MAIL_HOST'], settings['MAIL_FROM'], settings['MAIL_USER'],
35             settings['MAIL_PASS'], settings.getint('MAIL_PORT'),
36             settings.getbool('MAIL_TLS'), settings.getbool('MAIL_SSL'))
37 
38     def send(self, to, subject, body, cc=None, attachs=(), _callback=None):
39         if attachs:
40             msg = MIMEMultipart()
41         else:
42             msg = MIMENonMultipart('text', 'plain')
43         msg['From'] = self.mailfrom
44         msg['To'] = COMMASPACE.join(to)
45         msg['Date'] = formatdate(localtime=True)
46         msg['Subject'] = subject
47         rcpts = to[:]
48         if cc:
49             rcpts.extend(cc)
50             msg['Cc'] = COMMASPACE.join(cc)
51 
52         if attachs:
53             msg.attach(MIMEText(body))
54             for attach_name, mimetype, f in attachs:
55                 part = MIMEBase(*mimetype.split('/'))
56                 part.set_payload(f.read())
57                 Encoders.encode_base64(part)
58                 part.add_header('Content-Disposition', 'attachment; filename="%s"' \
59                     % attach_name)
60                 msg.attach(part)
61         else:
62             msg.set_payload(body)
63 
64         if _callback:
65             _callback(to=to, subject=subject, body=body, cc=cc, attach=attachs, msg=msg)
66 
67         if self.debug:
68             log.msg(format='Debug mail sent OK: To=%(mailto)s Cc=%(mailcc)s Subject="%(mailsubject)s" Attachs=%(mailattachs)d',
69                     level=log.DEBUG, mailto=to, mailcc=cc, mailsubject=subject, mailattachs=len(attachs))
70             return
71 
72         dfd = self._sendmail(rcpts, msg.as_string())
73         dfd.addCallbacks(self._sent_ok, self._sent_failed,
74             callbackArgs=[to, cc, subject, len(attachs)],
75             errbackArgs=[to, cc, subject, len(attachs)])
76         reactor.addSystemEventTrigger('before', 'shutdown', lambda: dfd)
77         return dfd
78 
79     def _sent_ok(self, result, to, cc, subject, nattachs):
80         log.msg(format='Mail sent OK: To=%(mailto)s Cc=%(mailcc)s '
81                        'Subject="%(mailsubject)s" Attachs=%(mailattachs)d',
82                 mailto=to, mailcc=cc, mailsubject=subject, mailattachs=nattachs)
83 
84     def _sent_failed(self, failure, to, cc, subject, nattachs):
85         errstr = str(failure.value)
86         log.msg(format='Unable to send mail: To=%(mailto)s Cc=%(mailcc)s '
87                        'Subject="%(mailsubject)s" Attachs=%(mailattachs)d'
88                        '- %(mailerr)s',
89                 level=log.ERROR, mailto=to, mailcc=cc, mailsubject=subject,
90                 mailattachs=nattachs, mailerr=errstr)
91 
92     def _sendmail(self, to_addrs, msg):
93         msg = StringIO(msg)
94         d = defer.Deferred()
95         factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, \
96             to_addrs, msg, d, heloFallback=True, requireAuthentication=False, \
97             requireTransportSecurity=self.smtptls)
98         factory.noisy = False
99 
100         if self.smtpssl:
101             reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory())
102         else:
103             reactor.connectTCP(self.smtphost, self.smtpport, factory)
104 
105         return d
106
```
--- 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
@@ -35,11 +35,11 @@
             settings['MAIL_PASS'], settings.getint('MAIL_PORT'),
             settings.getbool('MAIL_TLS'), settings.getbool('MAIL_SSL'))
 
-    def send(self, to, subject, body, cc=None, attachs=(), _callback=None):
+    def send(self, to, subject, body, cc=None, attachs=(), mimetype='text/plain', _callback=None):
         if attachs:
             msg = MIMEMultipart()
         else:
-            msg = MIMENonMultipart('text', 'plain')
+            msg = MIMENonMultipart(*mimetype.split('/', 1))
         msg['From'] = self.mailfrom
         msg['To'] = COMMASPACE.join(to)
         msg['Date'] = formatdate(localtime=True)

{"golden_diff": "diff --git a/scrapy/mail.py b/scrapy/mail.py\n--- a/scrapy/mail.py\n+++ b/scrapy/mail.py\n@@ -35,11 +35,11 @@\n             settings['MAIL_PASS'], settings.getint('MAIL_PORT'),\n             settings.getbool('MAIL_TLS'), settings.getbool('MAIL_SSL'))\n \n-    def send(self, to, subject, body, cc=None, attachs=(), _callback=None):\n+    def send(self, to, subject, body, cc=None, attachs=(), mimetype='text/plain', _callback=None):\n         if attachs:\n             msg = MIMEMultipart()\n         else:\n-            msg = MIMENonMultipart('text', 'plain')\n+            msg = MIMENonMultipart(*mimetype.split('/', 1))\n         msg['From'] = self.mailfrom\n         msg['To'] = COMMASPACE.join(to)\n         msg['Date'] = formatdate(localtime=True)\n", "issue": "Allow sending HTML emails with scrapy.mail.MailSender\nI've patched this locally by changing the `send` method:\n\n```\ndef send(self, to, subject, body, cc=None, attachs=(), mime='text/plain', _callback=None):\n    if attachs:\n        msg = MIMEMultipart()\n    else:\n        msg = MIMENonMultipart(*mime.split('/'))\n```\n\nBut it seems fragile. Any thoughts?\n\nAllow sending HTML emails with scrapy.mail.MailSender\nI've patched this locally by changing the `send` method:\n\n```\ndef send(self, to, subject, body, cc=None, attachs=(), mime='text/plain', _callback=None):\n    if attachs:\n        msg = MIMEMultipart()\n    else:\n        msg = MIMENonMultipart(*mime.split('/'))\n```\n\nBut it seems fragile. Any thoughts?\n\n", "before_files": [{"content": "\"\"\"\nMail sending helpers\n\nSee documentation in docs/topics/email.rst\n\"\"\"\nfrom cStringIO import StringIO\nfrom email.MIMEMultipart import MIMEMultipart\nfrom email.MIMENonMultipart import MIMENonMultipart\nfrom email.MIMEBase import MIMEBase\nfrom email.MIMEText import MIMEText\nfrom email.Utils import COMMASPACE, formatdate\nfrom email import Encoders\n\nfrom twisted.internet import defer, reactor, ssl\nfrom twisted.mail.smtp import ESMTPSenderFactory\n\nfrom scrapy import log\n\nclass MailSender(object):\n\n    def __init__(self, smtphost='localhost', mailfrom='scrapy@localhost',\n            smtpuser=None, smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False):\n        self.smtphost = smtphost\n        self.smtpport = smtpport\n        self.smtpuser = smtpuser\n        self.smtppass = 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(settings['MAIL_HOST'], settings['MAIL_FROM'], settings['MAIL_USER'],\n            settings['MAIL_PASS'], settings.getint('MAIL_PORT'),\n            settings.getbool('MAIL_TLS'), settings.getbool('MAIL_SSL'))\n\n    def send(self, to, subject, body, cc=None, attachs=(), _callback=None):\n        if attachs:\n            msg = MIMEMultipart()\n        else:\n            msg = MIMENonMultipart('text', 'plain')\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 attachs:\n            msg.attach(MIMEText(body))\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=\"%s\"' \\\n                    % 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            log.msg(format='Debug mail sent OK: To=%(mailto)s Cc=%(mailcc)s Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                    level=log.DEBUG, mailto=to, mailcc=cc, mailsubject=subject, mailattachs=len(attachs))\n            return\n\n        dfd = self._sendmail(rcpts, msg.as_string())\n        dfd.addCallbacks(self._sent_ok, self._sent_failed,\n            callbackArgs=[to, cc, subject, len(attachs)],\n            errbackArgs=[to, cc, subject, len(attachs)])\n        reactor.addSystemEventTrigger('before', 'shutdown', lambda: dfd)\n        return dfd\n\n    def _sent_ok(self, result, to, cc, subject, nattachs):\n        log.msg(format='Mail sent OK: To=%(mailto)s Cc=%(mailcc)s '\n                       'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                mailto=to, mailcc=cc, mailsubject=subject, mailattachs=nattachs)\n\n    def _sent_failed(self, failure, to, cc, subject, nattachs):\n        errstr = str(failure.value)\n        log.msg(format='Unable to send mail: To=%(mailto)s Cc=%(mailcc)s '\n                       'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d'\n                       '- %(mailerr)s',\n                level=log.ERROR, mailto=to, mailcc=cc, mailsubject=subject,\n                mailattachs=nattachs, mailerr=errstr)\n\n    def _sendmail(self, to_addrs, msg):\n        msg = StringIO(msg)\n        d = defer.Deferred()\n        factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, \\\n            to_addrs, msg, d, heloFallback=True, requireAuthentication=False, \\\n            requireTransportSecurity=self.smtptls)\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\"\"\"\nfrom cStringIO import StringIO\nfrom email.MIMEMultipart import MIMEMultipart\nfrom email.MIMENonMultipart import MIMENonMultipart\nfrom email.MIMEBase import MIMEBase\nfrom email.MIMEText import MIMEText\nfrom email.Utils import COMMASPACE, formatdate\nfrom email import Encoders\n\nfrom twisted.internet import defer, reactor, ssl\nfrom twisted.mail.smtp import ESMTPSenderFactory\n\nfrom scrapy import log\n\nclass MailSender(object):\n\n    def __init__(self, smtphost='localhost', mailfrom='scrapy@localhost',\n            smtpuser=None, smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False):\n        self.smtphost = smtphost\n        self.smtpport = smtpport\n        self.smtpuser = smtpuser\n        self.smtppass = 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(settings['MAIL_HOST'], settings['MAIL_FROM'], settings['MAIL_USER'],\n            settings['MAIL_PASS'], settings.getint('MAIL_PORT'),\n            settings.getbool('MAIL_TLS'), settings.getbool('MAIL_SSL'))\n\n    def send(self, to, subject, body, cc=None, attachs=(), mimetype='text/plain', _callback=None):\n        if attachs:\n            msg = MIMEMultipart()\n        else:\n            msg = MIMENonMultipart(*mimetype.split('/', 1))\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 attachs:\n            msg.attach(MIMEText(body))\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=\"%s\"' \\\n                    % 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            log.msg(format='Debug mail sent OK: To=%(mailto)s Cc=%(mailcc)s Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                    level=log.DEBUG, mailto=to, mailcc=cc, mailsubject=subject, mailattachs=len(attachs))\n            return\n\n        dfd = self._sendmail(rcpts, msg.as_string())\n        dfd.addCallbacks(self._sent_ok, self._sent_failed,\n            callbackArgs=[to, cc, subject, len(attachs)],\n            errbackArgs=[to, cc, subject, len(attachs)])\n        reactor.addSystemEventTrigger('before', 'shutdown', lambda: dfd)\n        return dfd\n\n    def _sent_ok(self, result, to, cc, subject, nattachs):\n        log.msg(format='Mail sent OK: To=%(mailto)s Cc=%(mailcc)s '\n                       'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d',\n                mailto=to, mailcc=cc, mailsubject=subject, mailattachs=nattachs)\n\n    def _sent_failed(self, failure, to, cc, subject, nattachs):\n        errstr = str(failure.value)\n        log.msg(format='Unable to send mail: To=%(mailto)s Cc=%(mailcc)s '\n                       'Subject=\"%(mailsubject)s\" Attachs=%(mailattachs)d'\n                       '- %(mailerr)s',\n                level=log.ERROR, mailto=to, mailcc=cc, mailsubject=subject,\n                mailattachs=nattachs, mailerr=errstr)\n\n    def _sendmail(self, to_addrs, msg):\n        msg = StringIO(msg)\n        d = defer.Deferred()\n        factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, \\\n            to_addrs, msg, d, heloFallback=True, requireAuthentication=False, \\\n            requireTransportSecurity=self.smtptls)\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"}]}