def make_body_images_inline(body): """Looks for images inside the body and make them inline. Before sending a message in HTML format, it is necessary to find all img tags contained in the body in order to rewrite them. For example, icons provided by CKeditor are stored on the server filesystem and not accessible from the outside. We must embark them as parts of the MIME message if we want recipients to display them correctly. :param body: the HTML body to parse """ html = lxml.html.fromstring(body) parts = [] for tag in html.iter("img"): src = tag.get("src") if src is None: continue o = urlparse(src) path = urllib.unquote(os.path.join(settings.BASE_DIR, o.path[1:])) if not os.path.exists(path): continue fname = os.path.basename(path) cid = "%s@modoboa" % os.path.splitext(fname)[0] tag.set("src", "cid:%s" % cid) with open(path, "rb") as fp: part = MIMEImage(fp.read()) part["Content-ID"] = "<%s>" % cid part.replace_header("Content-Type", '%s; name="%s"' % (part["Content-Type"], fname)) part["Content-Disposition"] = "inline" parts.append(part) return lxml.html.tostring(html), parts
def embedd_ir_attachment(self, cr, uid, message, body_part, context=None): # a unicode string is required here html_unicode_str = tools.ustr(body_part.get_payload(decode=True)) root = html.document_fromstring(html_unicode_str) matching_buffer = {} for child in root.iter(): # have to replace src by cid of the future attachement if child.tag == 'img': cid = uuid4() cid_id = ''.join('%s' % cid) matches = re.search(r'(ir.attachment\/)[\d]*', child.attrib.get('src')) if not matches: matches = re.search(r'(id=)[\d]+', child.attrib.get('src')) if matches: m_id = matches.group(0) img_id = m_id.split('/')[1] if '=' not in m_id else\ m_id.split('=')[1] if img_id: matching_buffer[img_id] = cid_id child.attrib['src'] = "cid:%s" % cid_id del body_part["Content-Transfer-Encoding"] # body has to be re-encoded into the message part using # the initial output charset body_part.set_payload( html.tostring( root, encoding=body_part.get_charset().get_output_charset())) Encoders.encode_base64(body_part) img_attachments = self.pool.get('ir.attachment').browse( cr, uid, map(int, matching_buffer.keys())) for img in img_attachments: content_id = matching_buffer.get("%s" % img.id) # our img.datas is already base64 part = MIMEImage( img.datas, _encoder=lambda a: a, _subtype=img.datas_fname.split(".")[-1].lower(), ) data_fname = img.datas_fname accepted_format = DEFAULT_FORMAT for f_format in IMAGE_FORMAT: if data_fname[-len(f_format):] == f_format: accepted_format = data_fname[-len(f_format):] part.add_header('Content-Disposition', 'inline', filename=data_fname) part.add_header('X-Attachment-Id', content_id) part.add_header('Content-ID', '<%s>' % content_id) part.replace_header('Content-Type', 'image/%s' % accepted_format) part.add_header("Content-Transfer-Encoding", "base64") message.attach(part) return
def find_images_in_body(body): """Looks for images inside a HTML body Before sending a message in HTML format, it is necessary to find all img tags contained in the body in order to rewrite them. For example, icons provided by CKeditor are stored on the server filesystem and not accessible from the outside. We must embark them as parts off the MIME message if we want recipients to display them correctly. :param body: the HTML body to parse """ from email.mime.image import MIMEImage from urlparse import urlparse html = lxml.html.fromstring(body) parts = [] for tag in html.iter("img"): src = tag.get("src") if src is None: continue o = urlparse(src) fname = os.path.basename(o.path) path = os.path.join(settings.MEDIA_ROOT, "webmail", fname) if not os.path.exists(path): continue cid = "%s@modoboa" % os.path.splitext(fname)[0] tag.set("src", "cid:%s" % cid) fp = open(path, "rb") p = MIMEImage(fp.read()) fp.close() p["Content-ID"] = "<%s>" % cid ct = p["Content-Type"] p.replace_header("Content-Type", '%s; name="%s"' \ % (ct, os.path.basename(fname))) p["Content-Disposition"] = "inline" parts.append(p) return lxml.html.tostring(html), parts
def make_body_images_inline(body): """Looks for images inside the body and make them inline. Before sending a message in HTML format, it is necessary to find all img tags contained in the body in order to rewrite them. For example, icons provided by CKeditor are stored on the server filesystem and not accessible from the outside. We must embark them as parts of the MIME message if we want recipients to display them correctly. :param body: the HTML body to parse """ import os from email.mime.image import MIMEImage from urlparse import urlparse html = lxml.html.fromstring(body) parts = [] for tag in html.iter("img"): src = tag.get("src") if src is None: continue o = urlparse(src) path = os.path.join(settings.MODOBOA_DIR, o.path[1:]) if not os.path.exists(path): continue fname = os.path.basename(path) cid = "%s@modoboa" % os.path.splitext(fname)[0] tag.set("src", "cid:%s" % cid) with open(path, "rb") as fp: part = MIMEImage(fp.read()) part["Content-ID"] = "<%s>" % cid part.replace_header( "Content-Type", '%s; name="%s"' % (part["Content-Type"], fname) ) part["Content-Disposition"] = "inline" parts.append(part) return lxml.html.tostring(html), parts
encode_quopri(part) else: encode_base64(part) else: part = MIMEBase(main_type, sub_type) part.set_payload(data) encode_base64(part) else: part = MIMEBase(main_type, sub_type) part.set_payload(data) if encoding == "base64": encode_base64(part) elif encoding == "quoted-printable": encode_quopri(part) elif encoding == "7or8bit": encode_7or8bit(part) else: # elif encoding == "noop": encode_noop(part) for key, value in attachment.get("replace_header_list", []): part.replace_header(key, value) for key, value in attachment.get("header_dict", {}).items(): # adds headers, does not replace or set part.add_header(key, value) for key, value in attachment.get("add_header_list", []): part.add_header(key, value) if attachment.get("filename", None) is not None: part.add_header("Content-Disposition", "attachment", attachment["filename"]) outer.attach(part) #return outer.as_string() return formatMultipartMessageToRFC2822String(outer)