def get_text(self, mess): text =[] html =[] char_set = mess.get_charsets() for part in mess.walk(): type = part.get_content_type() charset = part.get_content_charset() if type == 'text/plain': body = part.get_payload() # Determine what character set they use and convert to utf8 body = quopri.decodestring(body) body = decode_heuristically(body, enc = charset, denc = "utf-8") if body != None: text.append(body[0]) elif type == 'multipart/alternative': body = part.get_payload() if isinstance(body,ListType): for b in body: tx,ht = self.get_text(b) text.append(tx) html.append(ht) else: body = quopri.decodestring(body) body = quopri.decodestring(body) body = decode_heuristically(body, enc = charset, denc = "utf-8") if body != None: htlm.append(body[0]) return text,html
def handleOutgoingMail (ctx, mail): #imprime(mail) uri = __aps__['uri'] if uri: found = None for line in mail.head: if line.lower ().startswith ('list-unsubscribe:'): found = line break if found is None: # Tentando extrair link embutido na newsletter if mail.body is not None: soup = BeautifulSoup(quopri.decodestring(mail.body), "html.parser") linkSair = soup.find('a',id='linkUnsubscribe') if linkSair is not None: if linkSair['href'].lower().find("form.do") != -1: novoLink = linkSair['href'] else: # Substituindo link pelo mnemônico, a fim de permitir reconhecimento em alguns leitores de e-mails novoLink = (uri % linkSair['href'][linkSair['href'].lower().find("uid=")+4:]) er = re.compile(r"<a[^<]*linkUnsubscribe.*?>",re.IGNORECASE|re.DOTALL) linkInserido = quopri.decodestring(re.search(er,mail.body).group()) erStyle = re.compile(r"(style=.*?)[a-z].=",re.IGNORECASE|re.DOTALL) styleAdd = re.search(erStyle,linkInserido).group(1) if re.search(erStyle,linkInserido) else "" mail.body = re.sub(er,quopri.encodestring(("<a %s href=%s>" % (styleAdd,novoLink))),mail.body) mail.head.append ('List-Unsubscribe: <%s>' % novoLink) #imprime(mail) return
def hashLoginPassword(username, password, sessionid): """ Hashes login password """ username = quopri.decodestring(username) username = username.lower() password = quopri.decodestring(password) sha = hashlib.sha1(username + password).hexdigest() sha = hashlib.sha1(sha + sessionid).hexdigest() return sha
def headerUnicode(mimebytestring): h = email.header.decode_header(mimebytestring) res = [] for hh in h: if hh[1] is None: res.append(unicode(quopri.decodestring(hh[0]))) else: res.append(unicode(quopri.decodestring(hh[0]).decode(hh[1]))) return u" ".join(res)
def maintain_rfc_parse(message): """ This function parses an email and returns an array with different parts of the message but leaves the email still RFC compliant so that it works with Mail-Parser Plus app. Attachment headers are left in tact. :param message: This represents the email to be checked for attached email. :type message: email message object :return: Returns a email message formatted as a string :rtype: str """ if not message.is_multipart(): reformatted_message = quopri.decodestring( message.as_string().encode('ascii', 'ignore') ).decode("utf-8",'ignore') return reformatted_message boundary = message.get_boundary() new_payload = '--' + boundary for i in message.get_payload(): content_type = i.get_content_type() extension = str(os.path.splitext(i.get_filename() or '')[1]).lower() if extension in TEXT_FILE_EXTENSIONS or content_type in SUPPORTED_CONTENT_TYPES or \ i.get_content_maintype() == 'text': text_content = i.as_string().encode('ascii', 'ignore') text_content = quopri.decodestring(text_content).decode("utf-8",'ignore') new_payload += '\n' + text_content else: replace = re.sub(r'(?:\n\n)[\s\S]+',r'\n\n#UNSUPPORTED_ATTACHMENT:',i.as_string()) filename = i.get_filename() charset = i.get_content_charset() try: md5 = hashlib.md5(i.get_payload(None,True)).hexdigest() sha256 = hashlib.sha256(i.get_payload(None,True)).hexdigest() except: md5 = '' sha256 = '' replace_string = """ file_name = %(filename)s type = %(content_type)s charset = %(charset)s md5 = %(md5)s sha256 = %(sha256)s """ metadata = replace_string % dict( content_type=content_type, filename=filename, charset=charset, md5=md5, sha256=sha256, ) new_payload += '\n' \ + replace \ + metadata new_payload += '\n--' + boundary new_payload += '--' message.set_payload(new_payload) return message.as_string()
def set_message(self, message): self.sender = get_sender(message['Subject']) self.to = message['To'] if message.is_multipart(): src = unicode(quopri.decodestring(message.get_payload()[0])) else: src = unicode(quopri.decodestring(message.get_payload())) self.body, rest = split_body(src) self.loc = get_loc(rest) self.url = get_link(rest) self.raw = message.as_string() self.sent = datetime.datetime(*rfc822.parsedate(message['Date'])[:6])
def decodeContentType(part): tmp = re.search('(?si)Content-Type: +(.*?)(?: |\n|;)', part) if tmp!=None: content_type = tmp.group(1) else: content_type = '' tmp = re.search('charset="{0,1}([A-Za-z0-9\-]+)', part) if tmp!=None: enc = tmp.group(1) else: enc = '' tmp = re.search('(?s).*?(?:\n\n|\r\n\r\n)(.*)', part) if tmp!=None: body = tmp.group(1) else: body = '' tmp = re.search('(?si)(content-disposition: *attachment)', part) if tmp == None: tmp = re.search('(?si)(content-disposition: *inline)', part) if tmp!=None: attachment = 1 tmp = re.search('(?si)content-type:.*?(?:\n\n|\r\n\r\n)(.*)', body) if tmp!=None: body = tmp.group(1) else: attachment = 0 tmp = re.search('Content-Transfer-Encoding: +([a-zA-Z0-9\-]*)', part) if tmp!=None: cte = tmp.group(1) if cte.lower() == 'base64' and (content_type=='text/plain' or content_type=='text/html') and attachment==0: if (enc==''): body = base64.b64decode(body.encode('utf-8')).decode('utf-8', 'replace') else: body = base64.b64decode(body.encode('utf-8')).decode(enc, 'replace') if cte.lower() == 'quoted-printable' and (content_type=='text/plain' or content_type=='text/html') and attachment==0: if enc=='': body = quopri.decodestring(body.encode('utf-8')).decode('utf-8') else: body = quopri.decodestring(body.encode('utf-8')).decode(enc) tmp = re.search('(?si)filename="{0,1}(.*?)(?:"|\n)', part) if tmp!=None: filename = decodeHeader(tmp.group(1)) else: filename = '' tmp = re.search('(?si)Content-Id: *<([^>]*)>', part) if tmp!=None: content_id = tmp.group(1) else: content_id = '' return content_type, enc, body, attachment, filename, content_id
def do_search(self, request): import quopri, re a = request.args login = request.getUser() obj = yield self.buckets['mailmeta'].get(login) user_emails = obj.get_data().keys() terms = a.get('terms')[0] print 'TERMS:', terms res = yield self.buckets['mailbody'].search(terms) request.write('search found this:') r1 = re.compile(r".*Delivered-To:\s([a-zA-Z0-9.-]+)@.*?\n.*", re.DOTALL) # is this all? for doc in res['docs']: data = doc['value'] m = r1.match(data) if m.group(1) != login: continue # this msg was not for this user, skip it. content_trans = 'Content-Transfer-Encoding: quoted-printable' if content_trans in data: headers, _, body = data.partition(content_trans) else: headers, body = data, '' out = headers.decode('ascii') # headers should always be ascii-onl s = quopri.decodestring(body).decode('utf-8', errors='replace') print type(out),type(s) out = out + s out = out.encode('utf-8') request.write('<pre>' + out + '</pre>')
def str_conv(str, ): """ Конвертирование Subject во входящих Email """ error = False if not str: return str, error values = str.split('\n') value_results = [] for value in values: match = re.search(r'=\?((?:\w|-)+)\?(Q|q|B|b)\?(.+)\?=', value) if match: encoding, type_, code = match.groups() if type_.upper() == 'Q': value = quopri.decodestring(code) elif type_.upper() == 'B': value = base64.decodestring(code) try: value = str_encode(string=value, encoding=encoding, ) except UnicodeDecodeError: value = str_encode(string=value, encoding=encoding, errors='replace', ) error = True value_results.append(value) if len(value_results) > 0: return ''.join(value_results), error return str, error
def test_notifications_for_new_reply(self): ws = self.portal['workspaces']['workspace-1'] people = self.portal['people'] post = ws['post-2'] self.mailhost.messages = [] login(self.portal, 'test_user_1') helpers.create_reply(post, 'new-reply', text=richtextify(u"<p>test</p><p>test</p>123")) self.assertEqual(len(self.mailhost.messages), 2) recipients = [unicode(m['To']) for m in self.mailhost.messages] expected_recipients = [] for uid in ['test_user_1', 'test_user_2']: name = getattr(people.get(uid, None), 'title', uid) email = getattr(people.get(uid, None), 'emailAddress', None) expected_recipients.append('{0} <{1}>'.format(name, email)) self.assertEqual(recipients, expected_recipients) for message in self.mailhost.messages: self.assertEqual(unicode(message['Subject']), u"[Plone site] " + u"Test User replied to “Post 2” in Workspace 1") msg_text = quopri.decodestring(message.get_payload()) expected_msg_text = u"test\n\ntest\n123" self.assertEqual(msg_text, expected_msg_text)
def detachFile(self, att_name, filecontent, date=None): """ Writes the file and return the corresponding html The html file will store a link to the detached file If the file already exists, we compute a new name and create a link to the computed name file and to the file that has the same name... date is the date to use for the detached file """ att_name=os.path.split(att_name)[1] # sometimes, the name of the attached file contains the whole path which is not wanted if att_name.find('=?') != -1: # If the filename is encoded, we decode it filename=quopri.decodestring(self.decode_Q(att_name).encode('latin1')) # and encode it in latin1 (you may change this to utf-8) else: filename=att_name filelist=[filename] # # we write the attached file # Sometimes, due to formating, we find \n, \r or \t characters in the filenames. So we cut them off ofname=os.path.join(prm.attachedFilesDir, filename.strip().replace('\n','').replace('\r','').replace('?','').expandtabs(0)) if os.path.exists(ofname): i=1 fname=ofname sfname=os.path.splitext(fname) while os.path.exists(fname): fname="%s[%d]%s" % (sfname[0], i, sfname[1]) i+=1 filelist.append(os.path.split(fname)[-1]) ofname=fname # the outfile name is the new one of=open(ofname,'wb') of.write(filecontent) of.close() if date: os.utime(ofname, (date, date)) return self.getHtmlLinksFileContent(filelist)
def decode_body(self, bodyonly, charset, encoding): new_body = "" if encoding=="base64": try : new_body = base64.b64decode(bodyonly) except: dbgprint("into except base64") pass elif encoding=="quoted-printable" : try: #new_body = decode_header(new_body)[0][0].decode('utf-8') #new_body = str(quopri.decodestring(new_body).decode('utf-8')).strip() new_body = quopri.decodestring(bodyonly) except: dbgprint("into except qp") pass else : new_body = bodyonly dbgprint("unknown encoding:", encoding) #now decode the charset try : new_body = new_body.decode(charset) except: #make sure a string is passed, also if failed new_body = "".join(map(chr,new_body)) dbgprint("decoding failed") pass return new_body
def get_msg_content(msg): from BeautifulSoup import BeautifulSoup text='' last=msg['id'] if msg.is_multipart(): text=get_from_mp(msg) else: text=msg.get_payload(decode=True) text=quopri.decodestring(text) enc=BeautifulSoup(text).originalEncoding msg['enc']=enc subre="<b><span style='font-weight:bold'>Subject:</span></b> Re:" print msg['subj_e'] if enc and enc in ['ISO-8859-2']: try: msg['text']=text.decode('cp1251') except: msg['text']=text.replace('\x98','').decode('cp1251') elif enc and enc not in ['utf8','utf-8']: msg['text']=text.decode(enc) else: msg['text']=text return msg['text']
def read(self, n = None): """ python.org: Read up to n bytes from the object and return them. :param n: How many bytes to read from the current position (0 means until EOF) :return: (bytes) Data; None if EOF :since: v0.2.00 """ raw_data = self.raw_read(n) decoded_data = (Binary.BYTES_TYPE() if (self.decoded_data is None) else self.decoded_data) if (raw_data is not None): if (raw_data[-1:] == QuotedPrintableDecoder.BINARY_EQUAL_SIGN): additional_raw_data = self.raw_read(3) if (additional_raw_data is not None): raw_data += additional_raw_data # decoded_data += decodestring(raw_data) # if (len(decoded_data) > n): self.decoded_data = decoded_data[n:] return decoded_data[:n]
def linksToEpisodesSY(msg): """extract the links to episodes in a seriesyonkis email""" # TESTED if msg is None: raise TypeError # TODO testing how to encode an email right #logging.info(repr(str_msg)) #syMsg = f.parsestr(str) #syMsg = f.parsestr(str_msg) #syMsg = msg # TODO: aclarar si esto es asi, o no. mientras tanto, esta funcion # falla con errores de encoding, asi que no me vale. # con nosetes funciona, con normal falla -> con encode # syMsg = quopri.decodestring(msg.encode("UTF-8")) # con nosetest falla, con normal funcion -> sin encode syMsg = quopri.decodestring(msg) soup = bs4.BeautifulSoup(syMsg) episodes = set() for link in soup.find_all("a"): cleanLink = link.get('href', '') if "capitulo" in cleanLink: episodes.add(cleanLink.decode()) lst = list(episodes) lst.sort() return lst
def _infer_text_fragment_inner(self, title, body, post_id): # dead code? If not needs to be refactored with langstrings body = sanitize_html(body, []) quote = self.body.replace("\r", "") try: # for historical reasons quote = quopri.decodestring(quote) except: pass quote = sanitize_html(quote, []) if quote != self.body: self.body = quote quote = quote.replace("\n", "") start = body.find(quote) lookin = 'message-body' if start < 0: xpath = "//div[@id='%s']/div[class='post_title']" % (post_id) start = title.find(quote) if start < 0: return None lookin = 'message-subject' xpath = "//div[@id='message-%s']//div[@class='%s']" % ( Post.uri_generic(post_id), lookin) tfi = self.db.query(TextFragmentIdentifier).filter_by( extract=self).first() if not tfi: tfi = TextFragmentIdentifier(extract=self) tfi.xpath_start = tfi.xpath_end = xpath tfi.offset_start = start tfi.offset_end = start + len(quote) return tfi
def decode_transfer_encoding(encoding, body): if encoding == "base64": return base64.b64decode(body) elif encoding == "quoted-printable": return quopri.decodestring(body) else: return body
def __init__(self, replay_response, method=None): self.reason = replay_response['status']['message'] self.status = replay_response['status']['code'] self.version = None if 'body_text' in replay_response: # JSON decoder returns unicode, not str, so this needs to be # encoded to properly reproduce content off the wire. self._content = replay_response['body_text'].encode('utf8') elif 'body_quoted_printable' in replay_response: # quopri.decodestring returns str, which is correct for content off # the wire. self._content = quopri.decodestring(replay_response['body_quoted_printable']) else: # .decode('base64') returns str, which is correct for content off # the wire. self._content = replay_response['body'].decode('base64') self.fp = StringIO(self._content) msg_fp = StringIO('\r\n'.join('{}: {}'.format(h, v) for h, v in replay_response['headers'].iteritems())) self.msg = HTTPMessage(msg_fp) self.msg.fp = None # httplib does this, okay? length = self.msg.getheader('content-length') self.length = int(length) if length else None # Save method to handle HEAD specially as httplib does self._method = method
def get(self): user = users.get_current_user() restaurant_name = self.request.get('restaurant_name') # self.response.write(restaurant_name) restaurant = RestaurantModel.query(RestaurantModel.name == restaurant_name).fetch()[0] # str = restaurant.payment str = quopri.decodestring(restaurant.payment) cart = CartModel.query(CartModel.user==user, CartModel.restaurant_name==restaurant_name).fetch()[0] cart_id = cart.key.id() ######################################################Save the customer information (user address|phone|notes)########################################################### cart.customer_address = self.request.get('customer_address') cart.customer_phone = self.request.get('customer_phone') cart.customer_time = self.request.get('customer_time') cart.customer_notes = self.request.get('customer_notes') cart.put() shipping_fee = restaurant.shipping_fee template = JINJA_ENVIRONMENT.get_template('templates/confirm.html') template_values = { 'restaurant_name': restaurant_name, 'total_cost': cart.total, 'shipping_fee': shipping_fee, 'payment': str, 'cart_id': cart_id, 'customer_address': cart.customer_address, 'customer_phone': cart.customer_phone, 'customer_time': cart.customer_time, 'customer_notes': cart.customer_notes, } self.response.write(template.render(template_values))
def _get_verification_data(self, email_address): """A private helper for public helpers below. Note: We have two different public helpers here for verification code and link so that functional tests don't need to deal with idioms like: vcode, ignored = get_verification_for_address(email_address). """ email_msg = mail.get_latest_email_sent_to(email_address) vcode = link = None if email_msg: # The body is encoded as quoted-printable. This affects any line # longer than a certain length. Decode now to not have to worry # about it in the regexen. body = quopri.decodestring(email_msg.get_payload()) # get code match = re.search( '(Here is your confirmation code:|Copy and paste the ' 'confirmation code below into the desktop application.)' '(.*?)(Enter|If you made|If you don)', body, re.S) if match: vcode = match.group(2).strip() else: vcode = None # get link match = re.search( 'confirm your (?:account|email address|reset):(.*)If', body, re.S) link = None if match: link = match.group(1).strip() return vcode, link
def parseUTCDateTime(cls, dt_str): m = re.match(r"(\w+ \w+ \d+ \d+:\d+:\d+ )(\S.*\S)( \d+)", dt_str, re.U) if m is None: logging.warning("Datetime has unknown format: '" + dt_str + "' " + repr(dt_str)) return (None, "format_unknown") try: tm = datetime.strptime(m.group(1) + m.group(3), r"%a %b %d %H:%M:%S %Y") except ValueError: logging.warning("Can't parse datetime from: '" + m.group(1) + m.group(3) + "'") return (None, "parsing_failed") try: tzname = m.group(2) tz = timezone(tzname) except UnknownTimeZoneError: # Alternative timezone formats newtzname = re.sub(r"^GMT\+03:30$", r"Asia/Tehran", tzname) newtzname = re.sub(r"^(\w+[+-])0?(\d*)[:.]00$", r"\1\2", newtzname) newtzname = re.sub(r"^(GMT[+-]\d*)$", r"Etc/\1", newtzname) newtzname = re.sub(r"^GMT$", r"Etc/GMT+0", newtzname) newtzname = re.sub(r"^(EDT)$", r"EST5\1", newtzname) newtzname = re.sub(r"^(CDT)$", r"CST6\1", newtzname) newtzname = re.sub(r"^(MDT)$", r"MST7\1", newtzname) newtzname = re.sub(r"^(PDT)$", r"PST8\1", newtzname) newtzname = re.sub(r"^PST$", r"Etc/GMT-8", newtzname) newtzname = re.sub(r"^CST$", r"Etc/GMT-6", newtzname) newtzname = re.sub(r"^JST$", r"Japan", newtzname) newtzname = re.sub(r"^MEZ$", r"CET", newtzname) newtzname = re.sub(r"^CEST$", r"CET", newtzname) newtzname = re.sub(r"^HAEC$", r"CET", newtzname) newtzname = re.sub(r"^HNEC$", r"CET", newtzname) newtzname = re.sub(r"^AKST$", r"US/Alaska", newtzname) newtzname = re.sub(r"^MESZ$", r"Europe/Berlin", newtzname) newtzname = re.sub(r"^AWST$", r"Australia/Perth", newtzname) newtzname = re.sub(r"^ACDT$", r"Australia/Adelaide", newtzname) newtzname = re.sub(r"^AEDT$", r"Australia/Sydney", newtzname) newtzname = re.sub(r"^AEST$", r"Australia/Brisbane", newtzname) newtzname = re.sub(r"^NZDT$", r"Pacific/Auckland", newtzname) newtzname = re.sub(r"^CAT$", r"Etc/GMT+2", newtzname) newtzname = re.sub(r"^SAST$", r"Africa/Johannesburg", newtzname) newtzname = re.sub(r"^BRT$", r"America/Recife", newtzname) # See if timezone is Quoted-Printable UTF-8 logging.debug(str(ord(newtzname[0])) +' ' + str(ord(newtzname[1])) + ' ' + str(len(newtzname)) + ' ' + repr(newtzname)) if re.search('^[=A-Fa-f0-9 ]a$', newtzname): logging.debug("Trying for Quoted-Printable UTF-8 string for timezone") newtzname = decodestring(newtzname).decode('utf-8') if newtzname == u'\u041c\u043e\u0441\u043a\u043e\u0432\u0441\u043a\u043e\u0435 \u043b\u0435\u0442\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f': newtzname = "Europe/Moscow" logging.debug("Changed timezone from '" + tzname + "' to '" + newtzname + "'") try: tz = timezone(newtzname) except UnknownTimeZoneError: logging.warning("Unknown timezone: '" + tzname + "'") return (None, "timezone_unknown") try: tm = tz.localize(tm) except (ValueError, NonExistentTimeError): logging.warning("Error while localizing datetime '" + tm.strftime(r"%d/%m/%Y %H:%M:%S") + "' to '" + tz.zone + "'") return (None, "localizing_failed") logging.debug("UTC time parsed: '" + tm.astimezone(pytz.utc).strftime(r"%d/%m/%Y %H:%M:%S %Z") + "'") return (tm.astimezone(pytz.utc), "")
def process_message(self, peer, mailfrom, rcpttos, data): print 'Received mail from %s to %s.' % (mailfrom, rcpttos,) mail = email.message_from_string(data) subject = email.header.decode_header(mail['Subject'])[0][0] message_id = email.header.decode_header(mail['Message-ID'])[0][0] in_reply_to = email.header.decode_header(mail['In-Reply-To'])[0][0] text = mail.get_payload() encoding = mail['Content-Transfer-Encoding'] if encoding != None: if encoding.lower() in ('7bit', '8bit', 'binary'): pass # no conversion needed elif encoding.lower() == 'base64': text = base64.b64decode(text) elif encoding.lower() == 'quoted-printable': text = quopri.decodestring(text) else: print('WARNING: Unknown encoding, skipping decoding: ' '%s\n' 'text:\n%s\n' % (encoding, text)) charset = mail.get_content_charset() text = utf8(text, charset) text = normalize_str(text) message_from_mail(mailfrom, rcpttos, subject, message_id, in_reply_to, text)
def __init__(self, message, message_id=None, gpg=None): """ :arg str message: raw text of the email :arg str message_id: IMAP message ID or maildir message path :arg gpg: :class:`GnuPG` instance or None (which will create one) """ Message.__init__(self, message) self._message_id = message_id if not gpg: self._gpg = GnuPG() else: self._gpg = gpg self._content_types = ["text/plain", "text/html", "application/pgp-signature", "application/pgp-keys", "application/octet-stream"] self._parts = [] for part in self.walk(): content_type = part.get_content_type() if content_type in self._content_types: payload = quopri.decodestring(part.get_payload().strip()) self._parts.append( (content_type, payload) ) self._parse_for_openpgp()
def test_notifications_for_new_post(self): ws = self.portal['workspaces']['workspace-1'] people = self.portal['people'] self.mailhost.messages = [] login(self.portal, 'test_user_1') post = helpers.create_post(ws, 'new-post', title=u"New Post", text=richtextify(u"<p>test</p><p>test</p>123")) self.assertEqual(len(self.mailhost.messages), 0) helpers.publish_post(post) self.assertEqual(len(self.mailhost.messages), 2) recipients = [unicode(m['To']) for m in self.mailhost.messages] expected_recipients = [] for uid in ws.getMemberIds(): name = getattr(people.get(uid, None), 'title', uid) email = getattr(people.get(uid, None), 'emailAddress', None) if not email: continue expected_recipients.append('{0} <{1}>'.format(name, email)) self.assertEqual(recipients, expected_recipients) for message in self.mailhost.messages: self.assertEqual(unicode(message['Subject']), u"[Plone site] " + u"New post: “New Post” by Test User in Workspace 1") msg_text = quopri.decodestring(message.get_payload()) expected_msg_text = u"test\n\ntest\n123" self.assertEqual(msg_text, expected_msg_text)
def _decode_single_body(self): self.body = self.body.strip() cte = self.headers.get('Content-Transfer-Encoding', '').lower() if 'quoted-printable' in cte: LOG.debug("Detected quoted-printable encoding, decoding") self.body = quopri.decodestring(self.body) if 'base64' in cte: LOG.debug("Detected base64 encoding, decoding") try: self.body = base64.decodestring(self.body) except base64.binascii.Error: LOG.info("base64 decoder failed, trying partial decoding") self.body = base64_partial_decode(self.body) LOG.debug("Detected charset: %s", self.charset) try: self.body = self.body.decode( validate_charset(self.charset) and self.charset or 'ascii', 'strict' ) except UnicodeDecodeError: LOG.info('Error during strict decoding') self.email_stats['charset_errors'] = 1 self.body = self.body.decode( validate_charset(self.charset) and self.charset or 'ascii', 'ignore' ) if self._guess_html(): LOG.debug("Message recognized as HTML") self._parse_html() else: LOG.debug("Message recognized as plaintext")
def parse_message(msg): """returns a tuple (<from email address>, <subject>, <body>) the function will attempt to decode the email supported encodings are "quoted-printable" and "base64" not supported - emails using language - specific encodings """ sender = msg.get('From') subject = msg.get('Subject').replace('\r','').replace('\n','') if msg.is_multipart(): # BL: Wind always sends 2 payloads: 1 plain-text, the other html msg = msg.get_payload()[0] if isinstance(msg, list): raise CannotParseEmail(sender, subject) ctype = msg.get_content_type()#text/plain only raw_body = msg.get_payload()#text/plain only encoding = msg.get('Content-Transfer-Encoding') if encoding == 'base64': body = base64.b64decode(raw_body) elif encoding == 'quoted-printable': body = quopri.decodestring(raw_body) else: body = raw_body return (sender, subject, body)
def parse_email_set_var(context, address, expression): assert context.persona is not None, u'no persona is setup' msgs = context.mail.user_messages(address) assert msgs, u'no email received' mail = email.message_from_string(msgs[-1]) text = quopri.decodestring(mail.get_payload()).decode("utf-8") parse_text(context, text, expression)
def decode_transfer_encoding(encoding, body): if encoding == 'base64': return _base64_decode(body) elif encoding == 'quoted-printable': return quopri.decodestring(body) else: return body
def parse_part(part): part = part.strip(); # parse the part description (first three lines) # get Content-Type pat1 = 'Content-Type: (.*)'; pat1_res = re.search(pat1, part, re.I); ctype = pat1_res.groups()[0].strip() if pat1_res else ''; # get Content-Transfer-Encoding pat2 = 'Content-Transfer-Encoding: (.*)'; pat2_res = re.search(pat2, part, re.I); cenc = pat2_res.groups()[0].strip() if pat2_res else ''; # get Content-Location pat3 = 'Content-Location: (.*)'; pat3_res = re.search(pat3, part, re.I); cloc = pat3_res.groups()[0].strip() if pat3_res else ''; # check part description if cenc == '': return (-1, ctype, cenc, cloc, ''); # parse the contents try: contents = part.split('\n\n', 1)[1]; except: contents = part.split('\n\r\n', 1)[1]; if cenc == 'base64': s = base64.b64decode(contents); elif cenc == 'quoted-printable': s = quopri.decodestring(contents); return (0, ctype, cenc, cloc, s);
def decode_mime(msg_str): pattern = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=' match = re.search(pattern, msg_str) if match: charset, encoding, text = match.groups() if encoding is 'B': byte_string = base64.b64decode(text) elif encoding is 'Q': byte_string = quopri.decodestring(text) return byte_string.decode(charset) else: return msg_str
def decode(self, line): line = self._consumed_lines + line # add potentially stored previous lines self._consumed_lines = '' m = QuotedPrintableDecoder.quoted.match(line) if m: line = line[:m.start(1)] + line[m.end(1):] # remove the matched group 1 from line decoded_line = quopri.decodestring(line).decode('UTF-8') # Escape newlines, but preserve the last one (which must be '\n', since we read the file in universal newliens mode) decoded_line = decoded_line[:-1].replace('\r\n', '\\n') decoded_line = decoded_line.replace('\n', '\\n') return decoded_line + '\n' return line
def save_mail(self, email): [(subj, code)] = decode_header(email[1]['Subject']) new_email = Email(title=subj.decode(code), sender=email[1]['From'], date=email[1]['Date'], text=quopri.decodestring( email[0].encode('utf-8')).decode( 'utf-8', 'backslashreplace')) new_email.save() return new_email
def from_html(html, transfer_encoding): inputs = html if transfer_encoding == 'base64': inputs = base64.urlsafe_b64decode(inputs) elif transfer_encoding == 'quoted-printable' or transfer_encoding == '8bit' or transfer_encoding == '7bit': inputs = quopri.decodestring(base64.urlsafe_b64decode(inputs)) soup = BeautifulSoup(inputs) # kill all script and style elements for script in soup(["script", "style"]): script.extract() return clean_str(soup.get_text())
def replace(msg: Message, old, new) -> Message: content_type = msg.get_content_type() if (content_type.startswith("image/") or content_type.startswith("video/") or content_type.startswith("audio/") or content_type == "multipart/signed" or content_type.startswith("application/") or content_type == "text/calendar" or content_type == "text/directory" or content_type == "text/csv" or content_type == "text/x-python-script"): LOG.d("not applicable for %s", content_type) return msg if content_type in ("text/plain", "text/html"): encoding = get_encoding(msg) payload = msg.get_payload() if type(payload) is str: if encoding == EmailEncoding.QUOTED: LOG.d("handle quoted-printable replace %s -> %s", old, new) # first decode the payload try: new_payload = quopri.decodestring(payload).decode("utf-8") except UnicodeDecodeError: LOG.w("cannot decode payload:%s", payload) return msg # then replace the old text new_payload = new_payload.replace(old, new) clone_msg = copy(msg) clone_msg.set_payload(quopri.encodestring( new_payload.encode())) return clone_msg else: clone_msg = copy(msg) new_payload = payload.replace(encode_text(old, encoding), encode_text(new, encoding)) clone_msg.set_payload(new_payload) return clone_msg elif content_type in ( "multipart/alternative", "multipart/related", "multipart/mixed", "message/rfc822", ): new_parts = [] for part in msg.get_payload(): new_parts.append(replace(part, old, new)) clone_msg = copy(msg) clone_msg.set_payload(new_parts) return clone_msg LOG.w("Cannot replace text for %s", msg.get_content_type()) return msg
def parse_and_split_field(field): '''Parses a VCARD field. field is a tuple consisting of the field name and the field content. The content is decoded (if quoted printable) and de-splited by ";". The return value is a list consisting of the splitted values.''' result = [] if len(field) != 2: return result if field[0].find("ENCODING=QUOTED-PRINTABLE") > 0: result = quopri.decodestring(field[1]).split(";") else: result = field[1].split(";") return result
def encoded_words_to_text(encoded_words): encoded_word_regex = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=' groups = re.match(encoded_word_regex, encoded_words) if not groups: return encoded_words charset, encoding, encoded_text = re.match(encoded_word_regex, encoded_words).groups() if encoding == 'B': byte_string = base64.b64decode(encoded_text) elif encoding == 'Q': byte_string = quopri.decodestring(encoded_text) return byte_string.decode(charset)
def process_request(self, request): if request.method == 'POST' and 'HTTP_X_APPENGINE_BLOBUPLOAD' in request.META and request.META['HTTP_X_APPENGINE_BLOBUPLOAD'] == 'true': request.POST = request.POST.copy() log.info('POST before decoding: %s' % request.POST) for key in request.POST: if key.startswith('_') or key == u'csrfmiddlewaretoken': continue value = request.POST[key] if isinstance(value,(str, unicode)): request.POST[key] = unicode(quopri.decodestring(value), 'iso_8859-2') log.info('POST after decoding: %s' % request.POST) return None
def get_email_body(msg, message_type): output = "" if "multipart" in message_type: for part in msg.get_payload(): m_type = part["Content-Type"].split()[0].replace(";", "") if "multipart" in m_type: output = get_email_body(part, m_type) elif "text" in m_type and "html" not in m_type: try: encoded_word_regex = r"=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=" charset, encoding, encoded_text = re.match( encoded_word_regex, part.get_payload()).groups() if encoding is "B": body = base64.b64decode(encoded_text) elif encoding is "Q": body = quopri.decodestring(encoded_text) output = body.decode() # output = base64.urlsafe_b64decode(part.get_payload()).decode(encoding) except: try: output = base64.b64decode(part.get_payload()).decode() except: output = part.get_payload() break elif "text" in m_type and "html" not in m_type: try: encoded_word_regex = r"=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=" charset, encoding, encoded_text = re.match( encoded_word_regex, part.get_payload()).groups() if encoding is "B": body = base64.b64decode(encoded_text) elif encoding is "Q": body = quopri.decodestring(encoded_text) output = body.decode() except: try: output = base64.b64decode(part.get_payload()).decode() except: output = part.get_payload() return output
def get_tracking(sdata, account, shipper): """Parse tracking numbers from email subject lines""" _LOGGER.debug("Searching for tracking numbers for (%s)", shipper) tracking = [] pattern = None mail_list = sdata.split() body = None if shipper == "usps": pattern = re.compile(r"{}".format(const.USPS_TRACKING_PATTERN)) elif shipper == "ups": pattern = re.compile(r"{}".format(const.UPS_TRACKING_PATTERN)) elif shipper == "fedex": pattern = re.compile(r"{}".format(const.FEDEX_TRACKING_PATTERN)) elif shipper == "dhl": body = True pattern = re.compile(r"{}".format(const.DHL_TRACKING_PATTERN)) for i in mail_list: typ, data = account.fetch(i, "(RFC822)") for response_part in data: if not isinstance(response_part, tuple): continue msg = email.message_from_bytes(response_part[1]) if body is None: email_subject = msg["subject"] found = pattern.findall(email_subject) if len(found) > 0: _LOGGER.debug( "Found (%s) tracking number in email: (%s)", shipper, found[0] ) if found[0] in tracking: continue tracking.append(found[0]) continue _LOGGER.debug("No tracking number found for %s", shipper) else: # Search in email body for tracking number email_msg = quopri.decodestring(str(msg.get_payload(0))) email_msg = email_msg.decode("utf-8") found = pattern.findall(email_msg) if len(found) > 0: _LOGGER.debug( "Found (%s) tracking number in email: %s", shipper, found[0] ) if found[0] in tracking: continue tracking.append(found[0]) continue _LOGGER.debug("No tracking number found for %s", shipper) return tracking
def save_mail(self, i_d, filename='email_data.csv', verbose=False): """ Writes email data to csv ARGS: mail - logged in mail object i_d - list of i_ds ids of messages to get filename - string ending in .csv (default: 'email_data.csv') name of file to write to Returns: None, saves data to csv """ csv_file = open(filename, 'w', encoding='utf-8') csv_writer = csv.writer(csv_file) csv_writer.writerow( ['id', 'uid', 'from_', 'subject', 'msg', 'content_type']) for i in i_d: try: typ, data = self.mail.fetch(str(i).encode(), '(UID RFC822)') uid = email.message_from_bytes(data[0][0]) uid = uid.get_payload() uid = uid.split()[-3] meta = email.message_from_bytes(data[0][1]) from_ = meta['From'] subject = meta['Subject'] content_type = meta['Content-Type'].split(';')[0] msg = meta.get_payload() while type(msg) != str: msg = msg[0].get_payload() print(i) if verbose: print('UID: ', uid) print('From: ', from_) print('Subject: ', subject) print('Content-Type: ', content_type) print('Message: ', quopri.decodestring(msg)) from_, msg = self.clean_text(from_, msg) csv_writer.writerow( [i, uid, from_, subject, msg, content_type]) print('Message saved') except Exception as e: print(e)
def get_text(self): result = "" if self.content_type.startswith("text"): if self.encoding == "base64": self.data = base64.b64decode(self.data).decode() if self.encoding == "quoted-printable": self.data = quopri.decodestring(self.data).decode() return self.data for record in self.records: result = record.get_text() if result: return result return result
def parse_status_email_thread(self, data): statuses = [] for email_id in data[0].split(): response, message_data = self.connection.fetch( email_id, '(BODY.PEEK[TEXT])') message = "" for response_part in message_data: if isinstance(response_part, tuple): body = email.message_from_string(response_part[1]) # body if body.is_multipart(): for payload in body.get_payload(): message += quopri.decodestring(payload) else: message = quopri.decodestring(body.get_payload()) response, headers_data = self.connection.fetch( email_id, '(BODY[HEADER.FIELDS (SUBJECT FROM)])') headers = email.message_from_string(headers_data[0][1]) statuses.append({"from": headers['FROM'], "body": message}) return statuses
def info_from_html_for_naverpay(msg_content): global price, purchasing_item, purchasing_office soup = BeautifulSoup(msg_content, 'html.parser') soup.prettify() # 결제금액 for tag in soup.find_all('td'): temp = quopri.decodestring(tag.text) temp = temp.decode('utf-8') if "최종결제금액" in temp: price_index = temp.find("최종결제금액") price_content = temp[price_index + 6:] price = price_content.strip() break # case1:주문상품명만 if soup.find('html') is None: for tag in soup.find_all('td'): temp = quopri.decodestring(tag.text) temp = temp.decode('utf-8') if "주문상품" in temp: purchasing_index = temp.find("주문상품") purchasing_item = temp[purchasing_index + 4:] purchasing_item = purchasing_item.strip() purchasing_item = purchasing_item[:50].strip() purchasing_office = "none" break # case2:주문상품명,구매상점명 else: for tag in soup.find_all('td'): temp = quopri.decodestring(tag.text) temp = temp.decode('utf-8') if "판매자" in temp: purchasing_office_index = temp.find("판매자") purchasing_office = temp[purchasing_office_index + 10:purchasing_office_index + 150] purchasing_office = purchasing_office.strip() purchasing_item_index = temp.find("상품정보") purchasing_item = temp[purchasing_item_index + 10:] purchasing_item = purchasing_item.strip() break
def encoded_words_to_text(encoded_words): encoded_word_regex = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=' #กำหนดรูปแบบที่ต้องการค้นหา try: charset, encoding, encoded_text = re.match( encoded_word_regex, encoded_words).groups( ) #ค้นหาตามรูปแบบที่กำหนดโดยใช้ฟังก์ชั่น match if encoding is 'B': byte_string = base64.b64decode(encoded_text) elif encoding is 'Q': byte_string = quopri.decodestring(encoded_text) return byte_string.decode(charset) #ถอดรหัสเป็น utf-8 except: return encoded_words #ถ้าเกิดปัญหาอันเนื่องมาจากรูปแบบไม่ match กันจะคือค่าเดิมออกไป
def get_msg_payload(msg): encoding = msg.get('Content-Transfer-Encoding') payload = msg.get_payload() if type(payload) == list: a_msg = payload[0] # first is plaintext, second - html encoding = a_msg.get('Content-Transfer-Encoding') payload = a_msg.get_payload() DEBUG(u'Extracted email msg %r with encoding %r' % (payload, encoding)) if encoding == 'quoted-printable': payload = quopri.decodestring(payload) elif encoding == 'base64': payload = b64decode(payload) return payload
def arion_parse(self, payload): """Non-multipart but with the plaintext in HTML comment""" s = payload[:payload.index("-->")] lines = s.splitlines() # Fault tolerance, it changes around a bit try: amount = int(re.sub(r"[^0-9]", "", lines[9].split(": ")[1])) raw = quopri.decodestring(lines[11]).split(": ")[1] except IndexError: raise ValueError("2 Arion Bankmail without plaintext encoutered") # Not sure if nessesary or formed user input from user "Numi" skyring = raw.strip().decode("tis-620") return skyring, amount, "arion"
def parse(self, fname): 'parse bill content from eml(fname)' f = open(fname, 'rb') eml_bytes = f.read() f.close() # quoted-printable decode quo_dec = quopri.decodestring(eml_bytes) quo_dec = quo_dec.decode('utf-8') self.parse_year(quo_dec) self.parse_contents(quo_dec)
def encoded_words_to_text(encoded_words): """ Not used, left for reference only https://dmorgan.info/posts/encoded-word-syntax/ """ encoded_word_regex = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=' # encoded_word_regex = r'=\?{1}.+\?{1}[B|Q|b|q]\?{1}.+\?{1}=' charset, encoding, encoded_text = re.match(encoded_word_regex, encoded_words, re.IGNORECASE).groups() if encoding.upper() == 'B': byte_string = base64.b64decode(encoded_text) elif encoding.upper() == 'Q': byte_string = quopri.decodestring(encoded_text) return byte_string.decode(charset)
def uq(m): cs, how, data = m.group(1), m.group(2), m.group(3) if how in ('b', 'B'): try: data = base64.b64decode(''.join(data.split())+'===') except TypeError: print('FAILED TO B64DECODE: %s' % data) else: data = quopri.decodestring(data, header=True) try: return data.decode(cs) except LookupError: return data.decode('iso-8859-1') # Always works
def sendmail(to, message): mail_charset = 'utf-8' msg = MIMEText(quopri.decodestring(message), _charset=mail_charset) msg['Subject'] = Header(MAIL_SUBJECT, mail_charset) msg['From'] = MAIL_FROM msg['To'] = to try: smtpObj = SMTP(SMTP_HOST, SMTP_PORT) smtpObj.sendmail(MAIL_FROM, [to], msg.as_string()) smtpObj.quit() logger.info('Successfully sent email to %s' % to) except SMTPException: logger.error('Error: unable to send email to %s' % to)
def clean_content(content): # decode message from "quoted printable" format content = quopri.decodestring(content) # try to strip HTML tags # if errors happen in BeautifulSoup (for unknown encodings), then bail try: soup = BeautifulSoup(content, "html.parser", from_encoding="iso-8859-1") except Exception as e: return '' return ''.join(soup.findAll(text=True))
def message(self) -> Optional[str]: """Get message body""" message = '' if self._raw.is_multipart(): for payload in self._raw.get_payload(): message += payload.get_payload() else: message = self._raw.get_payload() # decode base64 encoded message if self._raw['Content-Transfer-Encoding'] == 'base64': message = b64decode(message) # decode MIME quoted-printable data return decodestring(message)
def readXML(filename): import quopri from lxml import etree with open(filename,encoding='utf-8') as f: root = etree.parse(f) emails = root.getroot().getchildren() text = [] for e in emails: aux = replaceNonAscii(e.text) aux = quopri.decodestring(aux) aux = aux.decode('latin-1') text.append(aux) return text
def encoded_words_to_text(encoded_words): """ from https://dmorgan.info/posts/encoded-word-syntax/ """ if not encoded_words.startswith("=?"): return encoded_words encoded_word_regex = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}=' charset, encoding, encoded_text = re.match(encoded_word_regex, encoded_words, flags=re.IGNORECASE).groups() if encoding.upper() == 'B': byte_string = base64.b64decode(encoded_text) elif encoding.upper() == 'Q': byte_string = quopri.decodestring(encoded_text) return byte_string.decode(charset)
def get_tracking( sdata: Any, account: Type[imaplib.IMAP4_SSL], the_format: Optional[str] = None ) -> list: """Parse tracking numbers from email. Returns list of tracking numbers """ tracking = [] pattern = None mail_list = sdata.split() _LOGGER.debug("Searching for tracking numbers in %s messages...", len(mail_list)) pattern = re.compile(r"{}".format(the_format)) for i in mail_list: data = email_fetch(account, i, "(RFC822)")[1] for response_part in data: if isinstance(response_part, tuple): msg = email.message_from_bytes(response_part[1]) _LOGGER.debug("Checking message subject...") # Search subject for a tracking number email_subject = msg["subject"] found = pattern.findall(email_subject) if len(found) > 0: _LOGGER.debug( "Found tracking number in email subject: (%s)", found[0], ) if found[0] not in tracking: tracking.append(found[0]) continue # Search in email body for tracking number _LOGGER.debug("Checking message body...") email_msg = quopri.decodestring(str(msg.get_payload(0))) email_msg = email_msg.decode("utf-8", "ignore") found = pattern.findall(email_msg) if len(found) > 0: # DHL is special if " " in the_format: found[0] = found[0].split(" ")[1] _LOGGER.debug("Found tracking number in email body: %s", found[0]) if found[0] not in tracking: tracking.append(found[0]) continue if len(tracking) == 0: _LOGGER.debug("No tracking numbers found") return tracking
def verify(signed_text, capath, check_crl): ''' Verify the signed message has been signed by the certificate (attached to the supplied SMIME message) it claims to have, by one of the accepted CAs in capath. Returns a tuple including the signer's certificate and the plain-text of the message if it has been verified. If the content transfer encoding is specified as 'quoted-printable' or 'base64', decode the message body accordingly. ''' if signed_text is None or capath is None: raise CryptoException('Invalid None argument to verify().') # This ensures that openssl knows that the string is finished. # It makes no difference if the signed message is correct, but # prevents it from hanging in the case of an empty string. signed_text += '\n\n' signer = get_signer_cert(signed_text) if not verify_cert(signer, capath, check_crl): raise CryptoException('Unverified signer') # The -noverify flag removes the certificate verification. The certificate # is verified above; this check would also check that the certificate # is allowed to sign with SMIME, which host certificates sometimes aren't. p1 = Popen(['openssl', 'smime', '-verify', '-CApath', capath, '-noverify'], stdin=PIPE, stdout=PIPE, stderr=PIPE) message, error = p1.communicate(signed_text) # SMIME header and message body are separated by a blank line lines = message.strip().splitlines() blankline = lines.index('') headers = '\n'.join(lines[:blankline]) body = '\n'.join(lines[blankline + 1:]) # two possible encodings if 'quoted-printable' in headers: body = quopri.decodestring(body) elif 'base64' in headers: body = base64.decodestring(body) # otherwise, plain text # Interesting problem here - we get a message 'Verification successful' # to standard error. We don't want to log this as an error each time, # but we do want to see if there's a genuine error... log.info(str(error).strip()) subj = get_certificate_subject(signer) return body, subj
def _get_attrs(self): """ Get the attributes to update the context with from the """ attrs = {} error = u'' params = self.request.params uploads = self._get_uploads() attrs['title'] = params.get('title') description = params.get('description') attrs['description'] = quopri.decodestring(description) url = params.get('url', None) if url: try: model.Design.url.validate(url) except datastore_errors.BadValueError: msg = self._(u'Web link is not a valid URL.') hint = self._( u'(If you don\'t have a web link, leave the field blank)') error = '%s %s' % (msg, hint) else: attrs['url'] = url series = params.getall('series') keys = [db.Key.from_path('Series', item) for item in series] instances = model.Series.get(keys) if None in instances: i = instances.index(None) msg = self._(u'Series does not exist:') error = '%s `%s`' % (msg, series[i]) attrs['series'] = keys if not error: google_user = users.get_current_user() google_user_id = google_user.user_id() user = model.User.get_by_user_id(google_user_id) # If this user has not been stored yet, create and store it. if user is None: try: user = model.User(google_user=google_user, google_user_id=google_user_id) # If they're an admin (and thus won't be moderated) make sure # they have an avatar here. if users.is_current_user_admin() and not user.avatar: user.set_avatar() user.put() except db.Error, err: error = unicode(err)
def getPostLinks(self, post): html = self.getPostContentHtml(post) # print(f"Html: {html}") import quopri html = quopri.decodestring(html) soup = BeautifulSoup(html, 'lxml') res = soup.find_all('a', href=True) # print(f"Res: {res}") links = [] for element in res: link = element['href'] if not link in links: links.append(link) return links
def decode_message(message): ret = '' for s in message.split('\n'): if len(s.split('?')) > 4: charset = s.split('?')[1] mode = s.split('?')[2] code = s.split('?')[3] if mode.upper() == 'B': ret += str(base64.decodebytes(code.encode(encoding=charset)), encoding=charset) else: ret += str(quopri.decodestring(code.encode(encoding=charset)), encoding=charset) return ret
def get_first_text_part(self, msg): maintype = msg.get_content_maintype() if maintype == 'multipart': for part in msg.get_payload(): print part.get_content_charset(part.get_payload()) if part.get_content_maintype() == 'text': resp= ' ' if part['Content-Transfer-Encoding'] == 'quoted-printable': resp= quopri.decodestring(part.get_payload()) if part.get_content_charset(False): resp = part.get_payload().decode(part.get_content_charset()) print resp return resp for part in msg.get_payload(): return self.get_first_text_part(part) elif maintype == 'text': resp= '' print msg.get_content_charset(msg.get_payload()) if msg['Content-Transfer-Encoding'] == 'quoted-printable': resp= quopri.decodestring(msg.get_payload()) if msg.get_content_charset(False): resp = msg.get_payload().decode(msg.get_content_charset()) print resp return resp else: return ' '