def test_multiple(self): part1 = multipart.MessagePart( entity_body=b"plain text version\r\n") part1.set_content_type("text/plain; charset=us-ascii") part2 = multipart.MessagePart( entity_body=b"RFC 1896 text/enriched version\r\n") part2.set_content_type("text/enriched") part3 = multipart.MessagePart( entity_body=b"fanciest version\r\n") part3.set_content_type("application/x-whatever") mtype = MediaType.from_str( "multipart/alternative; boundary=boundary42") mstream = multipart.MultipartSendWrapper(mtype, [part1, part2, part3]) self.assertTrue( mstream.read() == b"--boundary42\r\n" b"Content-Type: text/plain; charset=us-ascii\r\n" b"\r\n" b"plain text version\r\n" b"\r\n" b"--boundary42\r\n" b"Content-Type: text/enriched\r\n" b"\r\n" b"RFC 1896 text/enriched version\r\n" b"\r\n" b"--boundary42\r\n" b"Content-Type: application/x-whatever\r\n" b"\r\n" b"fanciest version\r\n" b"\r\n" b"--boundary42--")
def test_read_nonblocking(self): src = io.BytesIO(b"How are you?\n" * 10) src = MockBlockingByteReader(src, block_after=((10,))) part = multipart.MessagePart(entity_body=src) part.set_content_type("text/plain") mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") mstream = multipart.MultipartSendWrapper(mtype, [part]) # non-blocking non-empty stream lines = [] line = [] blocks = 0 while True: c = mstream.read(1) if c: if c == b"\n": # end of line lines.append(b"".join(line)) line = [] else: line.append(c) elif c is None: blocks += 1 else: break # our mock blocking stream always returns None at least once self.assertTrue(blocks > 1, "non-blocking stream failed to stall") boundary = lines.index(b"\r") self.assertTrue(boundary > 0, lines) for line in lines[boundary + 1:boundary + 11]: self.assertTrue(line == b"How are you?") mstream.close()
def test_readlines_crlf(self): # Now repeat the exercise with maximal CRLF part = multipart.MessagePart(entity_body=b"\r\nHow are you?\r\n") part.set_content_type("text/plain") mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") mstream = multipart.MultipartSendWrapper( mtype, [part], preamble=b"\r\nJust wanted to ask\r\n", epilogue=b"\r\nFine thanks!\r\n") lines = mstream.readlines() matches = [ b"\r\n", b"Just wanted to ask\r\n", b"\r\n", b"--gc0p4Jq0M2Yt08j34c0p\r\n", b"Content-Type: text/plain\r\n", b"\r\n", b"\r\n", b"How are you?\r\n", b"\r\n", b"--gc0p4Jq0M2Yt08j34c0p--\r\n", b"\r\n", b"Fine thanks!\r\n"] self.assertTrue(len(lines) == len(matches), lines) for line, match in zip(lines, matches): self.assertTrue(line == match, "Failed to match: %s" % match) mstream.close()
def test_constructor(self): part = multipart.MessagePart() mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") # pass in an iterable of MessageParts and required mime type mstream = multipart.MultipartSendWrapper(mtype, [part]) try: mstream.fileno() self.fail("MultipartSendWrapper.fileno") except IOError: pass # flush does nothing but is callable mstream.flush() self.assertFalse(mstream.isatty()) self.assertTrue(mstream.readable()) mstream.close() # can add an optional preamble, epilogue and boundary mstream = multipart.MultipartSendWrapper( mtype, [part], preamble=b"Hello", epilogue=b"Goodbye")
def test_write(self): part = multipart.MessagePart(entity_body=b"How are you?") part.set_content_type("text/plain") mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") mstream = multipart.MultipartSendWrapper(mtype, [part]) self.assertFalse(mstream.writable()) try: mstream.write(b"Hello") self.fail("MultipartSendWrapper.write") except IOError: pass mstream.close()
def test_nested(self): part_a = multipart.MessagePart(entity_body=b"Introduction") part_a.set_content_type("text/plain") part1 = multipart.MessagePart( entity_body=b"plain text version\r\n") part1.set_content_type("text/plain; charset=us-ascii") part2 = multipart.MessagePart( entity_body=b"RFC 1896 text/enriched version\r\n") part2.set_content_type("text/enriched") mtype = MediaType.from_str( 'multipart/alternative; boundary="---- next message ----"') mstream = multipart.MultipartSendWrapper(mtype, [part1, part2]) part_b = multipart.MessagePart(entity_body=mstream) part_b.set_content_type(mtype) mtype = MediaType.from_str( 'multipart/mixed; boundary="---- main boundary ----"') mstream = multipart.MultipartSendWrapper(mtype, [part_a, part_b]) result = mstream.read() self.assertTrue( result == b"------ main boundary ----\r\n" b'Content-Type: text/plain\r\n' b"\r\n" b"Introduction\r\n" b"------ main boundary ----\r\n" b"Content-Type: multipart/alternative; " b'boundary="---- next message ----"\r\n' b"\r\n" b"------ next message ----\r\n" b"Content-Type: text/plain; charset=us-ascii\r\n" b"\r\n" b"plain text version\r\n" b"\r\n" b"------ next message ----\r\n" b"Content-Type: text/enriched\r\n" b"\r\n" b"RFC 1896 text/enriched version\r\n" b"\r\n" b"------ next message ------\r\n" b"------ main boundary ------", repr(result))
def test_close(self): part = multipart.MessagePart() mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") # pass in an iterable of MessageParts mstream = multipart.MultipartSendWrapper(mtype, [part]) self.assertFalse(mstream.closed) mstream.close() self.assertTrue(mstream.closed) try: mstream.read(1) self.fail("MultipartSendWrapper.read after close") except IOError: pass
def test_readline(self): part = multipart.MessagePart(entity_body=b"How are you?") part.set_content_type("text/plain") mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") mstream = multipart.MultipartSendWrapper(mtype, [part]) # preamble is empty, straight into the boundary self.assertTrue( mstream.readline() == b"--gc0p4Jq0M2Yt08j34c0p\r\n") self.assertTrue( mstream.readline() == b"Content-Type: text/plain\r\n") # blank line self.assertTrue(mstream.readline() == b"\r\n") # body self.assertTrue(mstream.readline() == b"How are you?\r\n") # terminating boundary has NO CRLF self.assertTrue( mstream.readline() == b"--gc0p4Jq0M2Yt08j34c0p--")
def test_read(self): part = multipart.MessagePart(entity_body=b"How are you?") part.set_content_type("text/plain") mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") mstream = multipart.MultipartSendWrapper( mtype, [part], preamble=b"Just wanted to ask\r\n...", epilogue=b"Fine\r\nthanks!") # blocking stream c = mstream.read(1) self.assertTrue(c == b"J") line = [] while c != b"\n": line.append(c) c = mstream.read(1) # won't return None self.assertTrue(len(c) == 1) self.assertTrue( b"".join(line) == b'Just wanted to ask\r') data = mstream.read() self.assertTrue(data.endswith(b"Fine\r\nthanks!"), data) self.assertTrue(mstream.read(1) == b"") mstream.close()
def test_readlines(self): # Now try with preamble and epilogue (no CRLF) part = multipart.MessagePart(entity_body=b"How are you?") part.set_content_type("text/plain") mtype = MediaType.from_str( "multipart/mixed; boundary=gc0p4Jq0M2Yt08j34c0p") mstream = multipart.MultipartSendWrapper( mtype, [part], preamble=b"Just wanted to ask\r\n...", epilogue=b"Fine\r\nthanks!") lines = mstream.readlines() matches = [ b"Just wanted to ask\r\n", b"...\r\n", b"--gc0p4Jq0M2Yt08j34c0p\r\n", b"Content-Type: text/plain\r\n", b"\r\n", b"How are you?\r\n", b"--gc0p4Jq0M2Yt08j34c0p--\r\n", b"Fine\r\n", b"thanks!"] self.assertTrue(len(lines) == len(matches)) for line, match in zip(lines, matches): self.assertTrue(line == match, "Failed to match: %s" % match) mstream.close()