prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <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?
  
  
  </issue>
  <code>
  [start of scrapy/mail.py]
  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 of scrapy/mail.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: 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)
  
verification_info: {"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"}]}