Exemple #1
0
def test_deleteprop_doesnotexists(message):
    tag = PROP_TAG(PT_STRING8, 0x6600)
    problems = message.DeleteProps([tag])
    assert len(problems) == 1
    assert problems[0].ulIndex == 0
    assert PROP_ID(problems[0].ulPropTag) == PROP_ID(tag)
    assert problems[0].scode == MAPI_E_NOT_FOUND
def test_get(message):
    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 20)], MAPI_CREATE)
    assert len(ids) == 1
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_TYPE(ids[0]) == PT_UNSPECIFIED

    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 20)], 0)
    assert len(ids) == 1
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_TYPE(ids[0]) == PT_UNSPECIFIED
def test_createnewmulti(message):
    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 10), MAPINAMEID(b'1234567890123456', MNID_ID,11)], MAPI_CREATE)
    assert len(ids) == 2
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_ID(ids[1]) >= 0x8500

    tag = ids[1]
    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 11), MAPINAMEID(b'1234567890123456', MNID_ID,12)], MAPI_CREATE)

    assert len(ids) == 2
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_ID(ids[1]) >= 0x8500
    assert tag == ids[0]
def test_createnew2(message):
    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 5)], MAPI_CREATE)
    assert len(ids) == 1
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_TYPE(ids[0]) == PT_UNSPECIFIED

    tag = ids[0]
    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 5)], MAPI_CREATE)
    assert len(ids) == 1
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_TYPE(ids[0]) == PT_UNSPECIFIED
    assert tag == ids[0]

    ids = message.GetIDsFromNames([MAPINAMEID(b'1234567890123456', MNID_ID, 6)], MAPI_CREATE)
    assert len(ids) == 1
    assert PROP_ID(ids[0]) >= 0x8500
    assert PROP_TYPE(ids[0]) == PT_UNSPECIFIED
    assert tag != ids[0]
Exemple #5
0
def test_hiearchyid(store, message):
    # get on an unsaved prop, returns not found
    props = message.GetProps([PR_EC_HIERARCHYID], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_EC_HIERARCHYID))
    assert props[0].Value == MAPI_E_NOT_FOUND
    # must be present after save/reopen
    message.SaveChanges(0)
    hid = message.GetProps([PR_EC_HIERARCHYID], 0)[0].Value
    eid = message.GetProps([PR_ENTRYID], 0)[0].Value

    message = store.OpenEntry(eid, None, 0)
    # first prop to get is generated, loadObject did not happen, but should
    assert message.GetProps([PR_EC_HIERARCHYID], 0)[0].Value == hid
Exemple #6
0
def test_recordkey(message):
    props = message.GetProps([PR_RECORD_KEY], 0)
    assert props[0] == SPropValue(PROP_TAG(PT_ERROR, PROP_ID(PR_RECORD_KEY)), MAPI_E_NOT_FOUND)
    message.SaveChanges(KEEP_OPEN_READWRITE)
    props = message.GetProps([PR_RECORD_KEY, PR_ENTRYID], 0)
    assert props[0].ulPropTag == PR_RECORD_KEY
    assert len(props[0].Value) == 48
    assert props[0].Value == props[1].Value

    (id, att) = message.CreateAttach(None, 0)
    att.SetProps([SPropValue(PR_ATTACH_METHOD, ATTACH_EMBEDDED_MSG)])
    sub = att.OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, 0, MAPI_CREATE | MAPI_MODIFY)
    props = sub.GetProps([PR_RECORD_KEY, PR_ENTRYID, PR_SOURCE_KEY], 0)

    # Unsaved submessages have a source key but no record key or entryid
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RECORD_KEY))
    assert props[0].Value == MAPI_E_NOT_FOUND
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_ENTRYID))
    assert props[1].Value == MAPI_E_NOT_FOUND
    assert props[2].ulPropTag == PR_SOURCE_KEY
    assert len(props[2].Value) == 22

    sub.SaveChanges(0)
    att.SaveChanges(0)
    message.SaveChanges(0)

    att = message.OpenAttach(0, None, 0)
    sub = att.OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, 0, 0)
    props = sub.GetProps([PR_RECORD_KEY, PR_ENTRYID, PR_SOURCE_KEY], 0)

    # Saved submessages have a PR_SOURCE_KEY but no record key or entryid
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RECORD_KEY))
    assert props[0].Value == MAPI_E_NOT_FOUND
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_ENTRYID))
    assert props[1].Value == MAPI_E_NOT_FOUND
    assert props[2].ulPropTag == PR_SOURCE_KEY
    assert len(props[2].Value) == 22
