def encrypt_all_payloads( message, gpg_to_cmdline ): encrypted_payloads = list() if type( message.get_payload() ) == str: return encrypt_payload( message, gpg_to_cmdline ).get_payload() for payload in message.get_payload(): if( type( payload.get_payload() ) == list ): encrypted_payloads.extend( encrypt_all_payloads( payload, gpg_to_cmdline ) ) else: encrypted_payloads.append( encrypt_payload( payload, gpg_to_cmdline ) ) return encrypted_payloads
def test_customize_message_encoding(self): mailing = factories.MailingFactory( header="""Content-Transfer-Encoding: 7bit Content-Type: multipart/alternative; boundary="===============2840728917476054151==" Subject: Great news! From: Mailing Sender <*****@*****.**> To: <*****@*****.**> Date: Wed, 05 Jun 2013 06:05:56 -0000 """, body=""" This is a multi-part message in MIME format. --===============2840728917476054151== Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable This is a very simple mailing. I'm happy. --===============2840728917476054151== Content-Type: text/html; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head> <META http-equiv=3DContent-Type content=3D"text/html; charset=3Diso-8859-1"> </head> <body> This is <strong> a very simple</strong> <u>mailing</u>. = I'm happy! Nothing else to say... </body></html> --===============2840728917476054151==-- """ ) recipient = factories.RecipientFactory(mailing=mailing) customizer = MailCustomizer(recipient) fullpath = os.path.join(customizer.temp_path, MailCustomizer.make_file_name(recipient.mailing.id, recipient.id)) if os.path.exists(fullpath): os.remove(fullpath) self.assertFalse(os.path.exists(fullpath)) customizer._run_customizer() self.assertTrue(os.path.exists(fullpath)) parser = email.parser.Parser() message = parser.parse(file(fullpath, 'rt'), headersonly = False) assert(isinstance(message, email.message.Message)) self.assertTrue(message.is_multipart()) self.assertEquals("multipart/alternative", message.get_content_type()) self.assertEquals("text/plain", message.get_payload(i=0).get_content_type()) self.assertEquals("text/html", message.get_payload(i=1).get_content_type()) self.assertEquals(message.get_payload(i=0).get_payload(decode=True), "This is a very simple mailing. I'm happy.") self.assertIn("This is <strong> a very simple</strong> <u>mailing</u>. I'm happy! ", message.get_payload(i=1).get_payload(decode=True))
def encrypt_all_payloads(message, gpg_to_cmdline): encrypted_payloads = list() if type(message.get_payload()) == str: if ( cfg.has_key("default") and cfg["default"].has_key("mime_conversion") and cfg["default"]["mime_conversion"] == "yes" ): # Convert a plain text email into PGP/MIME attachment style. Modeled after enigmail. submsg1 = email.message.Message() submsg1.set_payload("Version: 1\n") submsg1.set_type("application/pgp-encrypted") submsg1.set_param("PGP/MIME version identification", "", "Content-Description") submsg2 = email.message.Message() submsg2.set_type("application/octet-stream") submsg2.set_param("name", "encrypted.asc") submsg2.set_param("OpenPGP encrypted message", "", "Content-Description") submsg2.set_param("inline", "", "Content-Disposition") submsg2.set_param("filename", "encrypted.asc", "Content-Disposition") # WTF! It seems to swallow the first line. Not sure why. Perhaps # it's skipping an imaginary blank line someplace. (ie skipping a header) # Workaround it here by prepending a blank line. submsg2.set_payload("\n" + message.get_payload()) message.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)" # Use this just to generate a MIME boundary string. junk_msg = MIMEMultipart() junk_str = junk_msg.as_string() # WTF! Without this, get_boundary() will return 'None'! boundary = junk_msg.get_boundary() # This also modifies the boundary in the body of the message, ie it gets parsed. if message.has_key("Content-Type"): message.replace_header( "Content-Type", 'multipart/encrypted; protocol="application/pgp-encrypted";\nboundary="%s"\n' % boundary, ) else: message["Content-Type"] = ( 'multipart/encrypted; protocol="application/pgp-encrypted";\nboundary="%s"\n' % boundary ) return [submsg1, encrypt_payload(submsg2, gpg_to_cmdline)] else: # Do a simple in-line PGP conversion of a plain text email. return encrypt_payload(message, gpg_to_cmdline).get_payload() for payload in message.get_payload(): if type(payload.get_payload()) == list: encrypted_payloads.extend(encrypt_all_payloads(payload, gpg_to_cmdline)) else: encrypted_payloads.append(encrypt_payload(payload, gpg_to_cmdline)) return encrypted_payloads
def encrypt_all_payloads(message, gpg_to_cmdline): encrypted_payloads = list() if type(message.get_payload()) == str: return encrypt_payload(message, gpg_to_cmdline).get_payload() for payload in message.get_payload(): if (type(payload.get_payload()) == list): encrypted_payloads.extend( encrypt_all_payloads(payload, gpg_to_cmdline)) else: encrypted_payloads.append(encrypt_payload(payload, gpg_to_cmdline)) return encrypted_payloads
def encrypt_all_payloads_inline( message, gpg_to_cmdline ): # This breaks cascaded MIME messages. Blame PGP/INLINE. encrypted_payloads = list() if type( message.get_payload() ) == str: return encrypt_payload( message, gpg_to_cmdline ).get_payload() for payload in message.get_payload(): if( type( payload.get_payload() ) == list ): encrypted_payloads.extend( encrypt_all_payloads_inline( payload, gpg_to_cmdline ) ) else: encrypted_payloads.append( encrypt_payload( payload, gpg_to_cmdline ) ) return encrypted_payloads
def _get_text(message): if message.is_multipart(): for part in message.get_payload(): text = _get_text(part) if text is not None: return text else: mimetype = message.get_content_type() if mimetype == 'text/plain': payload = message.get_payload() charset = message.get_content_charset() if charset is not None: payload = payload.decode(charset, 'replace') return payload
def convert_nested_message(message, top_level = False): if top_level: # Leave only content-related headers for tree purposes, do not # dupluicate all the headers. Also, leave From and Subject for # display purposes node = {k : v for k, v in message.items() if k.startswith("Content-") or k == 'From' or k == 'Subject'} else: node = dict(message) if message.is_multipart(): node['contents'] = map(convert_nested_message, message.get_payload()) else: node['contents'] = cas.add(db, message.get_payload(decode=True)) return node
def get_form_data(self, form=False): ct = self.headers.get('content-type', self.headers.get('CONTENT-TYPE', '')).lower() resp = {} # application/x-www-form-urlencoded if ct == 'application/x-www-form-urlencoded': body = yield from self.body.read() resp['form'] = urllib.parse.parse_qs(body.decode('latin1')) # multipart/form-data elif ct.startswith('multipart/form-data'): # pragma: no cover out = io.BytesIO() for key, val in self.headers.items(): out.write(bytes('{}: {}\r\n'.format(key, val), 'latin1')) out.write(b'\r\n') out.write(self.body) out.write(b'\r\n') out.seek(0) message = email.parser.BytesParser().parse(out) if message.is_multipart(): for msg in message.get_payload(): if msg.is_multipart(): logging.warn('multipart msg is not expected') else: key, params = cgi.parse_header( msg.get('content-disposition', '')) params['data'] = msg.get_payload() params['content-type'] = msg.get_content_type() resp['multipart-data'].append(params) return resp['form'] if form else resp
def load_from_checkpoint(self, checkpoint_data): parser = email.parser.BytesParser() message = parser.parsebytes(checkpoint_data) version = int(message['Version']) if version not in self.SUPPORTED_VERSIONS: raise storage.UnsupportedFileVersionError() if message.get_content_type() != 'application/json': raise storage.CorruptedProjectError( "Unexpected content type %s" % message.get_content_type()) serialized_checkpoint = message.get_payload() checkpoint = json.loads(serialized_checkpoint, cls=JSONDecoder) self.deserialize(checkpoint) self.init_references() def validate_node(root, parent, node): assert node.parent is parent, (node.parent, parent) assert node.root is root, (node.root, root) for c in node.list_children(): validate_node(root, node, c) validate_node(self, None, self)
def test_003_send_reply(self): itip_events = itip.events_from_message( message_from_string(itip_non_multipart)) itip.send_reply( "*****@*****.**", itip_events, "SUMMARY=%(summary)s; STATUS=%(status)s; NAME=%(name)s;") self.assertEqual(len(self.smtplog), 1) self.assertEqual(self.smtplog[0][0], '*****@*****.**', "From attendee") self.assertEqual(self.smtplog[0][1], '*****@*****.**', "To organizer") _accepted = participant_status_label('ACCEPTED') message = message_from_string(self.smtplog[0][2]) self.assertEqual( message.get('Subject'), _("Invitation for %(summary)s was %(status)s") % { 'summary': 'test', 'status': _accepted }) text = str(message.get_payload(0)) self.assertIn('SUMMARY=3Dtest', text) self.assertIn('STATUS=3D' + _accepted, text)
def extract_and_upload_attachments(message, realm): # type: (message.Message, Realm) -> text_type user_profile = get_user_profile_by_email(settings.EMAIL_GATEWAY_BOT) attachment_links = [] payload = message.get_payload() if not isinstance(payload, list): # This is not a multipart message, so it can't contain attachments. return "" for part in payload: content_type = part.get_content_type() filename = part.get_filename() if filename: attachment = part.get_payload(decode=True) if isinstance(attachment, binary_type): s3_url = upload_message_image(filename, content_type, attachment, user_profile, target_realm=realm) formatted_link = u"[%s](%s)" % (filename, s3_url) attachment_links.append(formatted_link) else: logger.warning( "Payload is not bytes (invalid attachment %s in message from %s)." % (filename, message.get("From"))) return u"\n".join(attachment_links)
def extract_and_upload_attachments(message: message.Message, realm: Realm) -> str: user_profile = get_system_bot(settings.EMAIL_GATEWAY_BOT) attachment_links = [] payload = message.get_payload() if not isinstance(payload, list): # This is not a multipart message, so it can't contain attachments. return "" for part in payload: content_type = part.get_content_type() filename = part.get_filename() if filename: attachment = part.get_payload(decode=True) if isinstance(attachment, bytes): s3_url = upload_message_file(filename, len(attachment), content_type, attachment, user_profile, target_realm=realm) formatted_link = "[%s](%s)" % (filename, s3_url) attachment_links.append(formatted_link) else: logger.warning("Payload is not bytes (invalid attachment %s in message from %s)." % (filename, message.get("From"))) return "\n".join(attachment_links)
def encrypt_all_payloads_mime(message, gpg_to_cmdline): # Convert a plain text email into PGP/MIME attachment style. Modeled after enigmail. submsg1 = email.message.Message() submsg1.set_payload("Version: 1\n") submsg1.set_type("application/pgp-encrypted") submsg1.set_param('PGP/MIME version identification', "", 'Content-Description') submsg2 = email.message.Message() submsg2.set_type("application/octet-stream") submsg2.set_param('name', "encrypted.asc") submsg2.set_param('OpenPGP encrypted message', "", 'Content-Description') submsg2.set_param('inline', "", 'Content-Disposition') submsg2.set_param('filename', "encrypted.asc", 'Content-Disposition') if type(message.get_payload()) == str: # WTF! It seems to swallow the first line. Not sure why. Perhaps # it's skipping an imaginary blank line someplace. (ie skipping a header) # Workaround it here by prepending a blank line. # This happens only on text only messages. submsg2.set_payload("\n" + message.get_payload()) check_nested = True else: processed_payloads = generate_message_from_payloads(message) submsg2.set_payload(processed_payloads.as_string()) check_nested = False message.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)" # Use this just to generate a MIME boundary string. junk_msg = MIMEMultipart() junk_str = junk_msg.as_string( ) # WTF! Without this, get_boundary() will return 'None'! boundary = junk_msg.get_boundary() # This also modifies the boundary in the body of the message, ie it gets parsed. if message.has_key('Content-Type'): message.replace_header( 'Content-Type', "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary) else: message[ 'Content-Type'] = "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary return [submsg1, encrypt_payload(submsg2, gpg_to_cmdline, check_nested)]
def find_url_in_email(message: email.message.Message) -> Optional[str]: """Return the first URL in the given message's payload, or None.""" body = message.get_payload() match = _url_regex.search(body) if not match: return None return match.group(0)
def get_calls(imap, folder_name_call): date_list_call = [] datas_list_call = [] unread_messages_call = 0 message_number_call = [] status_1, select_data_1 = imap.select(folder_name_call) letters_list = imap.search(None, 'ALL') for i in letters_list[1][0].split(): cur_letter = imap.fetch(i, '(RFC822)') # print('current letter: {}'.format(cur_letter)) status, data = imap.fetch(i, '(RFC822)') message = email.message_from_bytes(data[0][1], _class=email.message.EmailMessage) # DATE --------------------------------------------------------- date = list(email.utils.parsedate_tz(message['Date']))[:3] date_out = '' for _ in date: date_out += str(_) + '.' date_final = date_out[0:-1] # -------------------------------------------------------------- # soup = BeautifulSoup(message.get_payload(decode=True), 'html5lib') soup = BeautifulSoup(message.get_payload(decode=True), 'lxml') try: # DATAS -------------------------- datas = soup.findAll('p') # print(datas) datas_out = list(map(lambda x: x.text, datas)) # print(datas_out) datas_final = '' for _ in datas_out: if _: datas_final += _ + ' ' # '\n' + ' ' datas_final = datas_final[0:] # print(datas_final) # -------------------------------------------------------------- # DATAFRAME --------------------------------------------------------- date_list_call.append(date_final) datas_list_call.append(datas_final) # ------------------------------------------------------------------- # print(date_list_call, datas_list_call) except IndexError as err: print('Ошибка:\n', traceback.format_exc()) print('IndexError') unread_messages_call += 1 message_number_call.append(i) return date_list_call, datas_list_call, unread_messages_call, message_number_call
def deserialize_command(self, cmd_data): parser = email.parser.BytesParser() message = parser.parsebytes(cmd_data) target_id = message['Target'] cmd_state = json.loads(message.get_payload(), cls=JSONDecoder) cmd = commands.Command.create_from_state(cmd_state) return cmd, target_id
def __init__(self, message=None, mailbox=None, messageUID=None, agent=None): YCommandMessage.__init__(self, message=message, mailbox=mailbox, messageUID=messageUID, agent=agent) opmlMimeTypes = ['text/xml', 'text/x-opml+xml'] self.opml = None if message is None: return if message.get_content_maintype() == 'multipart': parts = message.get_payload() for part in parts: if part.get_content_type() in opmlMimeTypes: self.opml = part.get_payload(decode=True) elif message.get_content_type() in opmlMimeTypes: self.opml = message.get_payload(decode=True)
async def handle_message(self, message: email.message.Message): body = message.get_payload() logger.get().msg("message received", envelope_from=message['X-MailFrom'], envelope_to=message['X-RcptTo'], peer=':'.join([i.strip(" '()")for i in message['X-Peer'].split(',')]), length=len(body) ) async with db.connection() as conn: await db.add_message(conn, message['X-MailFrom'], message['X-RcptTo'], message, message['X-Peer'])
def extractpayload(message, **kwargs): if message.is_multipart(): headerlen = kwargs.get('headerlen', 78) messagestr = mimetostring(message, headerlen) #.replace('\n','\r\n') boundary = '--' + message.get_boundary() temp = messagestr.split(boundary) temp.pop(0) return boundary + boundary.join(temp) else: return message.get_payload()
def encrypt_all_payloads_mime( message, gpg_to_cmdline ): # Convert a plain text email into PGP/MIME attachment style. Modeled after enigmail. submsg1 = email.message.Message() submsg1.set_payload("Version: 1\n") submsg1.set_type("application/pgp-encrypted") submsg1.set_param('PGP/MIME version identification', "", 'Content-Description' ) submsg2 = email.message.Message() submsg2.set_type("application/octet-stream") submsg2.set_param('name', "encrypted.asc") submsg2.set_param('OpenPGP encrypted message', "", 'Content-Description' ) submsg2.set_param('inline', "", 'Content-Disposition' ) submsg2.set_param('filename', "encrypted.asc", 'Content-Disposition' ) if type ( message.get_payload() ) == str: # WTF! It seems to swallow the first line. Not sure why. Perhaps # it's skipping an imaginary blank line someplace. (ie skipping a header) # Workaround it here by prepending a blank line. # This happens only on text only messages. submsg2.set_payload("\n" + message.get_payload()) check_nested = True else: processed_payloads = generate_message_from_payloads(message) submsg2.set_payload(processed_payloads.as_string()) check_nested = False message.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)" # Use this just to generate a MIME boundary string. junk_msg = MIMEMultipart() junk_str = junk_msg.as_string() # WTF! Without this, get_boundary() will return 'None'! boundary = junk_msg.get_boundary() # This also modifies the boundary in the body of the message, ie it gets parsed. if message.has_key('Content-Type'): message.replace_header('Content-Type', "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary) else: message['Content-Type'] = "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary return [ submsg1, encrypt_payload(submsg2, gpg_to_cmdline, check_nested) ]
def _structure( message: email.message.EmailMessage, level: int, include_default: bool) -> None: result.append('{0}{1}{2}'.format( indent * level, message.get_content_type(), ' [{0}]'.format(message.get_default_type()) if include_default else '')) if message.is_multipart(): for subpart in message.get_payload(): _structure(subpart, level + 1, include_default)
def parsePayload(message): """ :param message: 结构化邮件 :return parsepayload: 邮件正文(为一字典) """ trim = False parsepayload = {} #获取有效载荷列表,如果是单载荷简单邮件则将其转换成列表 payloadlist = message.get_payload() if type(payloadlist) != type([]): payloadlist = [message] #记录载荷数目 parsepayload['num'] = len(payloadlist) for num in range(0, parsepayload['num']): if parsepayload['num'] > 1: #多载荷时依次解析载荷,若载荷为文件则content为None if payloadlist[num].is_multipart(): content = payloadlist[num].get_payload() else: content = payloadlist[num].get_payload(decode=True) else: #单载荷时获取该载荷 content = payloadlist[0].get_payload(decode=True) #如果载荷不是文件则进行进一步处理 if content: try: #尝试进一步解析载荷(防止多重嵌套) if type(content) is type([]): trim = True content = content[-1].get_payload(decode=True) except: pass try: #尝试采用默认编码解码载荷,否则采用国标码 content = content.decode() except: try: content = content.decode('gbk') except: try: content = content.decode() except: pass #将载荷加入邮件字典 parsepayload['content' + str(num)] = str(content) if trim == True: parsepayload['content1'] = parsepayload['content0'] return parsepayload
def test_003_send_reply(self): itip_events = itip.events_from_message(message_from_string(itip_non_multipart)) itip.send_reply("*****@*****.**", itip_events, "SUMMARY=%(summary)s; STATUS=%(status)s; NAME=%(name)s;") self.assertEqual(len(self.smtplog), 1) self.assertEqual(self.smtplog[0][0], '*****@*****.**', "From attendee") self.assertEqual(self.smtplog[0][1], '*****@*****.**', "To organizer") _accepted = participant_status_label('ACCEPTED') message = message_from_string(self.smtplog[0][2]) self.assertEqual(message.get('Subject'), _("Invitation for %(summary)s was %(status)s") % { 'summary':'test', 'status':_accepted }) text = str(message.get_payload(0)); self.assertIn('SUMMARY=3Dtest', text) self.assertIn('STATUS=3D' + _accepted, text)
def test_customize_simple_message_with_recipient_attachment(self): recipient = factories.RecipientFactory( contact_data={ 'email': '*****@*****.**', 'custom': 'very simple', 'attachments': [ { 'filename': "export.csv", 'data': base64.b64encode("col1;col2;col3\nval1;val2;val3\n"), 'content-type': 'text/plain', 'charset': 'us-ascii', }, ] } ) #factories.MailingContentFactory(mailing=recipient.mailing) #print recipient.mailing.content customizer = MailCustomizer(recipient) fullpath = os.path.join(customizer.temp_path, MailCustomizer.make_file_name(recipient.mailing.id, recipient.id)) if os.path.exists(fullpath): os.remove(fullpath) self.assertFalse(os.path.exists(fullpath)) customizer._run_customizer() self.assertTrue(os.path.exists(fullpath)) parser = email.parser.Parser() message = parser.parse(file(fullpath, 'rt'), headersonly = False) assert(isinstance(message, email.message.Message)) self.assertTrue(message.is_multipart()) # print # print message.as_string() self.assertEquals(message.get_payload(i=0).get_payload(), 'This is a very simple mailing.') self.assertEquals(message.get_payload(i=1).get_payload(), 'col1;col2;col3\nval1;val2;val3\n')
def _get_upload_content(field_storage): """Returns an email.Message holding the values of the file transfer. It decodes the content of the field storage and creates a new email.Message. Args: field_storage: cgi.FieldStorage that represents uploaded blob. Returns: An email.message.Message holding the upload information. """ message = email.message.Message() message.add_header( 'content-transfer-encoding', field_storage.headers.getheader('Content-Transfer-Encoding', '')) message.set_payload(field_storage.file.read()) payload = message.get_payload(decode=True) return email.message_from_string(payload)
def test_generate_email(self): message = mail_request_handler.MailRequestHandler._generate_email( 'to', 'from', 'cc', 'subject', 'body') self.assertEqual('from', message['From']) self.assertEqual('to', message['To']) self.assertEqual('cc', message['Cc']) self.assertEqual('subject', message['Subject']) text, html = message.get_payload() self.assertEqual('text/plain', text.get_content_type()) self.assertEqual('utf-8', text.get_content_charset()) content = text.get_payload() if text['content-transfer-encoding'] != '7bit': content = content.decode(text['content-transfer-encoding']) self.assertEqual('body', content) self.assertEqual('text/html', html.get_content_type()) self.assertEqual('utf-8', html.get_content_charset()) content = html.get_payload() if html['content-transfer-encoding'] != '7bit': content = content.decode(html['content-transfer-encoding']) self.assertEqual('body', content)
def test_customize_message(self): mailing = factories.MailingFactory() recipient = factories.RecipientFactory(mailing=mailing) customizer = MailCustomizer(recipient) fullpath = os.path.join(customizer.temp_path, MailCustomizer.make_file_name(recipient.mailing.id, recipient.id)) if os.path.exists(fullpath): os.remove(fullpath) self.assertFalse(os.path.exists(fullpath)) customizer._run_customizer() self.assertTrue(os.path.exists(fullpath)) # print file(fullpath, 'rt').read() parser = email.parser.Parser() message = parser.parse(file(fullpath, 'rt'), headersonly = False) assert(isinstance(message, email.message.Message)) self.assertFalse(message.is_multipart()) self.assertTrue('Date' in message) self.assertEquals('This is a very simple mailing.', message.get_payload())
def extract_and_upload_attachments(message, realm): # type: (message.Message, Realm) -> text_type user_profile = get_user_profile_by_email(settings.EMAIL_GATEWAY_BOT) attachment_links = [] payload = message.get_payload() if not isinstance(payload, list): # This is not a multipart message, so it can't contain attachments. return "" for part in payload: content_type = part.get_content_type() filename = part.get_filename() if filename: s3_url = upload_message_image(filename, content_type, part.get_payload(decode=True), user_profile, target_realm=realm) formatted_link = u"[%s](%s)" % (filename, s3_url) attachment_links.append(formatted_link) return u"\n".join(attachment_links)
def test_create_mailing_from_message(self): parser = email.parser.Parser() msg = parser.parsestr("""Content-Transfer-Encoding: 7bit Content-Type: multipart/alternative; boundary="===============2840728917476054151==" Subject: Great news! From: Mailing Sender <*****@*****.**> To: <*****@*****.**> Date: Wed, 05 Jun 2013 06:05:56 -0000 This is a multi-part message in MIME format. --===============2840728917476054151== Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: quoted-printable This is a very simple mailing. I=92m happy. --===============2840728917476054151== Content-Type: text/html; charset="windows-1252" Content-Transfer-Encoding: quoted-printable <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head> <META http-equiv=3DContent-Type content=3D"text/html; charset=3Diso-8859-1"> </head> <body> This is <strong> a very simple</strong> <u>mailing</u>. = I=92m happy! Nothing else to say... </body></html> --===============2840728917476054151==-- """) mailing = Mailing.create_from_message(msg, mail_from='*****@*****.**', sender_name='Mailing Sender', scheduled_start=None, scheduled_duration=None) message = parser.parsestr(mailing.header + mailing.body) assert(isinstance(message, email.message.Message)) self.assertTrue(message.is_multipart()) self.assertEquals("multipart/alternative", message.get_content_type()) self.assertIsInstance(message.get_payload(i=0), email.message.Message) self.assertEquals("text/plain", message.get_payload(i=0).get_content_type()) self.assertEquals("windows-1252", message.get_payload(i=0).get_param('charset')) self.assertEquals("text/html", message.get_payload(i=1).get_content_type()) self.assertEquals("windows-1252", message.get_payload(i=1).get_param('charset')) self.assertEquals("This is a very simple mailing. I\x92m happy.", message.get_payload(i=0).get_payload(decode=True)) self.assertIn("This is <strong> a very simple</strong> <u>mailing</u>. I\x92m happy! ", message.get_payload(i=1).get_payload(decode=True))
def get_msg( message ): if not message.is_multipart(): return message.get_payload() return '\n\n'.join( [str(m) for m in message.get_payload()] )
def test_customize_alternative_message_with_recipient_attachment(self): recipient = factories.RecipientFactory( mailing = factories.MailingFactory( header="""Content-Transfer-Encoding: 7bit Content-Type: multipart/alternative; boundary="===============2840728917476054151==" Subject: Great news! From: Mailing Sender <*****@*****.**> To: <*****@*****.**> Date: Wed, 05 Jun 2013 06:05:56 -0000 """, body=""" This is a multi-part message in MIME format. --===============2840728917476054151== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit This is a very simple mailing. --===============2840728917476054151== Content-Type: text/html; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit <html><head></head> <body> This is <strong> a very simple</strong> <u>mailing</u>. Nothing else to say... --===============2840728917476054151==-- """ ), contact_data={ 'email': '*****@*****.**', 'custom': 'very simple', 'attachments': [ { 'filename': "export.csv", 'data': base64.b64encode("col1;col2;col3\nval1;val2;val3\n"), 'content-type': 'text/plain', 'charset': 'us-ascii', }, ] } ) customizer = MailCustomizer(recipient) fullpath = os.path.join(customizer.temp_path, MailCustomizer.make_file_name(recipient.mailing.id, recipient.id)) if os.path.exists(fullpath): os.remove(fullpath) self.assertFalse(os.path.exists(fullpath)) customizer._run_customizer() self.assertTrue(os.path.exists(fullpath)) parser = email.parser.Parser() message = parser.parse(file(fullpath, 'rt'), headersonly = False) assert(isinstance(message, email.message.Message)) # print # print message.as_string() self.assertTrue(message.is_multipart()) self.assertEquals("multipart/mixed", message.get_content_type()) self.assertEquals("multipart/alternative", message.get_payload(i=0).get_content_type()) self.assertEquals(message.get_payload(i=0).get_payload(i=0).get_payload(), 'This is a very simple mailing.') self.assertIn("This is <strong> a very simple</strong> <u>mailing</u>.", message.get_payload(i=0).get_payload(i=1).get_payload()) self.assertEquals(message.get_payload(i=1).get_payload(), 'col1;col2;col3\nval1;val2;val3\n')
def test_customize_mixed_and_alternative_and_related_message_with_recipient_attachment(self): recipient = factories.RecipientFactory( mailing = factories.MailingFactory( header="""Content-Transfer-Encoding: 7bit Content-Type: multipart/mixed; boundary="===============0000000000000000000==" Subject: Great news! From: Mailing Sender <*****@*****.**> To: <*****@*****.**> Date: Wed, 05 Jun 2013 06:05:56 -0000 """, body=""" This is a multi-part message in MIME format. --===============0000000000000000000== Content-Type: multipart/alternative; boundary="===============1111111111111111111==" --===============1111111111111111111== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit This is a very simple mailing. --===============1111111111111111111== Content-Type: multipart/related; boundary="===============2222222222222222222==" This is a multi-part message in MIME format. --===============2222222222222222222== Content-Type: text/html; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit <html><head></head> <body> This is <strong> a very simple</strong> <u>mailing</u>. Nothing else to say... <img id="Image 2"src="cid:[email protected]" height="45" width="130" border="0"> </body></html> --===============2222222222222222222== Content-Type: image/jpeg; name="akema_logo_signatures.jpg" Content-Transfer-Encoding: base64 Content-ID: <*****@*****.**> Content-Disposition: inline; filename="akema_logo_signatures.jpg" /9j/4AAQSkZJRgABAQEASABIAAD/4QESRXhpZgAATU0AKgAAAAgABgEaAAUAAAABAAAAVgEb AAUAAAABAAAAXgEoAAMAAAABAAIAAAExAAIAAAASAAAAZgEyAAIAAAAUAAAAeIdpAAQAAAAB AAAAjAAAANAAAABIAAAAAQAAAEgAAAABUGFpbnQuTkVUIHYzLjUuMTAAMjAxMjoxMjoxMSAx --===============2222222222222222222==-- --===============1111111111111111111==-- --===============0000000000000000000== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="common.txt" This is an attachment common for all recipients. Nothing else to say... --===============0000000000000000000==-- """ ), contact_data={ 'email': '*****@*****.**', 'custom': 'very simple', 'attachments': [ { 'filename': "export.csv", 'data': base64.b64encode("col1;col2;col3\nval1;val2;val3\n"), 'content-type': 'text/plain', 'charset': 'us-ascii', }, ] } ) customizer = MailCustomizer(recipient) fullpath = os.path.join(customizer.temp_path, MailCustomizer.make_file_name(recipient.mailing.id, recipient.id)) if os.path.exists(fullpath): os.remove(fullpath) self.assertFalse(os.path.exists(fullpath)) customizer._run_customizer() self.assertTrue(os.path.exists(fullpath)) parser = email.parser.Parser() message = parser.parse(file(fullpath, 'rt'), headersonly = False) assert(isinstance(message, email.message.Message)) # print # print message.as_string() self.assertTrue(message.is_multipart()) self.assertEquals("multipart/mixed", message.get_content_type()) self.assertEquals("multipart/alternative", message.get_payload(i=0).get_content_type()) self.assertEquals("text/plain", message.get_payload(i=0).get_payload(i=0).get_content_type()) self.assertEquals("multipart/related", message.get_payload(i=0).get_payload(i=1).get_content_type()) self.assertEquals('This is a very simple mailing.', message.get_payload(i=0).get_payload(i=0).get_payload()) self.assertIn("This is <strong> a very simple</strong> <u>mailing</u>.", message.get_payload(i=0).get_payload(i=1).get_payload(i=0).get_payload()) self.assertIn("This is an attachment", message.get_payload(i=1).get_payload()) self.assertEquals(message.get_payload(i=2).get_payload(), 'col1;col2;col3\nval1;val2;val3\n')
def craft_message(headers, body, attachments, embeddeds, mbx, is_html): """This function handles the creation of a Python email.message object from the headers and body lists created during the main loop.""" global edir attachments_ok = False embeddedcids = [] if body: msg_text = ''.join(body) else: msg_text = '' # there's no point honoring 'multipart' if we don't have any # attachments or embeddeds to attach, so we'll pay most # attention to whether we have any attachments or embeddeds # defined for this message if attachments or embeddeds: is_multipart = True else: is_multipart = False message = None contenttype = headers.getValue('Content-Type:') if contenttype and re_html.search(contenttype): is_html = True if not contenttype: msattach = headers.getValue('X-MS-Attachment:') if msattach: message = MIMEMultipart() attachments_ok = "Dunno" attachments_contenttype = "Still Dunno" else: if is_html: message = MIMENonMultipart('text', 'html') else: message = MIMENonMultipart('text', 'plain') attachments_ok = False attachments_contenttype = False print "T", elif re_rfc822.search(contenttype): print "[", message = MIMEMessage( craft_message(*extract_pieces(body, -1, mbx, True))) print "]", elif not is_multipart: mimetype = re_single_contenttype.search(contenttype) if mimetype: main = mimetype.group(1) sub = mimetype.group(2) if main != 'multipart': message = MIMENonMultipart(main, sub) attachments_ok = False attachments_contenttype = False print "X", else: # I've seen some messages in Eudora # mailboxes that label themselves as # multitype/related without having any # attachments ever declared in the # Eudora box. # # By passing here, we allow the next # clause to go ahead and create an # appropriate MIMENonMultipart pass if not message: if is_html: message = MIMENonMultipart('text', 'html') else: message = MIMENonMultipart('text', 'plain') attachments_ok = False attachments_contenttype = False else: subtype = re_multi_contenttype.search(contenttype) if subtype: message = MIMEMultipart(_subtype=subtype.group(1)) attachments_ok = subtype.group(1) attachments_contenttype = contenttype print "Y", else: message = MIMEMultipart() print "Z", attachments_ok = "Dunno" attachments_contenttype = "Still Dunno" # Need to add support here for processing embeddeds if embeddeds: if not isinstance(message, MIMEMultipart): print "\n\n==================================================\n" print "Found surprise multipart for embeddeds!\n" message = MIMEMultipart(_subtype='related') else: print "\n\n==================================================\n" print "Found embeddeds in multipart!\n" p = EudoraHTMLParser() try: p.feed(msg_text) cids = p.get_cids() except HTMLParseError: # okay, we've got unparseable HTML here. # Let's just use a quick regexp to see if we can make sense of this. cids = [] for match in re_cids_finder.finditer(msg_text): cids.append("cid:" + match.group(1)) if not len(cids) == len(embeddeds): print "cids / embeddeds mismatch!" print print mbx for piece in ['To:', 'From:', 'Subject:', 'Date:']: if headers.getValue(piece): print piece + " " + headers.getValue(piece)[:80] print print "\tcid\t\t\t\t\t\t\tembedded" i = 0 while i < len(cids) or i < len(embeddeds): if i < len(cids): print "%d.\t%s" % (i, cids[i]), print "\t" * (6 - (len(cids[i]) // 8)), else: print "%d.\t" % (i, ), print "\t\t\t\t\t\t", if i < len(embeddeds): print embeddeds[i], if edir and os.path.exists(edir + os.sep + embeddeds[i]): print " *" else: print " !" else: print i = i + 1 cidi = 0 embeddedi = 0 cidsmatched = set() while cidi < len(cids) or embeddedi < len(embeddeds): if cidi < len(cids) and embeddedi < len(embeddeds): if cids[cidi].startswith('cid:'): actualcid = cids[cidi][4:] else: actualcid = cids[cidi] # the document might have several img # references to the same cid.. we # don't want to try to mate up # multiple inline files in that case if actualcid in cidsmatched: cidi = cidi + 1 else: cidsmatched.add(actualcid) embeddedcids.append((actualcid, embeddeds[embeddedi])) embeddedi = embeddedi + 1 cidi = cidi + 1 elif embeddedi < len(embeddeds): embeddedcids.append((None, embeddeds[embeddedi])) embeddedi = embeddedi + 1 else: # we have more cids than # embeddeds, keep looping # through cidi = cidi + 1 print "\n\nAttaching inline components:" for c, f in embeddedcids: print "%s\t%s" % (c, f) print "\n==================================================\n" if attachments: if not isinstance(message, MIMEMultipart): #print "\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" #print "Forcing surprise multipart!\n" #print "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" message = MIMEMultipart() # bind the headers into our message set_headers(message, headers) try: # rfc822 MIMEMessage objects handle payload management # on constructions, we must not try to do it here. if not isinstance(message, MIMEMessage): if not isinstance(message, MIMEMultipart): message.set_payload(msg_text) elif is_html: message.attach(MIMEText(msg_text, _subtype='html')) else: message.attach(MIMEText(msg_text)) except Exception, e: print "\nHEY HEY HEY message = " + str(msg_text) + "\n" print "Type of message's payload is " + str(type( message.get_payload())) + "\n" if isinstance(message.get_payload(), list): print "Size of message's payload list is " + str( len(message.get_payload())) + "\n" print ")))))))))))))))))))) First part" print str(message.get_payload()[0]) print ">>>>>>>>>>>>>>>>>>>> Second part" print str(message.get_payload()[1]) print "attachments_contenttype is (%s)" % (attachments_contenttype, ) print "attachments_ok is (%s)" % (attachments_ok, ) if attachments: print "Yeah, attachments were found: %d" % (len(attachments), ) print "EXCEPTION " + str(e) + "\n" traceback.print_exc(file=sys.stdout)
def craft_message( headers, body, attachments, embeddeds, mbx, is_html): """This function handles the creation of a Python email.message object from the headers and body lists created during the main loop.""" global edir attachments_ok = False embeddedcids = [] if body: msg_text = ''.join(body) else: msg_text = '' # there's no point honoring 'multipart' if we don't have any # attachments or embeddeds to attach, so we'll pay most # attention to whether we have any attachments or embeddeds # defined for this message if attachments or embeddeds: is_multipart = True else: is_multipart = False message = None contenttype = headers.getValue('Content-Type:') if contenttype and re_html.search(contenttype): is_html = True if not contenttype: msattach = headers.getValue('X-MS-Attachment:') if msattach: message = MIMEMultipart() attachments_ok = "Dunno" attachments_contenttype = "Still Dunno" else: if is_html: message = MIMENonMultipart('text', 'html') else: message = MIMENonMultipart('text', 'plain') attachments_ok = False attachments_contenttype = False print "T", elif re_rfc822.search( contenttype ): print "[", message = MIMEMessage(craft_message(*extract_pieces(body, -1, mbx, True))) print "]", elif not is_multipart: mimetype = re_single_contenttype.search( contenttype ) if mimetype: main = mimetype.group(1) sub = mimetype.group(2) if main != 'multipart': message = MIMENonMultipart(main, sub) attachments_ok = False attachments_contenttype = False print "X", else: # I've seen some messages in Eudora # mailboxes that label themselves as # multitype/related without having any # attachments ever declared in the # Eudora box. # # By passing here, we allow the next # clause to go ahead and create an # appropriate MIMENonMultipart pass if not message: if is_html: message = MIMENonMultipart('text', 'html') else: message = MIMENonMultipart('text', 'plain') attachments_ok = False attachments_contenttype = False else: subtype = re_multi_contenttype.search( contenttype ) if subtype: message = MIMEMultipart(_subtype=subtype.group(1)) attachments_ok = subtype.group(1) attachments_contenttype = contenttype print "Y", else: message = MIMEMultipart() print "Z", attachments_ok = "Dunno" attachments_contenttype = "Still Dunno" # Need to add support here for processing embeddeds if embeddeds: if not isinstance( message, MIMEMultipart): print "\n\n==================================================\n" print "Found surprise multipart for embeddeds!\n" message = MIMEMultipart(_subtype='related') else: print "\n\n==================================================\n" print "Found embeddeds in multipart!\n" p = EudoraHTMLParser() try: p.feed(msg_text) cids = p.get_cids() except HTMLParseError: # okay, we've got unparseable HTML here. # Let's just use a quick regexp to see if we can make sense of this. cids = [] for match in re_cids_finder.finditer(msg_text): cids.append("cid:" + match.group(1)) if not len(cids) == len(embeddeds): print "cids / embeddeds mismatch!" print print mbx for piece in ['To:', 'From:' , 'Subject:', 'Date:']: if headers.getValue(piece): print piece + " " + headers.getValue(piece)[:80] print print "\tcid\t\t\t\t\t\t\tembedded" i = 0 while i < len(cids) or i < len(embeddeds): if i < len(cids): print "%d.\t%s" % (i, cids[i]), print "\t" * (6 - (len(cids[i]) // 8)), else: print "%d.\t" % (i, ), print "\t\t\t\t\t\t", if i < len(embeddeds): print embeddeds[i], if edir and os.path.exists(edir + os.sep + embeddeds[i]): print " *" else: print " !" else: print i = i + 1 cidi = 0 embeddedi = 0 cidsmatched = set() while cidi < len(cids) or embeddedi < len(embeddeds): if cidi < len(cids) and embeddedi < len(embeddeds): if cids[cidi].startswith('cid:'): actualcid = cids[cidi][4:] else: actualcid = cids[cidi] # the document might have several img # references to the same cid.. we # don't want to try to mate up # multiple inline files in that case if actualcid in cidsmatched: cidi = cidi + 1 else: cidsmatched.add(actualcid) embeddedcids.append( (actualcid, embeddeds[embeddedi]) ) embeddedi = embeddedi + 1 cidi = cidi + 1 elif embeddedi < len(embeddeds): embeddedcids.append( (None, embeddeds[embeddedi]) ) embeddedi = embeddedi + 1 else: # we have more cids than # embeddeds, keep looping # through cidi = cidi + 1 print "\n\nAttaching inline components:" for c, f in embeddedcids: print "%s\t%s" % (c, f) print "\n==================================================\n" if attachments: if not isinstance( message, MIMEMultipart): #print "\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" #print "Forcing surprise multipart!\n" #print "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" message = MIMEMultipart() # bind the headers into our message set_headers( message, headers ) try: # rfc822 MIMEMessage objects handle payload management # on constructions, we must not try to do it here. if not isinstance( message, MIMEMessage ): if not isinstance( message, MIMEMultipart): message.set_payload(msg_text) elif is_html: message.attach(MIMEText(msg_text, _subtype='html')) else: message.attach(MIMEText(msg_text)) except Exception, e: print "\nHEY HEY HEY message = " + str(msg_text) + "\n" print "Type of message's payload is " + str(type(message.get_payload())) + "\n" if isinstance( message.get_payload(), list ): print "Size of message's payload list is " + str(len(message.get_payload())) + "\n" print ")))))))))))))))))))) First part" print str(message.get_payload()[0]) print ">>>>>>>>>>>>>>>>>>>> Second part" print str(message.get_payload()[1]) print "attachments_contenttype is (%s)" % (attachments_contenttype, ) print "attachments_ok is (%s)" % (attachments_ok, ) if attachments: print "Yeah, attachments were found: %d" % (len(attachments), ) print "EXCEPTION " + str(e) + "\n" traceback.print_exc(file=sys.stdout)
def get_msg(message): if not message.is_multipart(): return message.get_payload() return '\n\n'.join([str(m) for m in message.get_payload()])
def main(): global folder_name global folder_name_call unread_messages = 0 unread_messages_call = 0 message_number = [] message_number_call = [] date_list = [] shipment_list = [] address_list = [] datas_list = [] price_list = [] date_list_call = [] datas_list_call = [] # CONNECT ----------------------------------------------- password, server, login = get_pass() print("Connecting to {}...".format(server)) imap = imaplib.IMAP4_SSL(server) print("Connected! Logging in as {}...".format(login)) imap.login(login, password) print("Logged in! Listing folders...") # -------------------------------------------------------- folders = [] for item in imap.list()[1]: folder_raw = imap_utf7.decode(item) try: folder = folder_raw.split('"')[3] except IndexError: folder = folder_raw.split('"')[2] if folder == 'INBOX|юмакс заказы': folder_number = imap.list()[1].index(item) folder_name = imap.list()[1][folder_number].decode('utf-8').split( '"')[-2] if folder == 'юммаксзвонки': # print('Haaaaalllooooo!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') # print(item, type(item)) # print(str(item).split('"')) folder_number_call = imap.list()[1].index(item) folder_name_call = imap.list()[1][folder_number_call].decode( 'utf-8').split('"')[-2] folders.append(folder) # print(folder) # ENTER THE FOLDER ------------------------------------------------ date_list_call, datas_list_call, unread_messages_call, message_number_call = get_calls( imap, folder_name_call) status, select_data = imap.select(folder_name) letters_list = imap.search(None, 'ALL') # ---------------------------------------------------------------- # CYCLE FOR LETTERS ---------------------------------------------- # for i in ['26']: # for i in [str(x) for x in range(1, 5)]: for i in letters_list[1][0].split(): cur_letter = imap.fetch(i, '(RFC822)') # print('current letter: {}'.format(cur_letter)) status, data = imap.fetch( i, '(RFC822)') # .encoding('utf-8') '(RFC822)' message = email.message_from_bytes(data[0][1], _class=email.message.EmailMessage) # DATE --------------------------------------------------------- date = list(email.utils.parsedate_tz(message['Date']))[:3] date_out = '' for _ in date: date_out += str(_) + '.' date_final = date_out[0:-1] # -------------------------------------------------------------- # soup = BeautifulSoup(message.get_payload(decode=True), 'html5lib') soup = BeautifulSoup(message.get_payload(decode=True), 'lxml') try: # PRICE ----------------------------------------------------- try: price = 0 if soup.strong: price = soup.strong.string.split('=')[0] price = [x for x in price if x.isdigit() or x == '.'] price_str = ''.join(price) price = float(price_str) # ------------------------------------------------------------ # DATAS -------------------------- datas = soup.findAll('p')[0].findAll('b') # print(datas) datas_out = list(map(lambda x: x.string, datas)) # print(datas_out) datas_final = '' for _ in datas_out: if _: datas_final += _ + ' ' # '\n' + ' ' datas_final = datas_final[0:] # -------------------------------------------------------------- # ADDRESS ------------------------------------------------------ address = str(soup.findAll('p')[2].contents[0]) # print(address) if ',' in list(address): address = str(address).replace(',', '') # -------------------------------------------------------------- shipment = '' if len(soup.findAll('p')) > 4: shipment = str(soup.findAll('p')[4].contents[0]) shipment = shipment.replace('\\', '') # print(shipment) # DATAFRAME --------------------------------------------------------- date_list.append(date_final) shipment_list.append(shipment) price_list.append(price) address_list.append(address) datas_list.append(datas_final) # ----------------------------------------------------------------------- # print(date_final, shipment, price, address, datas_final) except AttributeError as e: print('Ошибка:\n', traceback.format_exc()) print('AttributeError') unread_messages += 1 message_number.append(i) except IndexError as err: print('Ошибка:\n', traceback.format_exc()) print('IndexError') unread_messages += 1 message_number.append(i) print('unread messages : {}'.format(unread_messages)) print('unread messages call: {}'.format(unread_messages_call)) print('unread messages numbers: {}'.format(message_number)) print('unread messages numbers call: {}'.format(message_number_call)) # print(datas_list) # print(datas_list_call) writer = ExcelWriter('Заказы и звонки.xlsx') df = DataFrame({ 'Date': date_list, 'Shipment': shipment_list, 'Price': price_list, 'Address': address_list, 'Personal data': datas_list }) df_call = DataFrame({ 'Date': date_list_call, 'Personal data': datas_list_call }) df.to_excel(writer, 'Заказы', index=False) df_call.to_excel(writer, 'Звонки', index=False) writer.save() imap.logout()