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_content_transfer_encoding(self):
     part = multipart.MessagePart()
     # value is a single token, represented as a character string
     for token in ("7bit", "8bit", "binary", "quoted-printable",
                   "base64", "x-custom", "BINARY"):
         part.set_content_transfer_encoding(token)
         self.assertTrue(part.get_header('Content-Transfer-Encoding') ==
                         token.encode('ascii'))
         self.assertTrue(is_text(part.get_content_transfer_encoding()))
         self.assertTrue(part.get_content_transfer_encoding() ==
                         token.lower())
     # default is 7bit
     part.set_header('Content-Transfer-Encoding', None)
     self.assertTrue(part.get_content_transfer_encoding() == '7bit')
     # bad tokens should raise an error on set
     try:
         part.set_content_transfer_encoding("9:bit")
         self.fail("bad token in content-transfer-encoding (set)")
     except ValueError:
         pass
     part.set_header('Content-Transfer-Encoding', b"9:bit")
     # badly formed should be treated as an unrecognized value
     self.assertTrue(part.get_content_transfer_encoding() is None)
     # Any entity with an unrecognized Content-Transfer-Encoding must
     # be treated as if it has a Content-Type of
     # "application/octet-stream", regardless of what the
     # Content-Type header field actually says.
     self.assertTrue(part.get_content_type() == APPLICATION_OCTETSTREAM)
     part.set_content_type("text/plain")
     self.assertTrue(part.get_content_type() == APPLICATION_OCTETSTREAM)
     part.set_content_transfer_encoding("9bit")
     self.assertTrue(part.get_content_type() == APPLICATION_OCTETSTREAM)
 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_content_id(self):
     part = multipart.MessagePart()
     # value is a character string that must be a valid addr-spec
     # spaces are removed and ignored as per specification
     part.set_content_id(" content @ pyslet.org ")
     self.assertTrue(part.get_header('Content-ID') ==
                     b"<*****@*****.**>")
     self.assertTrue(is_text(part.get_content_id()))
     self.assertTrue(part.get_content_id() == "*****@*****.**")
     try:
         part.set_content_id("content:[email protected]")
         self.fail("bad localpart in content ID")
     except grammar.BadSyntax:
         pass
     part.set_header("Content-ID", b"content:[email protected]")
     self.assertTrue(part.get_content_id() is None)
 def test_content_description(self):
     part = multipart.MessagePart()
     # any text, though non-ascii will be problematic 'the mechanism
     # specified in RFC 2047' is broken and not work implementing. we
     # treat this field as ASCII text or raw bytes with spaces trimmed
     part.set_content_description(" About my content ")
     self.assertTrue(part.get_header('Content-Description') ==
                     b"About my content")
     self.assertTrue(part.get_content_description() == b"About my content")
     try:
         part.set_content_description(ul("Caf\xe9"))
         self.fail("Content description should ASCII encode")
     except UnicodeError:
         pass
     # OK to pass raw bytes
     part.set_content_description(ul("Caf\xe9").encode('iso-8859-1'))
     self.assertTrue(part.get_header('Content-Description') == b"Caf\xe9")
     self.assertTrue(part.get_content_description() == b"Caf\xe9")
 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_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()
 def test_constructor(self):
     part = multipart.MessagePart()
     self.assertTrue(isinstance(part, http.Message))