Exemple #7
0
def test_subject_unicode(store, message):
    # Normalized subject not found if no subject is present
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PROP_TAG(PT_ERROR, PROP_ID(PR_NORMALIZED_SUBJECT_W)), MAPI_E_NOT_FOUND)]

    # Subject prefix is generated if it contains a maximum of 3 characters followed by a colon :
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re: ')]
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'test')]

    # Prefix should be correctly calculated with characters that occupy more than 1 byte
    message.SetProps([SPropValue(PR_SUBJECT_W, '回复: japanese subject')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, '回复: ')]
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'japanese subject')]

    # Although the MAPI documentation states a space must be present after the colon (:) we allow that in our code:
    # Set short prefix 'Re:', should clash with longer 'Re: ' prefix later
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re:factor')])
    subjects = message.GetProps([PR_SUBJECT_PREFIX_W, PR_NORMALIZED_SUBJECT_W], 0)
    assert subjects == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re:'),SPropValue(PR_NORMALIZED_SUBJECT_W, 'factor')]

    # If prefix is larger than 3 characters it won't be calculated and the normalized property will be equal to the subject.
    # If the prefix is manually set and equal to the beginning of the subject it will be removed from the normalized.
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Heelverhaal: test')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, '')]
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'Heelverhaal: test')]
    message.SetProps([SPropValue(PR_SUBJECT_PREFIX_W, 'Heelverhaal: ')])
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'test')]

    # If the prefix is different than intial string of the subject, the normalized will be equal to the subject
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test'), SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'Re: test')]

    # After forcing the prefix to be different, it won't be recalculated anymore
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]

    # After a reload we calculate the prefix again
    message.SaveChanges(KEEP_OPEN_READWRITE)
    entryid = message.GetProps([PR_ENTRYID], 0)
    m2 = store.OpenEntry(entryid[0].Value, None, MAPI_MODIFY)
    m2.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    prefix = m2.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re: ')]

    # And the original message after save changes will also recalculate the prefix
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re: ')]

    # If we delete the message the prefix should not be found anymore
    message.DeleteProps([PR_SUBJECT_W])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PROP_TAG(PT_ERROR, PROP_ID(PR_SUBJECT_PREFIX_W)), MAPI_E_NOT_FOUND)]

    # If we set it explicitly and then delete the subject, we'll keep the prefix
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test'), SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]
    message.DeleteProps([PR_SUBJECT_W])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]

    # If we delete the prefix and then set the subject it will be synced again.
    message.DeleteProps([PR_SUBJECT_W, PR_SUBJECT_PREFIX_W])
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re:factor')])
    prefix = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert prefix == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re:')]
Exemple #8
0
def test_deleteprop_computed(message):
    problems = message.DeleteProps([PR_ENTRYID])
    assert len(problems) == 1
    assert problems[0].ulIndex == 0
    assert PROP_ID(problems[0].ulPropTag) == PROP_ID(PR_ENTRYID)
    assert problems[0].scode == MAPI_E_COMPUTED
