def prepare_message(user, useralias, addresses, subject, contents, attachments, headers, encoding, newline_to_break=True): # check if closed!!!!!! XXX """ Prepare a MIME message """ if isinstance(contents, text_type): contents = [contents] if isinstance(attachments, text_type): attachments = [attachments] # merge contents and attachments for now. if attachments is not None: for a in attachments: if not os.path.isfile(a): raise TypeError("'{0}' is not a valid filepath".format(a)) contents = attachments if contents is None else contents + attachments has_included_images, content_objects = prepare_contents(contents, encoding) msg = MIMEMultipart() if headers is not None: # Strangely, msg does not have an update method, so then manually. for k, v in headers.items(): msg[k] = v if headers is None or "Date" not in headers: msg["Date"] = formatdate() msg_alternative = MIMEMultipart("alternative") msg_related = MIMEMultipart("related") msg_related.attach("-- HTML goes here --") msg.attach(msg_alternative) add_subject(msg, subject) add_recipients_headers(user, useralias, msg, addresses) htmlstr = "" altstr = [] if has_included_images: msg.preamble = "This message is best displayed using a MIME capable email reader." if contents is not None: for content_object, content_string in zip(content_objects, contents): if content_object["main_type"] == "image": # all image objects need base64 encoding, so do it now email.encoders.encode_base64(content_object["mime_object"]) # aliased image {'path' : 'alias'} if isinstance(content_string, dict) and len(content_string) == 1: for key in content_string: hashed_ref = str(abs(hash(key))) alias = content_string[key] # pylint: disable=undefined-loop-variable content_string = key else: alias = os.path.basename(str(content_string)) hashed_ref = str(abs(hash(alias))) # TODO: I should probably remove inline now that there is "attachments" # if string is `inline`, inline, else, attach # pylint: disable=unidiomatic-typecheck if type(content_string) == inline: htmlstr += '<img src="cid:{0}" title="{1}"/>'.format( hashed_ref, alias) content_object["mime_object"].add_header( "Content-ID", "<{0}>".format(hashed_ref)) altstr.append( "-- img {0} should be here -- ".format(alias)) # inline images should be in related MIME block msg_related.attach(content_object["mime_object"]) else: # non-inline images get attached like any other attachment msg.attach(content_object["mime_object"]) else: if content_object["encoding"] == "base64": email.encoders.encode_base64(content_object["mime_object"]) msg.attach(content_object["mime_object"]) elif content_object["sub_type"] not in ["html", "plain"]: msg.attach(content_object["mime_object"]) else: if newline_to_break: content_string = content_string.replace("\n", "<br>") try: htmlstr += "<div>{0}</div>".format(content_string) except UnicodeEncodeError: htmlstr += u"<div>{0}</div>".format(content_string) altstr.append(content_string) msg_related.get_payload()[0] = MIMEText(htmlstr, "html", _charset=encoding) msg_alternative.attach(MIMEText("\n".join(altstr), _charset=encoding)) msg_alternative.attach(msg_related) return msg
def prepare_message(user, useralias, addresses, subject, contents, attachments, headers, encoding, newline_to_break=True): # check if closed!!!!!! XXX """ Prepare a MIME message """ if isinstance(contents, text_type): contents = [contents] if isinstance(attachments, text_type): attachments = [attachments] # merge contents and attachments for now. if attachments is not None: for a in attachments: if not os.path.isfile(a): raise TypeError("'{0}' is not a valid filepath".format(a)) contents = attachments if contents is None else contents + attachments has_included_images, content_objects = prepare_contents(contents, encoding) msg = MIMEMultipart() if headers is not None: # Strangely, msg does not have an update method, so then manually. for k, v in headers.items(): msg[k] = v if headers is None or "Date" not in headers: msg["Date"] = formatdate() msg_alternative = MIMEMultipart("alternative") msg_related = MIMEMultipart("related") msg_related.attach("-- HTML goes here --") msg.attach(msg_alternative) add_subject(msg, subject) add_recipients_headers(user, useralias, msg, addresses) htmlstr = "" altstr = [] if has_included_images: msg.preamble = "This message is best displayed using a MIME capable email reader." if contents is not None: for content_object, content_string in zip(content_objects, contents): if content_object["main_type"] == "image": # all image objects need base64 encoding, so do it now email.encoders.encode_base64(content_object["mime_object"]) # aliased image {'path' : 'alias'} if isinstance(content_string, dict) and len(content_string) == 1: for key in content_string: hashed_ref = str(abs(hash(key))) alias = content_string[key] # pylint: disable=undefined-loop-variable content_string = key else: alias = os.path.basename(str(content_string)) hashed_ref = str(abs(hash(alias))) # TODO: I should probably remove inline now that there is "attachments" # if string is `inline`, inline, else, attach # pylint: disable=unidiomatic-typecheck if type(content_string) == inline: htmlstr += '<img src="cid:{0}" title="{1}"/>'.format(hashed_ref, alias) content_object["mime_object"].add_header( "Content-ID", "<{0}>".format(hashed_ref) ) altstr.append("-- img {0} should be here -- ".format(alias)) # inline images should be in related MIME block msg_related.attach(content_object["mime_object"]) else: # non-inline images get attached like any other attachment msg.attach(content_object["mime_object"]) else: if content_object["encoding"] == "base64": email.encoders.encode_base64(content_object["mime_object"]) msg.attach(content_object["mime_object"]) elif content_object["sub_type"] not in ["html", "plain"]: msg.attach(content_object["mime_object"]) else: if newline_to_break: content_string = content_string.replace("\n", "<br>") try: htmlstr += "<div>{0}</div>".format(content_string) except UnicodeEncodeError: htmlstr += u"<div>{0}</div>".format(content_string) altstr.append(content_string) msg_related.get_payload()[0] = MIMEText(htmlstr, "html", _charset=encoding) msg_alternative.attach(MIMEText("\n".join(altstr), _charset=encoding)) msg_alternative.attach(msg_related) return msg