def build_email(
        self,
        email_from,
        email_to,
        subject,
        body,
        email_cc=None,
        email_bcc=None,
        reply_to=False,
        attachments=None,
        message_id=None,
        references=None,
        object_id=False,
        subtype="plain",
        headers=None,
        body_alternative=None,
        subtype_alternative="plain",
    ):
        """ copy-pasted from odoo/addons/base/models/ir_mail_server.py::build_email """

        ftemplate = "__image-%s__"
        fcounter = 0
        attachments = attachments or []

        pattern = re.compile(r'"data:image/png;base64,[^"]*"')
        pos = 0
        new_body = ""
        body = body or ""
        while True:
            match = pattern.search(body, pos)
            if not match:
                break
            s = match.start()
            e = match.end()
            data = body[s + len('"data:image/png;base64,'):e - 1]
            new_body += body[pos:s]
            fname = ftemplate % fcounter
            fcounter += 1
            attachments.append((fname, base64.b64decode(data)))

            new_body += '"cid:%s"' % fname
            pos = e

        new_body += body[pos:]
        body = new_body

        email_from = email_from or tools.config.get("email_from")
        assert email_from, (
            "You must either provide a sender address explicitly or configure "
            "a global sender address in the server configuration or with the "
            "--email-from startup parameter.")

        # Note: we must force all strings to to 8-bit utf-8 when crafting message,
        #       or use encode_header() for headers, which does it automatically.

        headers = headers or {}  # need valid dict later

        if not email_cc:
            email_cc = []
        if not email_bcc:
            email_bcc = []
        if not body:
            body = u""

        email_body_utf8 = ustr(body).encode("utf-8")
        email_text_part = MIMEText(email_body_utf8,
                                   _subtype=subtype,
                                   _charset="utf-8")
        msg = MIMEMultipart()

        if not message_id:
            if object_id:
                message_id = tools.generate_tracking_message_id(object_id)
            else:
                message_id = make_msgid()
        msg["Message-Id"] = encode_header(message_id)
        if references:
            msg["references"] = encode_header(references)
        msg["Subject"] = encode_header(subject)
        msg["From"] = encode_rfc2822_address_header(email_from)
        del msg["Reply-To"]
        if reply_to:
            msg["Reply-To"] = encode_rfc2822_address_header(reply_to)
        else:
            msg["Reply-To"] = msg["From"]
        msg["To"] = encode_rfc2822_address_header(COMMASPACE.join(email_to))
        if email_cc:
            msg["Cc"] = encode_rfc2822_address_header(
                COMMASPACE.join(email_cc))
        if email_bcc:
            msg["Bcc"] = encode_rfc2822_address_header(
                COMMASPACE.join(email_bcc))
        msg["Date"] = formatdate()
        # Custom headers may override normal headers or provide additional ones
        for key, value in headers.items():
            msg[ustr(key).encode("utf-8")] = encode_header(value)

        if subtype == "html" and not body_alternative and html2text:
            # Always provide alternative text body ourselves if possible.
            text_utf8 = tools.html2text(
                email_body_utf8.decode("utf-8")).encode("utf-8")
            alternative_part = MIMEMultipart(_subtype="alternative")
            alternative_part.attach(
                MIMEText(text_utf8, _charset="utf-8", _subtype="plain"))
            alternative_part.attach(email_text_part)
            msg.attach(alternative_part)
        elif body_alternative:
            # Include both alternatives, as specified, within a multipart/alternative part
            alternative_part = MIMEMultipart(_subtype="alternative")
            body_alternative_utf8 = ustr(body_alternative).encode("utf-8")
            alternative_body_part = MIMEText(body_alternative_utf8,
                                             _subtype=subtype_alternative,
                                             _charset="utf-8")
            alternative_part.attach(alternative_body_part)
            alternative_part.attach(email_text_part)
            msg.attach(alternative_part)
        else:
            msg.attach(email_text_part)

        if attachments:
            for (fname, fcontent) in attachments:
                filename_rfc2047 = encode_header_param(fname)
                part = MIMEBase("application", "octet-stream")

                # The default RFC2231 encoding of Message.add_header() works in Thunderbird but not GMail
                # so we fix it by using RFC2047 encoding for the filename instead.
                part.sudo().set_param("name", filename_rfc2047)
                part.add_header("Content-Disposition",
                                "attachment",
                                filename=filename_rfc2047)
                part.add_header("Content-ID",
                                "<%s>" % filename_rfc2047)  # NEW STUFF

                part.set_payload(fcontent)
                encoders.encode_base64(part)
                msg.attach(part)
        return msg