Exemple #9
0
def test_plain(store, message):
    message.SetProps([SPropValue(PR_BODY, b'pr_body')])
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED, PR_HTML], 0)
    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_body'
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED))
    assert props[1].Value == MAPI_E_NOT_FOUND
    assert props[2].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[2].Value == MAPI_E_NOT_FOUND

    # Retest after reload
    message.SaveChanges(0)
    entryid = message.GetProps([PR_ENTRYID], 0)[0].Value
    message = store.OpenEntry(entryid, None, 0)
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED, PR_HTML], 0)

    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_body'
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED))
    assert props[1].Value == MAPI_E_NOT_FOUND
    assert props[2].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[2].Value == MAPI_E_NOT_FOUND

    # Try two properties

    # BODY, RTF
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED], 0)
    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_body'
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED))
    assert props[1].Value == MAPI_E_NOT_FOUND

    # BODY, HTML
    props = message.GetProps([PR_BODY, PR_HTML], 0)
    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_body'
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[1].Value == MAPI_E_NOT_FOUND

    # RTF, HTML
    props = message.GetProps([PR_RTF_COMPRESSED, PR_HTML], 0)
    assert props[0].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[0].Value) > 0
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[1].Value == MAPI_E_NOT_FOUND

    # Try one property

    # BODY
    props = message.GetProps([PR_BODY], 0)
    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_body'

    # RTF
    props = message.GetProps([PR_RTF_COMPRESSED], 0)
    assert props[0].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[0].Value) > 0

    # HTML
    props = message.GetProps([PR_HTML], 0)
    assert props[0].ulPropTag == PR_HTML
    assert len(props[0].Value) > 0
Exemple #10
0
def test_html(store, message):
    message.SetProps([SPropValue(PR_HTML, b"pr_html_body")])
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED, PR_HTML], 0)

    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY
    bodystream = message.OpenProperty(PR_BODY, IID_IStream, 0, 0)
    assert bodystream.Read(4096) == b'pr_html_body'
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED))
    assert props[1].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[2].ulPropTag == PR_HTML
    assert props[2].Value == b'pr_html_body'

    # Retest after reload
    message.SaveChanges(0)
    entryid = message.GetProps([PR_ENTRYID], 0)[0].Value
    message = store.OpenEntry(entryid, None, 0)
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED, PR_HTML], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY

    bodystream = message.OpenProperty(PR_BODY, IID_IStream, 0, 0)
    assert bodystream.Read(4096) == b'pr_html_body'
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED))
    assert props[1].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[2].ulPropTag == PR_HTML
    assert props[2].Value == b'pr_html_body'

    # Try two properties

    # BODY == RTF
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[1].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[1].Value)

    # BODY == HTML
    props = message.GetProps([PR_BODY, PR_HTML], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[1].ulPropTag == PR_HTML
    assert props[1].Value == b'pr_html_body'

    # RTF == HTML
    props = message.GetProps([PR_RTF_COMPRESSED, PR_HTML], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_RTF_COMPRESSED))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[1].ulPropTag == PR_HTML
    assert props[1].Value == b'pr_html_body'

    # Try one property

    # BODY
    props = message.GetProps([PR_BODY], 0)
    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_html_body'

    # RTF
    props = message.GetProps([PR_RTF_COMPRESSED], 0)
    assert props[0].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[0].Value) > 0

    # HTML
    props = message.GetProps([PR_HTML], 0)
    assert props[0].ulPropTag == PR_HTML
    assert props[0].Value == b'pr_html_body'
