def create_message(corpus, data, msg0=None): from email import Charset, Parser, MIMEMessage if not isinstance(data, unicode): raise TypeError("data must be a unicode.") p = Parser.FeedParser() p.feed(data) msg1 = p.close() csmap = Charset.Charset(config.MESSAGE_CHARSET) attach_msgs = [] # Re-encode the headers. headers = [] labels = [] for (k, v) in msg1.items(): v = rmsp(v) if not v: continue kl = k.lower() if kl == "x-forward-msg": attach_msgs.extend(get_numbers(v)) continue if kl == "label": labels = v.split(",") continue headers.append((k.encode("ascii", "strict"), encode_header(v, csmap))) # Remove all the existing headers. for k in msg1.keys(): del msg1[k] # Reattach the headers. for (k, v) in headers: msg1[k] = v # Change the body. data = msg1.get_payload(decode=False) try: # First try to encode with us-ascii. data.encode("ascii", "strict") # Succeed. msg1.set_charset("ascii") except UnicodeError: # Re-encode the body. if not csmap.output_charset: csmap = Charset.Charset("utf-8") msg1.set_charset(str(csmap.output_charset)) data = data.encode(str(csmap.output_codec), "replace") msg1.set_payload(data) # Attach other messages (for forwarding). if attach_msgs: for loc in attach_msgs: p = Parser.FeedParser() p.feed(corpus.get_message(loc)) msg1 = mime_add(msg1, MIMEMessage.MIMEMessage(p.close())) # Integrate other mime objects. if msg0 and msg0.is_multipart(): for obj in msg0.get_payload()[1:]: msg1 = mime_add(msg1, obj) validate_message_structure(msg1) return (msg1, labels)
def create_message(corpus, data, msg0=None): from email import Charset, Parser, MIMEMessage if not isinstance(data, unicode): raise TypeError('data must be a unicode.') p = Parser.FeedParser() p.feed(data) msg1 = p.close() csmap = Charset.Charset(config.MESSAGE_CHARSET) attach_msgs = [] # Re-encode the headers. headers = [] labels = [] for (k, v) in msg1.items(): v = rmsp(v) if not v: continue kl = k.lower() if kl == 'x-forward-msg': attach_msgs.extend(get_numbers(v)) continue if kl == 'label': labels = v.split(',') continue headers.append((k.encode('ascii', 'strict'), encode_header(v, csmap))) # Remove all the existing headers. for k in msg1.keys(): del msg1[k] # Reattach the headers. for (k, v) in headers: msg1[k] = v # Change the body. data = msg1.get_payload(decode=False) try: # First try to encode with us-ascii. data.encode('ascii', 'strict') # Succeed. msg1.set_charset('ascii') except UnicodeError: # Re-encode the body. if not csmap.output_charset: csmap = Charset.Charset('utf-8') msg1.set_charset(str(csmap.output_charset)) data = data.encode(str(csmap.output_codec), 'replace') msg1.set_payload(data) # Attach other messages (for forwarding). if attach_msgs: for loc in attach_msgs: p = Parser.FeedParser() p.feed(corpus.get_message(loc)) msg1 = mime_add(msg1, MIMEMessage.MIMEMessage(p.close())) # Integrate other mime objects. if msg0 and msg0.is_multipart(): for obj in msg0.get_payload()[1:]: msg1 = mime_add(msg1, obj) validate_message_structure(msg1) return (msg1, labels)
def construct_mail(self): """ compiles the information contained in this envelope into a :class:`email.Message`. """ # build body text part textpart = MIMEText(self.body.encode('utf-8'), 'plain', 'utf-8') # wrap it in a multipart container if necessary if self.attachments or self.sign or self.encrypt: msg = MIMEMultipart() msg.attach(textpart) else: msg = textpart headers = self.headers.copy() # add Message-ID if 'Message-ID' not in headers: headers['Message-ID'] = [email.Utils.make_msgid()] if 'User-Agent' in headers: uastring_format = headers['User-Agent'][0] else: uastring_format = settings.get('user_agent').strip() uastring = uastring_format.format(version=__version__) if uastring: headers['User-Agent'] = [uastring] # copy headers from envelope to mail for k, vlist in headers.items(): for v in vlist: msg[k] = encode_header(k, v) # add attachments for a in self.attachments: msg.attach(a.get_mime_representation()) return msg
def construct_mail(self): """ compiles the information contained in this envelope into a :class:`email.Message`. """ # Build body text part. To properly sign/encrypt messages later on, we # convert the text to its canonical format (as per RFC 2015). canonical_format = self.body.encode('utf-8') canonical_format = canonical_format.replace('\\t', ' ' * 4) textpart = MIMEText(canonical_format, 'plain', 'utf-8') # wrap it in a multipart container if necessary if self.attachments: inner_msg = MIMEMultipart() inner_msg.attach(textpart) # add attachments for a in self.attachments: inner_msg.attach(a.get_mime_representation()) else: inner_msg = textpart if self.sign: plaintext = crypto.email_as_string(inner_msg) logging.debug('signing plaintext: ' + plaintext) try: signatures, signature_str = crypto.detached_signature_for( plaintext, self.sign_key) if len(signatures) != 1: raise GPGProblem(("Could not sign message " "(GPGME did not return a signature)")) except gpgme.GpgmeError as e: if e.code == gpgme.ERR_BAD_PASSPHRASE: # If GPG_AGENT_INFO is unset or empty, the user just does # not have gpg-agent running (properly). if os.environ.get('GPG_AGENT_INFO', '').strip() == '': msg = "Got invalid passphrase and GPG_AGENT_INFO\ not set. Please set up gpg-agent." raise GPGProblem(msg) else: raise GPGProblem(("Bad passphrase. Is " "gpg-agent running?")) raise GPGProblem(str(e)) micalg = crypto.RFC3156_micalg_from_algo(signatures[0].hash_algo) unencrypted_msg = MIMEMultipart('signed', micalg=micalg, protocol= 'application/pgp-signature') # wrap signature in MIMEcontainter stype = 'pgp-signature; name="signature.asc"' signature_mime = MIMEApplication(_data=signature_str, _subtype=stype, _encoder=encode_7or8bit) signature_mime['Content-Description'] = 'signature' signature_mime.set_charset('us-ascii') # add signed message and signature to outer message unencrypted_msg.attach(inner_msg) unencrypted_msg.attach(signature_mime) unencrypted_msg['Content-Disposition'] = 'inline' else: unencrypted_msg = inner_msg if self.encrypt: plaintext = crypto.email_as_string(unencrypted_msg) logging.debug('encrypting plaintext: ' + plaintext) try: encrypted_str = crypto.encrypt(plaintext, self.encrypt_keys.values()) except gpgme.GpgmeError as e: raise GPGProblem(str(e)) outer_msg = MIMEMultipart('encrypted', protocol='application/pgp-encrypted') version_str = 'Version: 1' encryption_mime = MIMEApplication(_data=version_str, _subtype='pgp-encrypted', _encoder=encode_7or8bit) encryption_mime.set_charset('us-ascii') encrypted_mime = MIMEApplication(_data=encrypted_str, _subtype='octet-stream', _encoder=encode_7or8bit) encrypted_mime.set_charset('us-ascii') outer_msg.attach(encryption_mime) outer_msg.attach(encrypted_mime) else: outer_msg = unencrypted_msg headers = self.headers.copy() # add Message-ID if 'Message-ID' not in headers: headers['Message-ID'] = [email.Utils.make_msgid()] if 'User-Agent' in headers: uastring_format = headers['User-Agent'][0] else: uastring_format = settings.get('user_agent').strip() uastring = uastring_format.format(version=__version__) if uastring: headers['User-Agent'] = [uastring] # copy headers from envelope to mail for k, vlist in headers.items(): for v in vlist: outer_msg[k] = encode_header(k, v) return outer_msg
def construct_mail(self): """ compiles the information contained in this envelope into a :class:`email.Message`. """ # Build body text part. To properly sign/encrypt messages later on, we # convert the text to its canonical format (as per RFC 2015). canonical_format = self.body.encode("utf-8") canonical_format = canonical_format.replace("\\t", " " * 4) textpart = MIMEText(canonical_format, "plain", "utf-8") # wrap it in a multipart container if necessary if self.attachments: inner_msg = MIMEMultipart() inner_msg.attach(textpart) # add attachments for a in self.attachments: inner_msg.attach(a.get_mime_representation()) else: inner_msg = textpart if self.sign: plaintext = crypto.email_as_string(inner_msg) logging.debug("signing plaintext: " + plaintext) try: signatures, signature_str = crypto.detached_signature_for(plaintext, self.sign_key) if len(signatures) != 1: raise GPGProblem(("Could not sign message " "(GPGME did not return a signature)")) except gpgme.GpgmeError as e: if e.code == gpgme.ERR_BAD_PASSPHRASE: # If GPG_AGENT_INFO is unset or empty, the user just does # not have gpg-agent running (properly). if os.environ.get("GPG_AGENT_INFO", "").strip() == "": raise GPGProblem(("Bad passphrase and " "GPG_AGENT_INFO not set. Please setup " "gpg-agent.")) else: raise GPGProblem(("Bad passphrase. Is " "gpg-agent running?")) raise GPGProblem(str(e)) micalg = crypto.RFC3156_micalg_from_algo(signatures[0].hash_algo) outer_msg = MIMEMultipart("signed", micalg=micalg, protocol="application/pgp-signature") # wrap signature in MIMEcontainter signature_mime = MIMEApplication( _data=signature_str, _subtype='pgp-signature; name="signature.asc"', _encoder=encode_7or8bit ) signature_mime["Content-Description"] = "signature" signature_mime.set_charset("us-ascii") # add signed message and signature to outer message outer_msg.attach(inner_msg) outer_msg.attach(signature_mime) outer_msg["Content-Disposition"] = "inline" else: outer_msg = inner_msg headers = self.headers.copy() # add Message-ID if "Message-ID" not in headers: headers["Message-ID"] = [email.Utils.make_msgid()] if "User-Agent" in headers: uastring_format = headers["User-Agent"][0] else: uastring_format = settings.get("user_agent").strip() uastring = uastring_format.format(version=__version__) if uastring: headers["User-Agent"] = [uastring] # copy headers from envelope to mail for k, vlist in headers.items(): for v in vlist: outer_msg[k] = encode_header(k, v) return outer_msg
def construct_mail(self): """ compiles the information contained in this envelope into a :class:`email.Message`. """ # Build body text part. To properly sign/encrypt messages later on, we # convert the text to its canonical format (as per RFC 2015). canonical_format = self.body.encode('utf-8') canonical_format = canonical_format.replace('\\t', ' ' * 4) textpart = MIMEText(canonical_format, 'plain', 'utf-8') # wrap it in a multipart container if necessary if self.attachments: inner_msg = MIMEMultipart() inner_msg.attach(textpart) # add attachments for a in self.attachments: inner_msg.attach(a.get_mime_representation()) else: inner_msg = textpart if self.sign: plaintext = crypto.email_as_string(inner_msg) logging.info('signing plaintext: ' + plaintext) try: signatures, signature_str = crypto.detached_signature_for( plaintext, self.sign_key) if len(signatures) != 1: raise GPGProblem(("Could not sign message " "(GPGME did not return a signature)")) except gpgme.GpgmeError as e: if e.code == gpgme.ERR_BAD_PASSPHRASE: # If GPG_AGENT_INFO is unset or empty, the user just does # not have gpg-agent running (properly). if os.environ.get('GPG_AGENT_INFO', '').strip() == '': raise GPGProblem( ("Bad passphrase and " "GPG_AGENT_INFO not set. Please setup " "gpg-agent.")) else: raise GPGProblem(("Bad passphrase. Is " "gpg-agent running?")) raise GPGProblem(str(e)) micalg = crypto.RFC3156_micalg_from_algo(signatures[0].hash_algo) outer_msg = MIMEMultipart('signed', micalg=micalg, protocol='application/pgp-signature') # wrap signature in MIMEcontainter signature_mime = MIMEApplication( _data=signature_str, _subtype='pgp-signature; name="signature.asc"', _encoder=encode_7or8bit) signature_mime['Content-Description'] = 'signature' signature_mime.set_charset('us-ascii') # add signed message and signature to outer message outer_msg.attach(inner_msg) outer_msg.attach(signature_mime) outer_msg['Content-Disposition'] = 'inline' else: outer_msg = inner_msg headers = self.headers.copy() # add Message-ID if 'Message-ID' not in headers: headers['Message-ID'] = [email.Utils.make_msgid()] if 'User-Agent' in headers: uastring_format = headers['User-Agent'][0] else: uastring_format = settings.get('user_agent').strip() uastring = uastring_format.format(version=__version__) if uastring: headers['User-Agent'] = [uastring] # copy headers from envelope to mail for k, vlist in headers.items(): for v in vlist: outer_msg[k] = encode_header(k, v) return outer_msg