def test_plain_rtf_back(message, copy): # test for #7067 message.SetProps([SPropValue(PR_BODY, u"abcé'def".encode('utf8'))]) message.SaveChanges(0) props = message.GetProps([PR_BODY], 0) assert props[0].Value == u"abcé'def".encode('utf8') stream = message.OpenProperty(PR_HTML, IID_IStream, 0, 0) html = stream.Read(10240) assert html == b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\n<HTML>\n<HEAD>\n<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">\n<META NAME="Generator" CONTENT="Kopano HTML builder 1.0">\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n<!-- Converted from text/plain format -->\n\n<P><FONT STYLE="font-family: courier" SIZE=2>\nabcé\'def</FONT>\n</P>\n\n</BODY></HTML>' stream = message.OpenProperty(PR_RTF_COMPRESSED, IID_IStream, 0, 0) rtfprop = WrapCompressedRTFStream(stream, 0) rtf = rtfprop.Read(10240) assert rtf == b"{\\rtf1\\ansi\\ansicpg1252\\fromtext \\deff0{\\fonttbl\n{\\f0\\fswiss Arial;}\n{\\f1\\fmodern Courier New;}\n{\\f2\\fnil\\fcharset2 Symbol;}\n{\\f3\\fmodern\\fcharset0 Courier New;}}\n{\\colortbl\\red0\\green0\\blue0;\\red0\\green0\\blue255;}\n\\uc1\\pard\\plain\\deftab360 \\f0\\fs20 abc\\'E9'def}" # force generate from RTF to html by excluding PR_HTML message.CopyTo([], [PR_HTML], 0, None, IID_IMessage, copy, 0) stream = copy.OpenProperty(PR_HTML, IID_IStream, 0, 0) html = stream.Read(10240) # conversion is quite different (enters \r\n instead of \n, charset not us-ascii anymore) # so just find the real corruption error and test that. (faulty code generated 'abc\x9\xdef') # depending on the converter and copy source body, either one can be correct, except for the faulty one mentioned. assert html.find(b"abcé'def") != -1 or html.find( b"abcé'def") != -1
def stream(mapiobj, proptag): stream = mapiobj.OpenProperty(proptag, IID_IStream, 0, 0) if proptag == PR_RTF_COMPRESSED: stream = WrapCompressedRTFStream(stream, 0) block_size = 0x100000 # 1MB data = [] while True: temp = stream.Read(block_size) data.append(temp) if len(temp) < block_size: break data = b''.join(data) if PROP_TYPE(proptag) == PT_UNICODE: data = data.decode('utf-32le') # under windows them be utf-16le? return data
def test_HTMLToRTFAndBack(message, copy): # test for #7244 message.SetProps([ SPropValue(PR_INTERNET_CPID, 28605), SPropValue(PR_HTML, b'<html><body>I’d like that.<br></body></html>') ]) plain = message.GetProps([PR_BODY_W], 0)[0].Value assert plain == 'I’d like that.\r\n' stream = message.OpenProperty(PR_RTF_COMPRESSED, IID_IStream, 0, 0) rtfprop = WrapCompressedRTFStream(stream, 0) rtf = rtfprop.Read(10240) assert rtf == b'{\\rtf1\\ansi\\ansicpg1252\\fromhtml1 \\deff0{\\fonttbl\r\n{\\f0\\fswiss\\fcharset0 Arial;}\r\n{\\f1\\fmodern Courier New;}\r\n{\\f2\\fnil\\fcharset2 Symbol;}\r\n{\\f3\\fmodern\\fcharset0 Courier New;}\r\n{\\f4\\fswiss\\fcharset0 Arial;}\r\n{\\f5\\fswiss Tahoma;}\r\n{\\f6\\fswiss\\fcharset0 Times New Roman;}}\r\n{\\colortbl\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green0\\blue255;}\r\n\\uc1\\pard\\plain\\deftab360 \\f0\\fs24 \r\n{\\*\\htmltag19 <html>}{\\*\\htmltag64}\r\n{\\*\\htmltag50 <body>}{\\*\\htmltag64}I\\htmlrtf \\u8217 ?\\htmlrtf0{\\*\\htmltag80’}d like that.\r\n{\\*\\htmltag112 <br>}{\\*\\htmltag64}\\htmlrtf \\line \\htmlrtf0 \r\n{\\*\\htmltag58 </body>}{\\*\\htmltag64}\r\n{\\*\\htmltag27 </html>}{\\*\\htmltag64}}\r\n' message.SaveChanges(0) # note: this copies the PR_RTF_COMPRESSED, and re-creates the plain+html bodies in copy. (rtf->html + rtf->plain) message.CopyTo([], None, 0, None, IID_IMessage, copy, 0) html = copy.GetProps([PR_HTML], 0)[0].Value # previously, we had a leading enter here because of rtf conversion (we could strip that in Util::HrHtmlToRtf()) # but since we now copy from plain again, the enter isn't present anymore assert html == b"<html><body>I’d like that.<br></body></html>" plain = copy.GetProps([PR_BODY_W], 0)[0].Value assert plain == 'I’d like that.\r\n'
def PreSending(self, session, addrbook, store, folder, message): if not os.path.isdir(self.disclaimerdir): self.logger.logWarn( "!--- Disclaimer directory '%s' doesn't exist." % self.disclaimerdir) return MP_CONTINUE, company = None props = store.GetProps([PR_USER_ENTRYID], 0) if props[0].ulPropTag == PR_USER_ENTRYID: currentuser = session.OpenEntry(props[0].Value, None, 0) userprops = currentuser.GetProps([PR_EC_COMPANY_NAME_W], 0) if userprops[0].ulPropTag == PR_EC_COMPANY_NAME_W and len( userprops[0].Value) > 0: company = userprops[0].Value.encode("utf-8") self.logger.logDebug("*--- Company name is '%s'" % (company)) bodytag = self.bestBody(message) self.logger.logDebug("*--- The message bestbody 0x%08X" % bodytag) if bodytag == PR_BODY_W: disclaimer = u"\r\n" + codecs.decode( self.getDisclaimer('txt', company), 'utf-8') bodystream = message.OpenProperty(PR_BODY_W, IID_IStream, 0, MAPI_MODIFY) bodystream.Seek(0, STREAM_SEEK_END) bodystream.Write(disclaimer.encode('utf-32-le')) bodystream.Commit(0) elif bodytag == PR_HTML: charset = "us-ascii" props = message.GetProps([PR_INTERNET_CPID], 0) if props[0].ulPropTag == PR_INTERNET_CPID: charset = self.getCharSetByCP(props[0].Value) disclaimer = u"<br>" + codecs.decode( self.getDisclaimer('html', company), 'utf-8') stream = message.OpenProperty(PR_HTML, IID_IStream, 0, MAPI_MODIFY) stream.Seek(0, STREAM_SEEK_END) stream.Write(disclaimer.encode(charset)) stream.Commit(0) elif bodytag == PR_RTF_COMPRESSED: self.logger.logWarn("!--- RTF disclaimer is not supported") # RTF not supported because this cause body issues. return MP_CONTINUE, rtf = self.getDisclaimer('rtf', company) stream = message.OpenProperty(PR_RTF_COMPRESSED, IID_IStream, 0, MAPI_MODIFY) uncompressed = WrapCompressedRTFStream(stream, MAPI_MODIFY) # Find end tag uncompressed.Seek(-5, STREAM_SEEK_END) data = uncompressed.Read(5) for i in range(4, 0, -1): if data[i] == '}': uncompressed.Seek(i - 5, STREAM_SEEK_END) break uncompressed.Write(rtf) uncompressed.Commit(0) stream.Commit(0) else: self.logger.logWarn("!--- No Body exists") return MP_CONTINUE,