Exemple #11
0
def test_rtf(store, message):
    rtfprop = message.OpenProperty(PR_RTF_COMPRESSED, IID_IStream, 0,
                                   MAPI_MODIFY | MAPI_CREATE)
    rtf = WrapCompressedRTFStream(rtfprop, 0)
    rtf.Write(b'pr_rtf_compressed')
    rtf.Commit(0)
    rtfprop.Seek(STREAM_SEEK_SET, 0)
    compdata = rtfprop.Read(4096)
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED, PR_HTML], 0)

    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY

    bodystream = message.OpenProperty(PR_BODY, IID_IStream, 0, 0)
    assert bodystream.Read(4096) == b'pr_rtf_compressed\r\n'
    assert props[1].ulPropTag == PR_RTF_COMPRESSED
    assert props[1].Value == compdata
    assert props[2].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[2].Value == MAPI_E_NOT_FOUND

    # Retest after reload
    message.SaveChanges(0)
    entryid = message.GetProps([PR_ENTRYID], 0)[0].Value
    message = store.OpenEntry(entryid, None, 0)
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED, PR_HTML], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY

    bodystream = message.OpenProperty(PR_BODY, IID_IStream, 0, 0)
    assert bodystream.Read(4096) == b'pr_rtf_compressed\r\n'
    assert props[1].ulPropTag == PR_RTF_COMPRESSED
    assert props[1].Value == compdata
    assert props[2].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[2].Value == MAPI_E_NOT_FOUND

    # Try two properties

    # BODY == RTF
    props = message.GetProps([PR_BODY, PR_RTF_COMPRESSED], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[1].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[1].Value)

    # BODY == HTML
    props = message.GetProps([PR_BODY, PR_HTML], 0)
    assert props[0].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_BODY))
    assert props[0].Value == MAPI_E_NOT_ENOUGH_MEMORY
    assert props[1].ulPropTag == PR_HTML
    assert len(props[1].Value) > 0

    # RTF == HTML
    props = message.GetProps([PR_RTF_COMPRESSED, PR_HTML], 0)
    assert props[0].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[0].Value) > 0
    assert props[1].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML))
    assert props[1].Value == MAPI_E_NOT_FOUND

    # Try one property

    # BODY
    props = message.GetProps([PR_BODY], 0)
    assert props[0].ulPropTag == PR_BODY
    assert props[0].Value == b'pr_rtf_compressed\r\n'

    # RTF
    props = message.GetProps([PR_RTF_COMPRESSED], 0)
    assert props[0].ulPropTag == PR_RTF_COMPRESSED
    assert len(props[0].Value) > 0

    # HTML
    props = message.GetProps([PR_HTML], 0)
    assert props[0].ulPropTag == PR_HTML
    assert len(props[0].Value) > 0
Exemple #12
0
def test_subject_unicode(store, message):
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PROP_TAG(PT_ERROR, PROP_ID(PR_NORMALIZED_SUBJECT_W)), MAPI_E_NOT_FOUND)]
    # set short prefix 'Re:', should clash with longer 'Re: ' prefix later
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re:factor')])
    subjects = message.GetProps([PR_SUBJECT_PREFIX_W, PR_NORMALIZED_SUBJECT_W], 0)
    assert subjects == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re:'),SPropValue(PR_NORMALIZED_SUBJECT_W, 'factor')]
    #subject prefix is synced, normalized is short
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re: ')]
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'test')]
    #subject prefix is synced, normalized is same
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Heelverhaal: test')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, '')]
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'Heelverhaal: test')]
    #subject prefix is still synced
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Fw: test')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject, [SPropValue(PR_SUBJECT_PREFIX_W, 'Fw: ')]
    #explicit is not synced anymore
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test'), SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')])
    normalized = message.GetProps([PR_NORMALIZED_SUBJECT_W], 0)
    assert normalized == [SPropValue(PR_NORMALIZED_SUBJECT_W, 'test')]
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]
    # once you've SetPropsed PR_SUBJECT_PREFIX_W, it's not touched anymore
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]
    # and after a reload?
    message.SaveChanges(KEEP_OPEN_READWRITE)
    entryid = message.GetProps([PR_ENTRYID], 0)
    m2 = store.OpenEntry(entryid[0].Value, None, MAPI_MODIFY)
    m2.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    subject = m2.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re: ')]
    # and orig message after save changes?
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re: ')]
    # what after deleting?
    message.DeleteProps([PR_SUBJECT_W])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PROP_TAG(PT_ERROR, PROP_ID(PR_SUBJECT_PREFIX_W)), MAPI_E_NOT_FOUND)]
    # explicit is not synced anymore
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re: test'), SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]
    # what after deleting expliclit?
    message.DeleteProps([PR_SUBJECT_W])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Aap')]
    # no spaces, delete explicit prefix to sync again
    message.DeleteProps([PR_SUBJECT_W, PR_SUBJECT_PREFIX_W])
    message.SetProps([SPropValue(PR_SUBJECT_W, 'Re:factor')])
    subject = message.GetProps([PR_SUBJECT_PREFIX_W], 0)
    assert subject == [SPropValue(PR_SUBJECT_PREFIX_W, 'Re:')]