IdCoderTNEF.pas 121 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. { Rev 1.3 16/01/2005 22:33:06 CCostelloe
  18. { Minor update
  19. }
  20. {
  21. { Rev 1.2 22/12/2004 23:09:52 CCostelloe
  22. { Another intermediate check-in, this sorts out the compressed RTF message and
  23. { (if it has one) the message .Body.
  24. }
  25. {
  26. { Rev 1.1 18/12/2004 20:35:24 CCostelloe
  27. { Intermediate check-in, lots more to be done.
  28. }
  29. {
  30. { Rev 1.0 02/12/2004 22:56:26 CCostelloe
  31. { Initial version
  32. }
  33. unit IdCoderTNEF;
  34. {
  35. This is for decoding Microsoft's TNEF email messages, which are usually
  36. transmitted as an attachment called either "WINMAIL.DAT" or "ATT00001.DAT"
  37. in a MIME-encoded message (though other variants of the file name, but not
  38. the extension, are occasionally encountered).
  39. The MIME type should be "application/ms-tnef".
  40. This is deliberately NOT similar to the other coder classes, this
  41. should usually be used by passing in a TNEF TIdAttachment which has
  42. been extracted from a message.
  43. You can optionally get a debugging log of the parsing by setting the third
  44. optional parameter to True, as in "TIdCoderTNEF.Parse(A_TIdBytes,
  45. A_TIdMessage, True);", and then load the log into a TMemo by calling
  46. "Memo1.Text := A_TIdCoderTNEF.Log;".
  47. The aim of the initial implementation was just to extract any attachments from
  48. the TNEF, along with their filenames, and put them in the TIdMessage's
  49. MessageParts for the user.
  50. Some additional applicable fields have also been parsed out of the TNEF
  51. and inserted into the TIdMessage. This is an ongoing development.
  52. METHODOLOGY:
  53. A TNEF is a collection of blocks of data, each block is either a
  54. IdTNEFLvlMessage or a IdTNEFLvlAttachment block. IdTNEFLvlAttachment
  55. blocks are straightforward, see the parsing below.
  56. A IdTNEFLvlMessage block may contain an item like the message subject,
  57. date sent, etc. However, a block may also contain a IdTNEFattMAPIProps,
  58. which contains sub-blocks corresponding to MAPI properties which will
  59. also typically include the message subject, date sent, etc.
  60. The methodology used by me is that the IdTNEFLvlMessage level takes
  61. priority, i.e. if there is a message subject at both the IdTNEFLvlMessage
  62. and the IdTNEFattMAPIProps level, then the IdTNEFLvlMessage is the one
  63. that will be used.
  64. The TIdMessage is filled in from the TNEF in a similar manner to the way
  65. Indy decodes MIME messages. Particularly note that the message text
  66. is often only in an RTF format and so it will be put in a TIdText part
  67. and NOT in the TIdMessage.Body. The TIdMessage.Body MAY contain the
  68. plain-text version of the message, IF it is present.
  69. Parts (either TIdText or TIdAttachmentFile) are added to the TIdMessage
  70. in the order they are encountered. This may be different from an
  71. RFC-compliant MIME email, which (in the case of alternative versions
  72. of the message text) puts the simplest first, i.e. text/plain
  73. before text/html before text/rtf.
  74. To do:
  75. When finished decoding, rescan the parts and insert parts like
  76. 'multipart/alternative' and set up the ParentPart pointers as required to
  77. imitate Indy's treatment of MIME parts in Indy10.
  78. For LLong, LShort, get them to get signed values.
  79. GetMapiSysTime or GetTime may be out by an hour? Time zone issue?
  80. Add meaningful headers like ContentType to message parts.
  81. Some TIdMessage fields may be found in different TNEF fields (e.g. sender/from).
  82. They don't appear to be consistent in practice, and there may be semantical
  83. differences between the usage of terms like Sender between TNEF and MIME.
  84. See the "TODO"s in the code below.
  85. }
  86. interface
  87. {$I IdCompilerDefines.inc}
  88. uses
  89. Classes,
  90. IdGlobal,
  91. IdMessage,
  92. IdException,
  93. IdAttachment,
  94. IdAttachmentFile,
  95. SysUtils;
  96. type
  97. TIdCoderTNEF = class(TObject)
  98. private
  99. FData: TStream; //Used for walking through the file
  100. FKey: Word; //Every TNEF has one, but no-one seems to know why!
  101. FLog: string; //The (optional) debugging log goes here
  102. FDoLogging: Boolean; //Should we be doing the optional logging?
  103. FMsg: TIdMessage; //The destination for our extracted attachments
  104. FCurrentAttachment: TIdAttachment; //Attachment we are currently decoding into
  105. FReceiptRequested: Boolean; //Need to cache this because receipt flag may precede sender address
  106. //
  107. procedure DoLog(const AMsg: String; const AAppendSize: Boolean = True);
  108. procedure DoLogFmt(const AFormat: string; const Args: array of const; AAppendSize: Boolean = True);
  109. //Low-level utility functions:
  110. function GetMultipleUnicodeOrString8String(AType: Word): TIdUnicodeString;
  111. function GetUnicodeOrString8String(AType: Word): TIdUnicodeString;
  112. function GetByte: Byte;
  113. function GetBytes(ALength: Integer; APeek: Boolean = False): TIdBytes;
  114. function GetByteAsHexString: string; overload;
  115. function GetByteAsHexString(AByte: Byte): string; overload;
  116. function GetByteAsChar(AByte: Byte): char;
  117. function GetBytesAsHexString(ACount: integer): string;
  118. function GetWord: Word;
  119. function GetLongWord: LongWord;
  120. function GetInt64: Int64;
  121. function GetString(ALength: Word): string;
  122. function GetDate(ALength: Word): TDateTime;
  123. procedure Skip(ACount: integer);
  124. procedure CheckForEof(ANumBytesRequested: integer);
  125. procedure Checksum(ANumBytesToCheck: integer);
  126. function PadWithZeroes(const AStr: string; ACount: integer): string;
  127. procedure DumpBytes(const ABytes: TIdBytes);
  128. //Attribute-specific stuff...
  129. function GetAttributeString(const AAttributeName: string; AType: Word): string;
  130. //MAPI parsing...
  131. function GetStringForMapiType(AType: Word): string;
  132. function GetMapiBoolean(AType: Word; const AText: string): Smallint;
  133. function GetMapiLong(AType: Word; const AText: string): Longint;
  134. function GetMapiStrings(AType: Word; const AText: string): string;
  135. function GetMapiBinary(AType: Word; const AText: string): TIdBytes;
  136. function GetMapiBinaryAsEmailName(AType: Word; const AText: string): string;
  137. function GetMapiBinaryAsString(AType: Word; const AText: string): string;
  138. //function GetMapiObject(AType: Word; AText: string): TIdBytes;
  139. function GetMapiItemAsBytes(AType: Word; const AText: string): TIdBytes;
  140. function GetMapiItemAsBytesPossiblyCompressed(AType: Word; const AText: string): TIdBytes;
  141. function DecompressRtf(ACount, ALength: LongWord; AType: Word; const AText: string): TIdBytes;
  142. function GetMapiSysTime(AType: Word; const AText: string): TDateTime;
  143. function InternalGetMapiItemAsBytes(ACount, ALength: LongWord; AType: Word; const AText: string): TIdBytes;
  144. protected
  145. procedure ParseMessageBlock;
  146. procedure ParseAttachmentBlock;
  147. procedure ParseAttribute(AAttribute, AType: Word);
  148. procedure ParseMapiProps(ALength: LongWord);
  149. procedure ParseMapiProp;
  150. procedure IsCurrentAttachmentValid;
  151. //For debugging log...
  152. function GetStringForAttribute(AAttribute: Word): string;
  153. function GetStringForType(AType: Word): string;
  154. public
  155. //The following is the normal parser call you would use...
  156. procedure Parse(const AIn: TIdAttachment; AMsg: TIdMessage; ALog: Boolean = False); overload;
  157. //TIdIMAP4 should set up a stream & use this...
  158. procedure Parse(const AIn: TStream; AMsg: TIdMessage; ALog: Boolean = False); overload;
  159. //The TIdBytes and string versions are really for debugging...
  160. procedure Parse(const AIn: TIdBytes; AMsg: TIdMessage; ALog: Boolean = False); overload;
  161. procedure Parse(const AIn: string; AMsg: TIdMessage; ALog: Boolean = False); overload;
  162. //Tells you if a filename matches TNEF semantics (winmail.dat, att0001.dat)
  163. class function IsFilenameTnef(const AFilename: string): Boolean; static; {$IFDEF HAS_DEPRECATED}deprecated{$IFDEF HAS_DEPRECATED_MSG} 'Use standalone IsFilenameTnef() function'{$ENDIF};{$ENDIF}
  164. property Key: Word read FKey; //TODO: Does this have a meaningful use?
  165. property Log: string read FLog;
  166. end;
  167. EIdTnefInvalidTNEFSignature = class(EIdException);
  168. EIdTnefRanOutOfBytes = class(EIdException);
  169. EIdTnefUnknownBlockType = class(EIdException);
  170. EIdTnefChecksumFailure = class(EIdException);
  171. EIdTnefCurrentAttachmentInvalid = class(EIdException);
  172. EIdTnefAttributeUnexpectedType = class(EIdException);
  173. EIdTnefUnexpectedType = class(EIdException);
  174. EIdTnefUnexpectedValue = class(EIdException);
  175. EIdTnefNotSupported = class(EIdException);
  176. EIdTnefUnknownMapiType = class(EIdException);
  177. EIdTnefCorruptData = class(EIdException);
  178. function IsFilenameTnef(const AFilename: string): Boolean;
  179. implementation
  180. uses
  181. {$IFDEF HAS_UNIT_DateUtils}DateUtils,{$ENDIF}
  182. IdMessageClient, IdText, IdStream;
  183. const
  184. //Initial RTF-compression decode string...
  185. IdTNEF_decode_string: string = '{\rtf1\ansi\mac\deff0\deftab720{\fonttbl;}{\f0\fnil \froman \fswiss \fmodern \fscript \fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\colortbl\red0\green0\blue0'+#10#13+'\par \pard\plain\f0\fs20\b\i\u\tab\tx'; {Do not localize}
  186. //The following are equivalents to those defined Microsoft's TNEF.H.
  187. //File signature...
  188. IdTNEFSignature = $223E9F78; //Every TNEF should have this
  189. //Highest-level block types...
  190. IdTNEFLvlMessage = 1; //Corresponds to Microsoft's LVL_MESSAGE
  191. IdTNEFLvlAttachment = 2; //Corresponds to Microsoft's LVL_ATTACHMENT
  192. //Data types...
  193. IdTNEFAtpTriples = 0; //Corresponds to Microsoft's AtpTriples, similarly for the following
  194. IdTNEFAtpString = 1;
  195. IdTNEFAtpText = 2;
  196. IdTNEFAtpDate = 3;
  197. IdTNEFAtpShort = 4;
  198. IdTNEFAtpLong = 5;
  199. IdTNEFAtpByte = 6;
  200. IdTNEFAtpWord = 7;
  201. IdTNEFAtpDWord = 8;
  202. IdTNEFAtpMax = 9;
  203. //Attribute types...
  204. IdTNEFattNull = $0000;
  205. IdTNEFattFrom = $8000; // /* PR_ORIGINATOR_RETURN_ADDRESS */
  206. IdTNEFattSubject = $8004; // /* PR_SUBJECT */
  207. IdTNEFattDateSent = $8005; // /* PR_CLIENT_SUBMIT_TIME */
  208. IdTNEFattDateRecd = $8006; // /* PR_MESSAGE_DELIVERY_TIME */
  209. IdTNEFattMessageStatus = $8007; // /* PR_MESSAGE_FLAGS */
  210. IdTNEFattMessageClass = $8008; // /* PR_MESSAGE_CLASS */
  211. IdTNEFattMessageID = $8009; // /* PR_MESSAGE_ID */
  212. IdTNEFattParentID = $800A; // /* PR_PARENT_ID */
  213. IdTNEFattConversationID = $800B; // /* PR_CONVERSATION_ID */
  214. IdTNEFattBody = $800C; // /* PR_BODY */
  215. IdTNEFattPriority = $800D; // /* PR_IMPORTANCE */
  216. IdTNEFattAttachData = $800F; // /* PR_ATTACH_DATA_xxx */
  217. IdTNEFattAttachTitle = $8010; // /* PR_ATTACH_FILENAME */
  218. IdTNEFattAttachMetaFile = $8011; // /* PR_ATTACH_RENDERING */
  219. IdTNEFattAttachCreateDate = $8012; // /* PR_CREATION_TIME */
  220. IdTNEFattAttachModifyDate = $8013; // /* PR_LAST_MODIFICATION_TIME */
  221. IdTNEFattDateModified = $8020; // /* PR_LAST_MODIFICATION_TIME */
  222. IdTNEFattAttachTransportFilename = $9001; // /* PR_ATTACH_TRANSPORT_NAME */
  223. IdTNEFattAttachRenddata = $9002; //
  224. IdTNEFattMAPIProps = $9003; //
  225. IdTNEFattRecipTable = $9004; // /* PR_MESSAGE_RECIPIENTS */
  226. IdTNEFattAttachment = $9005; //
  227. IdTNEFattTnefVersion = $9006; //
  228. IdTNEFattOemCodepage = $9007; //
  229. IdTNEFattOriginalMessageClass = $0006; // /* PR_ORIG_MESSAGE_CLASS */
  230. IdTNEFattOwner = $0000; // /* PR_RCVD_REPRESENTING_xxx or PR_SENT_REPRESENTING_xxx */
  231. IdTNEFattSentFor = $0001; // /* PR_SENT_REPRESENTING_xxx */
  232. IdTNEFattDelegate = $0002; // /* PR_RCVD_REPRESENTING_xxx */
  233. IdTNEFattDateStart = $0006; // /* PR_DATE_START */
  234. IdTNEFattDateEnd = $0007; // /* PR_DATE_END */
  235. IdTNEFattAidOwner = $0008; // /* PR_OWNER_APPT_ID */
  236. IdTNEFattRequestRes = $0009; // /* PR_RESPONSE_REQUESTED */
  237. //Message priorities...
  238. IdTNEFprioLow = 3;
  239. IdTNEFprioNorm = 2;
  240. IdTNEFprioHigh = 1;
  241. //MAPI property value types...
  242. IdTNEF_PT_UNSPECIFIED = 0; //TODO: * (Reserved for interface use) type doesn't matter to caller */
  243. IdTNEF_PT_NULL = 1; //TODO: * NULL property value */
  244. IdTNEF_PT_I2 = 2; //* Signed 16-bit value */
  245. IdTNEF_PT_LONG = 3; //* Signed 32-bit value */
  246. IdTNEF_PT_R4 = 4; //* 4-byte floating point */
  247. IdTNEF_PT_DOUBLE = 5; //TODO: * Floating point double */
  248. IdTNEF_PT_CURRENCY = 6; //TODO: * Signed 64-bit int (decimal w/ 4 digits right of decimal pt) */
  249. IdTNEF_PT_APPTIME = 7; //TODO: * Application time */
  250. IdTNEF_PT_ERROR = 10; //TODO: * 32-bit error value */
  251. IdTNEF_PT_BOOLEAN = 11; //* 16-bit boolean (non-zero true) */
  252. IdTNEF_PT_OBJECT = 13; //* Embedded object in a property */
  253. IdTNEF_PT_I8 = 20; //TODO: * 8-byte signed integer */
  254. IdTNEF_PT_STRING8 = 30; //* Null terminated 8-bit character string */
  255. IdTNEF_PT_UNICODE = 31; //* Null terminated Unicode string */
  256. IdTNEF_PT_SYSTIME = 64; //TODO: * FILETIME 64-bit int w/ number of 100ns periods since Jan 1,1601 */
  257. IdTNEF_PT_CLSID = 72; //TODO:* OLE GUID */
  258. IdTNEF_PT_BINARY = 258; //* Uninterpreted (counted byte array) */
  259. IdTNEF_MV_FLAG = $1000; //TODO: * Multi-value flag */
  260. //MAPI property tags...
  261. IdTNEF_PR_ALTERNATE_RECIPIENT_ALLOWED = $0002; //PROP_TAG( PT_BOOLEAN, 0x0002)
  262. IdTNEF_PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED = $0023; //PROP_TAG( PT_BOOLEAN, 0x0023)
  263. IdTNEF_PR_PRIORITY = $0026; //PROP_TAG( PT_LONG, 0x0026)
  264. IdTNEF_PR_READ_RECEIPT_REQUESTED = $0029; //PROP_TAG( PT_BOOLEAN, 0x0029)
  265. IdTNEF_PR_ORIGINAL_SENSITIVITY = $002E; //PROP_TAG( PT_LONG, 0x002E)
  266. IdTNEF_PR_SENSITIVITY = $0036; //PROP_TAG( PT_LONG, 0x0036)
  267. IdTNEF_PR_CLIENT_SUBMIT_TIME = $0039; //PROP_TAG( PT_SYSTIME, 0x0039)
  268. IdTNEF_PR_SUBJECT_PREFIX = $003D; //PROP_TAG( PT_TSTRING, 0x003D)
  269. IdTNEF_PR_MESSAGE_SUBMISSION_ID = $0047; //PROP_TAG( PT_BINARY, 0x0047)
  270. IdTNEF_PR_ORIGINAL_SUBJECT = $0049; //PROP_TAG( PT_TSTRING, 0x0049)
  271. IdTNEF_PR_ORIGINAL_AUTHOR_NAME = $004D; //PROP_TAG( PT_TSTRING, 0x004D)
  272. IdTNEF_PR_ORIGINAL_SUBMIT_TIME = $004E; //PROP_TAG( PT_SYSTIME, 0x004E)
  273. IdTNEF_PR_ORIGINAL_SENDER_NAME = $005A; //PROP_TAG( PT_TSTRING, 0x005A)
  274. IdTNEF_PR_ORIGINAL_SENDER_ENTRYID = $005B; //PROP_TAG( PT_BINARY, 0x005B)
  275. IdTNEF_PR_ORIGINAL_SENDER_SEARCH_KEY = $005C; //PROP_TAG( PT_BINARY, 0x005C)
  276. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_NAME = $005D; //PROP_TAG( PT_TSTRING, 0x005D)
  277. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_ENTRYID = $005E; //PROP_TAG( PT_BINARY, 0x005E)
  278. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY = $005F; //PROP_TAG( PT_BINARY, 0x005F)
  279. IdTNEF_PR_ORIGINAL_SENDER_ADDRTYPE = $0066; //PROP_TAG( PT_TSTRING, 0x0066)
  280. IdTNEF_PR_ORIGINAL_SENDER_EMAIL_ADDRESS = $0067; //PROP_TAG( PT_TSTRING, 0x0067)
  281. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE = $0068; //PROP_TAG( PT_TSTRING, 0x0068)
  282. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS= $0069; //PROP_TAG( PT_TSTRING, 0x0069)
  283. IdTNEF_PR_CONVERSATION_TOPIC = $0070; //PROP_TAG( PT_TSTRING, 0x0070)
  284. IdTNEF_PR_CONVERSATION_INDEX = $0071; //PROP_TAG( PT_BINARY, 0x0071)
  285. IdTNEF_PR_ORIGINAL_DISPLAY_CC = $0073; //PROP_TAG( PT_TSTRING, 0x0073)
  286. IdTNEF_PR_ORIGINAL_DISPLAY_TO = $0074; //PROP_TAG( PT_TSTRING, 0x0074)
  287. IdTNEF_PR_REPLY_REQUESTED = $0C17; //PROP_TAG( PT_BOOLEAN, 0x0C17)
  288. IdTNEF_PR_SENDER_SEARCH_KEY = $0C1D; //PROP_TAG( PT_BINARY, 0x0C1D)
  289. IdTNEF_PR_SENDER_NAME = $0C1A; //PROP_TAG( PT_TSTRING, 0x0C1A)
  290. IdTNEF_PR_DELETE_AFTER_SUBMIT = $0E01; //PROP_TAG( PT_BOOLEAN, 0x0E01)
  291. IdTNEF_PR_MESSAGE_DELIVERY_TIME = $0E06; //PROP_TAG( PT_SYSTIME, 0x0E06)
  292. IdTNEF_PR_SENTMAIL_ENTRYID = $0E0A; //PROP_TAG( PT_BINARY, 0x0E0A)
  293. IdTNEF_PR_NORMALIZED_SUBJECT = $0E1D; //PROP_TAG( PT_TSTRING, 0x0E1D)
  294. IdTNEF_PR_RTF_IN_SYNC = $0E1F; //PROP_TAG( PT_BOOLEAN, 0x0E1F)
  295. IdTNEF_PR_MAPPING_SIGNATURE = $0FF8; //PROP_TAG( PT_BINARY, 0x0FF8)
  296. IdTNEF_PR_STORE_RECORD_KEY = $0FFA; //PROP_TAG( PT_BINARY, 0x0FFA)
  297. IdTNEF_PR_STORE_ENTRYID = $0FFB; //PROP_TAG( PT_BINARY, 0x0FFB)
  298. IdTNEF_PR_OBJECT_TYPE = $0FFE; //PROP_TAG( PT_LONG, 0x0FFE)
  299. IdTNEF_PR_STORE_SUPPORT_MASK = $340D; //PROP_TAG( PT_LONG, 0x340D)
  300. IdTNEF_PR_TNEF_CORRELATION_KEY = $007F; //PROP_TAG(PT_BINARY, 0x007F)
  301. IdTNEF_PR_BODY = $1000; //PROP_TAG( PT_TSTRING, 0x1000)
  302. IdTNEF_PR_RTF_SYNC_BODY_CRC = $1006; //PROP_TAG( PT_LONG, 0x1006)
  303. IdTNEF_PR_RTF_SYNC_BODY_COUNT = $1007; //PROP_TAG( PT_LONG, 0x1007)
  304. IdTNEF_PR_RTF_SYNC_BODY_TAG = $1008; //PROP_TAG( PT_TSTRING, 0x1008)
  305. IdTNEF_PR_RTF_COMPRESSED = $1009; //PROP_TAG( PT_BINARY, 0x1009)
  306. IdTNEF_PR_RTF_SYNC_PREFIX_COUNT = $1010; //PROP_TAG( PT_LONG, 0x1010)
  307. IdTNEF_PR_RTF_SYNC_TRAILING_COUNT = $1011; //PROP_TAG( PT_LONG, 0x1011)
  308. IdTNEF_PR_ORIGINALLY_INTENDED_RECIP_ENTRYID = $1012; //PROP_TAG( PT_BINARY, 0x1012)
  309. {
  310. #define PR_ACKNOWLEDGEMENT_MODE PROP_TAG( PT_LONG, 0x0001)
  311. //#define PR_ALTERNATE_RECIPIENT_ALLOWED PROP_TAG( PT_BOOLEAN, 0x0002)
  312. #define PR_AUTHORIZING_USERS PROP_TAG( PT_BINARY, 0x0003)
  313. #define PR_AUTO_FORWARD_COMMENT PROP_TAG( PT_TSTRING, 0x0004)
  314. #define PR_AUTO_FORWARD_COMMENT_W PROP_TAG( PT_UNICODE, 0x0004)
  315. #define PR_AUTO_FORWARD_COMMENT_A PROP_TAG( PT_STRING8, 0x0004)
  316. #define PR_AUTO_FORWARDED PROP_TAG( PT_BOOLEAN, 0x0005)
  317. #define PR_CONTENT_CONFIDENTIALITY_ALGORITHM_ID PROP_TAG( PT_BINARY, 0x0006)
  318. #define PR_CONTENT_CORRELATOR PROP_TAG( PT_BINARY, 0x0007)
  319. #define PR_CONTENT_IDENTIFIER PROP_TAG( PT_TSTRING, 0x0008)
  320. #define PR_CONTENT_IDENTIFIER_W PROP_TAG( PT_UNICODE, 0x0008)
  321. #define PR_CONTENT_IDENTIFIER_A PROP_TAG( PT_STRING8, 0x0008)
  322. #define PR_CONTENT_LENGTH PROP_TAG( PT_LONG, 0x0009)
  323. #define PR_CONTENT_RETURN_REQUESTED PROP_TAG( PT_BOOLEAN, 0x000A)
  324. #define PR_CONVERSATION_KEY PROP_TAG( PT_BINARY, 0x000B)
  325. #define PR_CONVERSION_EITS PROP_TAG( PT_BINARY, 0x000C)
  326. #define PR_CONVERSION_WITH_LOSS_PROHIBITED PROP_TAG( PT_BOOLEAN, 0x000D)
  327. #define PR_CONVERTED_EITS PROP_TAG( PT_BINARY, 0x000E)
  328. #define PR_DEFERRED_DELIVERY_TIME PROP_TAG( PT_SYSTIME, 0x000F)
  329. #define PR_DELIVER_TIME PROP_TAG( PT_SYSTIME, 0x0010)
  330. #define PR_DISCARD_REASON PROP_TAG( PT_LONG, 0x0011)
  331. #define PR_DISCLOSURE_OF_RECIPIENTS PROP_TAG( PT_BOOLEAN, 0x0012)
  332. #define PR_DL_EXPANSION_HISTORY PROP_TAG( PT_BINARY, 0x0013)
  333. #define PR_DL_EXPANSION_PROHIBITED PROP_TAG( PT_BOOLEAN, 0x0014)
  334. #define PR_EXPIRY_TIME PROP_TAG( PT_SYSTIME, 0x0015)
  335. #define PR_IMPLICIT_CONVERSION_PROHIBITED PROP_TAG( PT_BOOLEAN, 0x0016)
  336. #define PR_IMPORTANCE PROP_TAG( PT_LONG, 0x0017)
  337. #define PR_IPM_ID PROP_TAG( PT_BINARY, 0x0018)
  338. #define PR_LATEST_DELIVERY_TIME PROP_TAG( PT_SYSTIME, 0x0019)
  339. #define PR_MESSAGE_CLASS PROP_TAG( PT_TSTRING, 0x001A)
  340. #define PR_MESSAGE_CLASS_W PROP_TAG( PT_UNICODE, 0x001A)
  341. #define PR_MESSAGE_CLASS_A PROP_TAG( PT_STRING8, 0x001A)
  342. #define PR_MESSAGE_DELIVERY_ID PROP_TAG( PT_BINARY, 0x001B)
  343. #define PR_MESSAGE_SECURITY_LABEL PROP_TAG( PT_BINARY, 0x001E)
  344. #define PR_OBSOLETED_IPMS PROP_TAG( PT_BINARY, 0x001F)
  345. #define PR_ORIGINALLY_INTENDED_RECIPIENT_NAME PROP_TAG( PT_BINARY, 0x0020)
  346. #define PR_ORIGINAL_EITS PROP_TAG( PT_BINARY, 0x0021)
  347. #define PR_ORIGINATOR_CERTIFICATE PROP_TAG( PT_BINARY, 0x0022)
  348. //#define PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0023)
  349. #define PR_ORIGINATOR_RETURN_ADDRESS PROP_TAG( PT_BINARY, 0x0024)
  350. #define PR_PARENT_KEY PROP_TAG( PT_BINARY, 0x0025)
  351. //#define PR_PRIORITY PROP_TAG( PT_LONG, 0x0026)
  352. #define PR_ORIGIN_CHECK PROP_TAG( PT_BINARY, 0x0027)
  353. #define PR_PROOF_OF_SUBMISSION_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0028)
  354. #define PR_READ_RECEIPT_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0029)
  355. #define PR_RECEIPT_TIME PROP_TAG( PT_SYSTIME, 0x002A)
  356. #define PR_RECIPIENT_REASSIGNMENT_PROHIBITED PROP_TAG( PT_BOOLEAN, 0x002B)
  357. #define PR_REDIRECTION_HISTORY PROP_TAG( PT_BINARY, 0x002C)
  358. #define PR_RELATED_IPMS PROP_TAG( PT_BINARY, 0x002D)
  359. //#define PR_ORIGINAL_SENSITIVITY PROP_TAG( PT_LONG, 0x002E)
  360. #define PR_LANGUAGES PROP_TAG( PT_TSTRING, 0x002F)
  361. #define PR_LANGUAGES_W PROP_TAG( PT_UNICODE, 0x002F)
  362. #define PR_LANGUAGES_A PROP_TAG( PT_STRING8, 0x002F)
  363. #define PR_REPLY_TIME PROP_TAG( PT_SYSTIME, 0x0030)
  364. #define PR_REPORT_TAG PROP_TAG( PT_BINARY, 0x0031)
  365. #define PR_REPORT_TIME PROP_TAG( PT_SYSTIME, 0x0032)
  366. #define PR_RETURNED_IPM PROP_TAG( PT_BOOLEAN, 0x0033)
  367. #define PR_SECURITY PROP_TAG( PT_LONG, 0x0034)
  368. #define PR_INCOMPLETE_COPY PROP_TAG( PT_BOOLEAN, 0x0035)
  369. #define PR_SENSITIVITY PROP_TAG( PT_LONG, 0x0036)
  370. #define PR_SUBJECT PROP_TAG( PT_TSTRING, 0x0037)
  371. #define PR_SUBJECT_W PROP_TAG( PT_UNICODE, 0x0037)
  372. #define PR_SUBJECT_A PROP_TAG( PT_STRING8, 0x0037)
  373. #define PR_SUBJECT_IPM PROP_TAG( PT_BINARY, 0x0038)
  374. //#define PR_CLIENT_SUBMIT_TIME PROP_TAG( PT_SYSTIME, 0x0039)
  375. #define PR_REPORT_NAME PROP_TAG( PT_TSTRING, 0x003A)
  376. #define PR_REPORT_NAME_W PROP_TAG( PT_UNICODE, 0x003A)
  377. #define PR_REPORT_NAME_A PROP_TAG( PT_STRING8, 0x003A)
  378. #define PR_SENT_REPRESENTING_SEARCH_KEY PROP_TAG( PT_BINARY, 0x003B)
  379. #define PR_X400_CONTENT_TYPE PROP_TAG( PT_BINARY, 0x003C)
  380. //#define PR_SUBJECT_PREFIX PROP_TAG( PT_TSTRING, 0x003D)
  381. //#define PR_SUBJECT_PREFIX_W PROP_TAG( PT_UNICODE, 0x003D)
  382. //#define PR_SUBJECT_PREFIX_A PROP_TAG( PT_STRING8, 0x003D)
  383. #define PR_NON_RECEIPT_REASON PROP_TAG( PT_LONG, 0x003E)
  384. #define PR_RECEIVED_BY_ENTRYID PROP_TAG( PT_BINARY, 0x003F)
  385. #define PR_RECEIVED_BY_NAME PROP_TAG( PT_TSTRING, 0x0040)
  386. #define PR_RECEIVED_BY_NAME_W PROP_TAG( PT_UNICODE, 0x0040)
  387. #define PR_RECEIVED_BY_NAME_A PROP_TAG( PT_STRING8, 0x0040)
  388. #define PR_SENT_REPRESENTING_ENTRYID PROP_TAG( PT_BINARY, 0x0041)
  389. #define PR_SENT_REPRESENTING_NAME PROP_TAG( PT_TSTRING, 0x0042)
  390. #define PR_SENT_REPRESENTING_NAME_W PROP_TAG( PT_UNICODE, 0x0042)
  391. #define PR_SENT_REPRESENTING_NAME_A PROP_TAG( PT_STRING8, 0x0042)
  392. #define PR_RCVD_REPRESENTING_ENTRYID PROP_TAG( PT_BINARY, 0x0043)
  393. #define PR_RCVD_REPRESENTING_NAME PROP_TAG( PT_TSTRING, 0x0044)
  394. #define PR_RCVD_REPRESENTING_NAME_W PROP_TAG( PT_UNICODE, 0x0044)
  395. #define PR_RCVD_REPRESENTING_NAME_A PROP_TAG( PT_STRING8, 0x0044)
  396. #define PR_REPORT_ENTRYID PROP_TAG( PT_BINARY, 0x0045)
  397. #define PR_READ_RECEIPT_ENTRYID PROP_TAG( PT_BINARY, 0x0046)
  398. #define PR_MESSAGE_SUBMISSION_ID PROP_TAG( PT_BINARY, 0x0047)
  399. #define PR_PROVIDER_SUBMIT_TIME PROP_TAG( PT_SYSTIME, 0x0048)
  400. //#define PR_ORIGINAL_SUBJECT PROP_TAG( PT_TSTRING, 0x0049)
  401. #define PR_ORIGINAL_SUBJECT_W PROP_TAG( PT_UNICODE, 0x0049)
  402. #define PR_ORIGINAL_SUBJECT_A PROP_TAG( PT_STRING8, 0x0049)
  403. #define PR_DISC_VAL PROP_TAG( PT_BOOLEAN, 0x004A)
  404. #define PR_ORIG_MESSAGE_CLASS PROP_TAG( PT_TSTRING, 0x004B)
  405. #define PR_ORIG_MESSAGE_CLASS_W PROP_TAG( PT_UNICODE, 0x004B)
  406. #define PR_ORIG_MESSAGE_CLASS_A PROP_TAG( PT_STRING8, 0x004B)
  407. #define PR_ORIGINAL_AUTHOR_ENTRYID PROP_TAG( PT_BINARY, 0x004C)
  408. #define PR_ORIGINAL_AUTHOR_NAME PROP_TAG( PT_TSTRING, 0x004D)
  409. #define PR_ORIGINAL_AUTHOR_NAME_W PROP_TAG( PT_UNICODE, 0x004D)
  410. #define PR_ORIGINAL_AUTHOR_NAME_A PROP_TAG( PT_STRING8, 0x004D)
  411. //#define PR_ORIGINAL_SUBMIT_TIME PROP_TAG( PT_SYSTIME, 0x004E)
  412. #define PR_REPLY_RECIPIENT_ENTRIES PROP_TAG( PT_BINARY, 0x004F)
  413. #define PR_REPLY_RECIPIENT_NAMES PROP_TAG( PT_TSTRING, 0x0050)
  414. #define PR_REPLY_RECIPIENT_NAMES_W PROP_TAG( PT_UNICODE, 0x0050)
  415. #define PR_REPLY_RECIPIENT_NAMES_A PROP_TAG( PT_STRING8, 0x0050)
  416. #define PR_RECEIVED_BY_SEARCH_KEY PROP_TAG( PT_BINARY, 0x0051)
  417. #define PR_RCVD_REPRESENTING_SEARCH_KEY PROP_TAG( PT_BINARY, 0x0052)
  418. #define PR_READ_RECEIPT_SEARCH_KEY PROP_TAG( PT_BINARY, 0x0053)
  419. #define PR_REPORT_SEARCH_KEY PROP_TAG( PT_BINARY, 0x0054)
  420. #define PR_ORIGINAL_DELIVERY_TIME PROP_TAG( PT_SYSTIME, 0x0055)
  421. #define PR_ORIGINAL_AUTHOR_SEARCH_KEY PROP_TAG( PT_BINARY, 0x0056)
  422. #define PR_MESSAGE_TO_ME PROP_TAG( PT_BOOLEAN, 0x0057)
  423. #define PR_MESSAGE_CC_ME PROP_TAG( PT_BOOLEAN, 0x0058)
  424. #define PR_MESSAGE_RECIP_ME PROP_TAG( PT_BOOLEAN, 0x0059)
  425. //#define PR_ORIGINAL_SENDER_NAME PROP_TAG( PT_TSTRING, 0x005A)
  426. //#define PR_ORIGINAL_SENDER_NAME_W PROP_TAG( PT_UNICODE, 0x005A)
  427. //#define PR_ORIGINAL_SENDER_NAME_A PROP_TAG( PT_STRING8, 0x005A)
  428. //#define PR_ORIGINAL_SENDER_ENTRYID PROP_TAG( PT_BINARY, 0x005B)
  429. //#define PR_ORIGINAL_SENDER_SEARCH_KEY PROP_TAG( PT_BINARY, 0x005C)
  430. //#define PR_ORIGINAL_SENT_REPRESENTING_NAME PROP_TAG( PT_TSTRING, 0x005D)
  431. //#define PR_ORIGINAL_SENT_REPRESENTING_NAME_W PROP_TAG( PT_UNICODE, 0x005D)
  432. //#define PR_ORIGINAL_SENT_REPRESENTING_NAME_A PROP_TAG( PT_STRING8, 0x005D)
  433. //#define PR_ORIGINAL_SENT_REPRESENTING_ENTRYID PROP_TAG( PT_BINARY, 0x005E)
  434. //#define PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY PROP_TAG( PT_BINARY, 0x005F)
  435. #define PR_START_DATE PROP_TAG( PT_SYSTIME, 0x0060)
  436. #define PR_END_DATE PROP_TAG( PT_SYSTIME, 0x0061)
  437. #define PR_OWNER_APPT_ID PROP_TAG( PT_LONG, 0x0062)
  438. #define PR_RESPONSE_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0063)
  439. #define PR_SENT_REPRESENTING_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0064)
  440. #define PR_SENT_REPRESENTING_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0064)
  441. #define PR_SENT_REPRESENTING_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0064)
  442. #define PR_SENT_REPRESENTING_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x0065)
  443. #define PR_SENT_REPRESENTING_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x0065)
  444. #define PR_SENT_REPRESENTING_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x0065)
  445. //#define PR_ORIGINAL_SENDER_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0066)
  446. //#define PR_ORIGINAL_SENDER_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0066)
  447. //#define PR_ORIGINAL_SENDER_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0066)
  448. //#define PR_ORIGINAL_SENDER_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x0067)
  449. //#define PR_ORIGINAL_SENDER_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x0067)
  450. //#define PR_ORIGINAL_SENDER_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x0067)
  451. //#define PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0068)
  452. //#define PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0068)
  453. //#define PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0068)
  454. //#define PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x0069)
  455. //#define PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x0069)
  456. //#define PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x0069)
  457. //#define PR_CONVERSATION_TOPIC PROP_TAG( PT_TSTRING, 0x0070)
  458. #define PR_CONVERSATION_TOPIC_W PROP_TAG( PT_UNICODE, 0x0070)
  459. #define PR_CONVERSATION_TOPIC_A PROP_TAG( PT_STRING8, 0x0070)
  460. //#define PR_CONVERSATION_INDEX PROP_TAG( PT_BINARY, 0x0071)
  461. #define PR_ORIGINAL_DISPLAY_BCC PROP_TAG( PT_TSTRING, 0x0072)
  462. #define PR_ORIGINAL_DISPLAY_BCC_W PROP_TAG( PT_UNICODE, 0x0072)
  463. #define PR_ORIGINAL_DISPLAY_BCC_A PROP_TAG( PT_STRING8, 0x0072)
  464. //#define PR_ORIGINAL_DISPLAY_CC PROP_TAG( PT_TSTRING, 0x0073)
  465. //#define PR_ORIGINAL_DISPLAY_CC_W PROP_TAG( PT_UNICODE, 0x0073)
  466. //#define PR_ORIGINAL_DISPLAY_CC_A PROP_TAG( PT_STRING8, 0x0073)
  467. //#define PR_ORIGINAL_DISPLAY_TO PROP_TAG( PT_TSTRING, 0x0074)
  468. //#define PR_ORIGINAL_DISPLAY_TO_W PROP_TAG( PT_UNICODE, 0x0074)
  469. //#define PR_ORIGINAL_DISPLAY_TO_A PROP_TAG( PT_STRING8, 0x0074)
  470. #define PR_RECEIVED_BY_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0075)
  471. #define PR_RECEIVED_BY_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0075)
  472. #define PR_RECEIVED_BY_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0075)
  473. #define PR_RECEIVED_BY_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x0076)
  474. #define PR_RECEIVED_BY_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x0076)
  475. #define PR_RECEIVED_BY_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x0076)
  476. #define PR_RCVD_REPRESENTING_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0077)
  477. #define PR_RCVD_REPRESENTING_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0077)
  478. #define PR_RCVD_REPRESENTING_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0077)
  479. #define PR_RCVD_REPRESENTING_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x0078)
  480. #define PR_RCVD_REPRESENTING_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x0078)
  481. #define PR_RCVD_REPRESENTING_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x0078)
  482. #define PR_ORIGINAL_AUTHOR_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0079)
  483. #define PR_ORIGINAL_AUTHOR_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0079)
  484. #define PR_ORIGINAL_AUTHOR_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0079)
  485. #define PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x007A)
  486. #define PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x007A)
  487. #define PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x007A)
  488. #define PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE PROP_TAG( PT_TSTRING, 0x007B)
  489. #define PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x007B)
  490. #define PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x007B)
  491. #define PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x007C)
  492. #define PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x007C)
  493. #define PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x007C)
  494. #define PR_TRANSPORT_MESSAGE_HEADERS PROP_TAG(PT_TSTRING, 0x007D)
  495. #define PR_TRANSPORT_MESSAGE_HEADERS_W PROP_TAG(PT_UNICODE, 0x007D)
  496. #define PR_TRANSPORT_MESSAGE_HEADERS_A PROP_TAG(PT_STRING8, 0x007D)
  497. #define PR_DELEGATION PROP_TAG(PT_BINARY, 0x007E)
  498. #define PR_TNEF_CORRELATION_KEY PROP_TAG(PT_BINARY, 0x007F)
  499. /*
  500. * Message content properties
  501. */
  502. //#define PR_BODY PROP_TAG( PT_TSTRING, 0x1000)
  503. //#define PR_BODY_W PROP_TAG( PT_UNICODE, 0x1000)
  504. //#define PR_BODY_A PROP_TAG( PT_STRING8, 0x1000)
  505. #define PR_REPORT_TEXT PROP_TAG( PT_TSTRING, 0x1001)
  506. #define PR_REPORT_TEXT_W PROP_TAG( PT_UNICODE, 0x1001)
  507. #define PR_REPORT_TEXT_A PROP_TAG( PT_STRING8, 0x1001)
  508. #define PR_ORIGINATOR_AND_DL_EXPANSION_HISTORY PROP_TAG( PT_BINARY, 0x1002)
  509. #define PR_REPORTING_DL_NAME PROP_TAG( PT_BINARY, 0x1003)
  510. #define PR_REPORTING_MTA_CERTIFICATE PROP_TAG( PT_BINARY, 0x1004)
  511. /* Removed PR_REPORT_ORIGIN_AUTHENTICATION_CHECK with DCR 3865, use PR_ORIGIN_CHECK */
  512. #define PR_RTF_SYNC_BODY_CRC PROP_TAG( PT_LONG, 0x1006)
  513. #define PR_RTF_SYNC_BODY_COUNT PROP_TAG( PT_LONG, 0x1007)
  514. #define PR_RTF_SYNC_BODY_TAG PROP_TAG( PT_TSTRING, 0x1008)
  515. #define PR_RTF_SYNC_BODY_TAG_W PROP_TAG( PT_UNICODE, 0x1008)
  516. #define PR_RTF_SYNC_BODY_TAG_A PROP_TAG( PT_STRING8, 0x1008)
  517. #define PR_RTF_COMPRESSED PROP_TAG( PT_BINARY, 0x1009)
  518. #define PR_RTF_SYNC_PREFIX_COUNT PROP_TAG( PT_LONG, 0x1010)
  519. #define PR_RTF_SYNC_TRAILING_COUNT PROP_TAG( PT_LONG, 0x1011)
  520. #define PR_ORIGINALLY_INTENDED_RECIP_ENTRYID PROP_TAG( PT_BINARY, 0x1012)
  521. /*
  522. * Reserved 0x1100-0x1200
  523. */
  524. /*
  525. * Message recipient properties
  526. */
  527. #define PR_CONTENT_INTEGRITY_CHECK PROP_TAG( PT_BINARY, 0x0C00)
  528. #define PR_EXPLICIT_CONVERSION PROP_TAG( PT_LONG, 0x0C01)
  529. #define PR_IPM_RETURN_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0C02)
  530. #define PR_MESSAGE_TOKEN PROP_TAG( PT_BINARY, 0x0C03)
  531. #define PR_NDR_REASON_CODE PROP_TAG( PT_LONG, 0x0C04)
  532. #define PR_NDR_DIAG_CODE PROP_TAG( PT_LONG, 0x0C05)
  533. #define PR_NON_RECEIPT_NOTIFICATION_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0C06)
  534. #define PR_DELIVERY_POINT PROP_TAG( PT_LONG, 0x0C07)
  535. #define PR_ORIGINATOR_NON_DELIVERY_REPORT_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0C08)
  536. #define PR_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT PROP_TAG( PT_BINARY, 0x0C09)
  537. #define PR_PHYSICAL_DELIVERY_BUREAU_FAX_DELIVERY PROP_TAG( PT_BOOLEAN, 0x0C0A)
  538. #define PR_PHYSICAL_DELIVERY_MODE PROP_TAG( PT_LONG, 0x0C0B)
  539. #define PR_PHYSICAL_DELIVERY_REPORT_REQUEST PROP_TAG( PT_LONG, 0x0C0C)
  540. #define PR_PHYSICAL_FORWARDING_ADDRESS PROP_TAG( PT_BINARY, 0x0C0D)
  541. #define PR_PHYSICAL_FORWARDING_ADDRESS_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0C0E)
  542. #define PR_PHYSICAL_FORWARDING_PROHIBITED PROP_TAG( PT_BOOLEAN, 0x0C0F)
  543. #define PR_PHYSICAL_RENDITION_ATTRIBUTES PROP_TAG( PT_BINARY, 0x0C10)
  544. #define PR_PROOF_OF_DELIVERY PROP_TAG( PT_BINARY, 0x0C11)
  545. #define PR_PROOF_OF_DELIVERY_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0C12)
  546. #define PR_RECIPIENT_CERTIFICATE PROP_TAG( PT_BINARY, 0x0C13)
  547. #define PR_RECIPIENT_NUMBER_FOR_ADVICE PROP_TAG( PT_TSTRING, 0x0C14)
  548. #define PR_RECIPIENT_NUMBER_FOR_ADVICE_W PROP_TAG( PT_UNICODE, 0x0C14)
  549. #define PR_RECIPIENT_NUMBER_FOR_ADVICE_A PROP_TAG( PT_STRING8, 0x0C14)
  550. #define PR_RECIPIENT_TYPE PROP_TAG( PT_LONG, 0x0C15)
  551. #define PR_REGISTERED_MAIL_TYPE PROP_TAG( PT_LONG, 0x0C16)
  552. //#define PR_REPLY_REQUESTED PROP_TAG( PT_BOOLEAN, 0x0C17)
  553. #define PR_REQUESTED_DELIVERY_METHOD PROP_TAG( PT_LONG, 0x0C18)
  554. #define PR_SENDER_ENTRYID PROP_TAG( PT_BINARY, 0x0C19)
  555. //#define PR_SENDER_NAME PROP_TAG( PT_TSTRING, 0x0C1A)
  556. //#define PR_SENDER_NAME_W PROP_TAG( PT_UNICODE, 0x0C1A)
  557. //#define PR_SENDER_NAME_A PROP_TAG( PT_STRING8, 0x0C1A)
  558. #define PR_SUPPLEMENTARY_INFO PROP_TAG( PT_TSTRING, 0x0C1B)
  559. #define PR_SUPPLEMENTARY_INFO_W PROP_TAG( PT_UNICODE, 0x0C1B)
  560. #define PR_SUPPLEMENTARY_INFO_A PROP_TAG( PT_STRING8, 0x0C1B)
  561. #define PR_TYPE_OF_MTS_USER PROP_TAG( PT_LONG, 0x0C1C)
  562. //#define PR_SENDER_SEARCH_KEY PROP_TAG( PT_BINARY, 0x0C1D)
  563. #define PR_SENDER_ADDRTYPE PROP_TAG( PT_TSTRING, 0x0C1E)
  564. #define PR_SENDER_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x0C1E)
  565. #define PR_SENDER_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x0C1E)
  566. #define PR_SENDER_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x0C1F)
  567. #define PR_SENDER_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x0C1F)
  568. #define PR_SENDER_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x0C1F)
  569. /*
  570. * Message non-transmittable properties
  571. */
  572. /*
  573. * The two tags, PR_MESSAGE_RECIPIENTS and PR_MESSAGE_ATTACHMENTS,
  574. * are to be used in the exclude list passed to
  575. * IMessage::CopyTo when the caller wants either the recipients or attachments
  576. * of the message to not get copied. It is also used in the ProblemArray
  577. * return from IMessage::CopyTo when an error is encountered copying them
  578. */
  579. #define PR_CURRENT_VERSION PROP_TAG( PT_I8, 0x0E00)
  580. //#define PR_DELETE_AFTER_SUBMIT PROP_TAG( PT_BOOLEAN, 0x0E01)
  581. #define PR_DISPLAY_BCC PROP_TAG( PT_TSTRING, 0x0E02)
  582. #define PR_DISPLAY_BCC_W PROP_TAG( PT_UNICODE, 0x0E02)
  583. #define PR_DISPLAY_BCC_A PROP_TAG( PT_STRING8, 0x0E02)
  584. #define PR_DISPLAY_CC PROP_TAG( PT_TSTRING, 0x0E03)
  585. #define PR_DISPLAY_CC_W PROP_TAG( PT_UNICODE, 0x0E03)
  586. #define PR_DISPLAY_CC_A PROP_TAG( PT_STRING8, 0x0E03)
  587. #define PR_DISPLAY_TO PROP_TAG( PT_TSTRING, 0x0E04)
  588. #define PR_DISPLAY_TO_W PROP_TAG( PT_UNICODE, 0x0E04)
  589. #define PR_DISPLAY_TO_A PROP_TAG( PT_STRING8, 0x0E04)
  590. #define PR_PARENT_DISPLAY PROP_TAG( PT_TSTRING, 0x0E05)
  591. #define PR_PARENT_DISPLAY_W PROP_TAG( PT_UNICODE, 0x0E05)
  592. #define PR_PARENT_DISPLAY_A PROP_TAG( PT_STRING8, 0x0E05)
  593. #define PR_MESSAGE_DELIVERY_TIME PROP_TAG( PT_SYSTIME, 0x0E06)
  594. #define PR_MESSAGE_FLAGS PROP_TAG( PT_LONG, 0x0E07)
  595. #define PR_MESSAGE_SIZE PROP_TAG( PT_LONG, 0x0E08)
  596. #define PR_PARENT_ENTRYID PROP_TAG( PT_BINARY, 0x0E09)
  597. #define PR_SENTMAIL_ENTRYID PROP_TAG( PT_BINARY, 0x0E0A)
  598. #define PR_CORRELATE PROP_TAG( PT_BOOLEAN, 0x0E0C)
  599. #define PR_CORRELATE_MTSID PROP_TAG( PT_BINARY, 0x0E0D)
  600. #define PR_DISCRETE_VALUES PROP_TAG( PT_BOOLEAN, 0x0E0E)
  601. #define PR_RESPONSIBILITY PROP_TAG( PT_BOOLEAN, 0x0E0F)
  602. #define PR_SPOOLER_STATUS PROP_TAG( PT_LONG, 0x0E10)
  603. #define PR_TRANSPORT_STATUS PROP_TAG( PT_LONG, 0x0E11)
  604. #define PR_MESSAGE_RECIPIENTS PROP_TAG( PT_OBJECT, 0x0E12)
  605. #define PR_MESSAGE_ATTACHMENTS PROP_TAG( PT_OBJECT, 0x0E13)
  606. #define PR_SUBMIT_FLAGS PROP_TAG( PT_LONG, 0x0E14)
  607. #define PR_RECIPIENT_STATUS PROP_TAG( PT_LONG, 0x0E15)
  608. #define PR_TRANSPORT_KEY PROP_TAG( PT_LONG, 0x0E16)
  609. #define PR_MSG_STATUS PROP_TAG( PT_LONG, 0x0E17)
  610. #define PR_MESSAGE_DOWNLOAD_TIME PROP_TAG( PT_LONG, 0x0E18)
  611. #define PR_CREATION_VERSION PROP_TAG( PT_I8, 0x0E19)
  612. #define PR_MODIFY_VERSION PROP_TAG( PT_I8, 0x0E1A)
  613. #define PR_HASATTACH PROP_TAG( PT_BOOLEAN, 0x0E1B)
  614. #define PR_BODY_CRC PROP_TAG( PT_LONG, 0x0E1C)
  615. //#define PR_NORMALIZED_SUBJECT PROP_TAG( PT_TSTRING, 0x0E1D)
  616. //#define PR_NORMALIZED_SUBJECT_W PROP_TAG( PT_UNICODE, 0x0E1D)
  617. //#define PR_NORMALIZED_SUBJECT_A PROP_TAG( PT_STRING8, 0x0E1D)
  618. #define PR_RTF_IN_SYNC PROP_TAG( PT_BOOLEAN, 0x0E1F)
  619. #define PR_ATTACH_SIZE PROP_TAG( PT_LONG, 0x0E20)
  620. #define PR_ATTACH_NUM PROP_TAG( PT_LONG, 0x0E21)
  621. #define PR_PREPROCESS PROP_TAG( PT_BOOLEAN, 0x0E22)
  622. /* PR_ORIGINAL_DISPLAY_TO, _CC, and _BCC moved to transmittible range 03/09/95 */
  623. #define PR_ORIGINATING_MTA_CERTIFICATE PROP_TAG( PT_BINARY, 0x0E25)
  624. #define PR_PROOF_OF_SUBMISSION PROP_TAG( PT_BINARY, 0x0E26)
  625. /*
  626. * The range of non-message and non-recipient property IDs (0x3000 - 0x3FFF) is
  627. * further broken down into ranges to make assigning new property IDs easier.
  628. *
  629. * From To Kind of property
  630. * --------------------------------
  631. * 3000 32FF MAPI_defined common property
  632. * 3200 33FF MAPI_defined form property
  633. * 3400 35FF MAPI_defined message store property
  634. * 3600 36FF MAPI_defined Folder or AB Container property
  635. * 3700 38FF MAPI_defined attachment property
  636. * 3900 39FF MAPI_defined address book property
  637. * 3A00 3BFF MAPI_defined mailuser property
  638. * 3C00 3CFF MAPI_defined DistList property
  639. * 3D00 3DFF MAPI_defined Profile Section property
  640. * 3E00 3EFF MAPI_defined Status property
  641. * 3F00 3FFF MAPI_defined display table property
  642. */
  643. /*
  644. * Properties common to numerous MAPI objects.
  645. *
  646. * Those properties that can appear on messages are in the
  647. * non-transmittable range for messages. They start at the high
  648. * end of that range and work down.
  649. *
  650. * Properties that never appear on messages are defined in the common
  651. * property range (see above).
  652. */
  653. /*
  654. * properties that are common to multiple objects (including message objects)
  655. * -- these ids are in the non-transmittable range
  656. */
  657. #define PR_ENTRYID PROP_TAG( PT_BINARY, 0x0FFF)
  658. #define PR_OBJECT_TYPE PROP_TAG( PT_LONG, 0x0FFE)
  659. #define PR_ICON PROP_TAG( PT_BINARY, 0x0FFD)
  660. #define PR_MINI_ICON PROP_TAG( PT_BINARY, 0x0FFC)
  661. #define PR_STORE_ENTRYID PROP_TAG( PT_BINARY, 0x0FFB)
  662. #define PR_STORE_RECORD_KEY PROP_TAG( PT_BINARY, 0x0FFA)
  663. #define PR_RECORD_KEY PROP_TAG( PT_BINARY, 0x0FF9)
  664. #define PR_MAPPING_SIGNATURE PROP_TAG( PT_BINARY, 0x0FF8)
  665. #define PR_ACCESS_LEVEL PROP_TAG( PT_LONG, 0x0FF7)
  666. #define PR_INSTANCE_KEY PROP_TAG( PT_BINARY, 0x0FF6)
  667. #define PR_ROW_TYPE PROP_TAG( PT_LONG, 0x0FF5)
  668. #define PR_ACCESS PROP_TAG( PT_LONG, 0x0FF4)
  669. /*
  670. * properties that are common to multiple objects (usually not including message objects)
  671. * -- these ids are in the transmittable range
  672. */
  673. #define PR_ROWID PROP_TAG( PT_LONG, 0x3000)
  674. #define PR_DISPLAY_NAME PROP_TAG( PT_TSTRING, 0x3001)
  675. #define PR_DISPLAY_NAME_W PROP_TAG( PT_UNICODE, 0x3001)
  676. #define PR_DISPLAY_NAME_A PROP_TAG( PT_STRING8, 0x3001)
  677. #define PR_ADDRTYPE PROP_TAG( PT_TSTRING, 0x3002)
  678. #define PR_ADDRTYPE_W PROP_TAG( PT_UNICODE, 0x3002)
  679. #define PR_ADDRTYPE_A PROP_TAG( PT_STRING8, 0x3002)
  680. #define PR_EMAIL_ADDRESS PROP_TAG( PT_TSTRING, 0x3003)
  681. #define PR_EMAIL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x3003)
  682. #define PR_EMAIL_ADDRESS_A PROP_TAG( PT_STRING8, 0x3003)
  683. #define PR_COMMENT PROP_TAG( PT_TSTRING, 0x3004)
  684. #define PR_COMMENT_W PROP_TAG( PT_UNICODE, 0x3004)
  685. #define PR_COMMENT_A PROP_TAG( PT_STRING8, 0x3004)
  686. #define PR_DEPTH PROP_TAG( PT_LONG, 0x3005)
  687. #define PR_PROVIDER_DISPLAY PROP_TAG( PT_TSTRING, 0x3006)
  688. #define PR_PROVIDER_DISPLAY_W PROP_TAG( PT_UNICODE, 0x3006)
  689. #define PR_PROVIDER_DISPLAY_A PROP_TAG( PT_STRING8, 0x3006)
  690. #define PR_CREATION_TIME PROP_TAG( PT_SYSTIME, 0x3007)
  691. #define PR_LAST_MODIFICATION_TIME PROP_TAG( PT_SYSTIME, 0x3008)
  692. #define PR_RESOURCE_FLAGS PROP_TAG( PT_LONG, 0x3009)
  693. #define PR_PROVIDER_DLL_NAME PROP_TAG( PT_TSTRING, 0x300A)
  694. #define PR_PROVIDER_DLL_NAME_W PROP_TAG( PT_UNICODE, 0x300A)
  695. #define PR_PROVIDER_DLL_NAME_A PROP_TAG( PT_STRING8, 0x300A)
  696. #define PR_SEARCH_KEY PROP_TAG( PT_BINARY, 0x300B)
  697. #define PR_PROVIDER_UID PROP_TAG( PT_BINARY, 0x300C)
  698. #define PR_PROVIDER_ORDINAL PROP_TAG( PT_LONG, 0x300D)
  699. /*
  700. * MAPI Form properties
  701. */
  702. #define PR_FORM_VERSION PROP_TAG(PT_TSTRING, 0x3301)
  703. #define PR_FORM_VERSION_W PROP_TAG(PT_UNICODE, 0x3301)
  704. #define PR_FORM_VERSION_A PROP_TAG(PT_STRING8, 0x3301)
  705. #define PR_FORM_CLSID PROP_TAG(PT_CLSID, 0x3302)
  706. #define PR_FORM_CONTACT_NAME PROP_TAG(PT_TSTRING, 0x3303)
  707. #define PR_FORM_CONTACT_NAME_W PROP_TAG(PT_UNICODE, 0x3303)
  708. #define PR_FORM_CONTACT_NAME_A PROP_TAG(PT_STRING8, 0x3303)
  709. #define PR_FORM_CATEGORY PROP_TAG(PT_TSTRING, 0x3304)
  710. #define PR_FORM_CATEGORY_W PROP_TAG(PT_UNICODE, 0x3304)
  711. #define PR_FORM_CATEGORY_A PROP_TAG(PT_STRING8, 0x3304)
  712. #define PR_FORM_CATEGORY_SUB PROP_TAG(PT_TSTRING, 0x3305)
  713. #define PR_FORM_CATEGORY_SUB_W PROP_TAG(PT_UNICODE, 0x3305)
  714. #define PR_FORM_CATEGORY_SUB_A PROP_TAG(PT_STRING8, 0x3305)
  715. #define PR_FORM_HOST_MAP PROP_TAG(PT_MV_LONG, 0x3306)
  716. #define PR_FORM_HIDDEN PROP_TAG(PT_BOOLEAN, 0x3307)
  717. #define PR_FORM_DESIGNER_NAME PROP_TAG(PT_TSTRING, 0x3308)
  718. #define PR_FORM_DESIGNER_NAME_W PROP_TAG(PT_UNICODE, 0x3308)
  719. #define PR_FORM_DESIGNER_NAME_A PROP_TAG(PT_STRING8, 0x3308)
  720. #define PR_FORM_DESIGNER_GUID PROP_TAG(PT_CLSID, 0x3309)
  721. #define PR_FORM_MESSAGE_BEHAVIOR PROP_TAG(PT_LONG, 0x330A)
  722. /*
  723. * Message store properties
  724. */
  725. #define PR_DEFAULT_STORE PROP_TAG( PT_BOOLEAN, 0x3400)
  726. #define PR_STORE_SUPPORT_MASK PROP_TAG( PT_LONG, 0x340D)
  727. #define PR_STORE_STATE PROP_TAG( PT_LONG, 0x340E)
  728. #define PR_IPM_SUBTREE_SEARCH_KEY PROP_TAG( PT_BINARY, 0x3410)
  729. #define PR_IPM_OUTBOX_SEARCH_KEY PROP_TAG( PT_BINARY, 0x3411)
  730. #define PR_IPM_WASTEBASKET_SEARCH_KEY PROP_TAG( PT_BINARY, 0x3412)
  731. #define PR_IPM_SENTMAIL_SEARCH_KEY PROP_TAG( PT_BINARY, 0x3413)
  732. #define PR_MDB_PROVIDER PROP_TAG( PT_BINARY, 0x3414)
  733. #define PR_RECEIVE_FOLDER_SETTINGS PROP_TAG( PT_OBJECT, 0x3415)
  734. #define PR_VALID_FOLDER_MASK PROP_TAG( PT_LONG, 0x35DF)
  735. #define PR_IPM_SUBTREE_ENTRYID PROP_TAG( PT_BINARY, 0x35E0)
  736. #define PR_IPM_OUTBOX_ENTRYID PROP_TAG( PT_BINARY, 0x35E2)
  737. #define PR_IPM_WASTEBASKET_ENTRYID PROP_TAG( PT_BINARY, 0x35E3)
  738. #define PR_IPM_SENTMAIL_ENTRYID PROP_TAG( PT_BINARY, 0x35E4)
  739. #define PR_VIEWS_ENTRYID PROP_TAG( PT_BINARY, 0x35E5)
  740. #define PR_COMMON_VIEWS_ENTRYID PROP_TAG( PT_BINARY, 0x35E6)
  741. #define PR_FINDER_ENTRYID PROP_TAG( PT_BINARY, 0x35E7)
  742. /* Proptags 0x35E8-0x35FF reserved for folders "guaranteed" by PR_VALID_FOLDER_MASK */
  743. /*
  744. * Folder and AB Container properties
  745. */
  746. #define PR_CONTAINER_FLAGS PROP_TAG( PT_LONG, 0x3600)
  747. #define PR_FOLDER_TYPE PROP_TAG( PT_LONG, 0x3601)
  748. #define PR_CONTENT_COUNT PROP_TAG( PT_LONG, 0x3602)
  749. #define PR_CONTENT_UNREAD PROP_TAG( PT_LONG, 0x3603)
  750. #define PR_CREATE_TEMPLATES PROP_TAG( PT_OBJECT, 0x3604)
  751. #define PR_DETAILS_TABLE PROP_TAG( PT_OBJECT, 0x3605)
  752. #define PR_SEARCH PROP_TAG( PT_OBJECT, 0x3607)
  753. #define PR_SELECTABLE PROP_TAG( PT_BOOLEAN, 0x3609)
  754. #define PR_SUBFOLDERS PROP_TAG( PT_BOOLEAN, 0x360A)
  755. #define PR_STATUS PROP_TAG( PT_LONG, 0x360B)
  756. #define PR_ANR PROP_TAG( PT_TSTRING, 0x360C)
  757. #define PR_ANR_W PROP_TAG( PT_UNICODE, 0x360C)
  758. #define PR_ANR_A PROP_TAG( PT_STRING8, 0x360C)
  759. #define PR_CONTENTS_SORT_ORDER PROP_TAG( PT_MV_LONG, 0x360D)
  760. #define PR_CONTAINER_HIERARCHY PROP_TAG( PT_OBJECT, 0x360E)
  761. #define PR_CONTAINER_CONTENTS PROP_TAG( PT_OBJECT, 0x360F)
  762. #define PR_FOLDER_ASSOCIATED_CONTENTS PROP_TAG( PT_OBJECT, 0x3610)
  763. #define PR_DEF_CREATE_DL PROP_TAG( PT_BINARY, 0x3611)
  764. #define PR_DEF_CREATE_MAILUSER PROP_TAG( PT_BINARY, 0x3612)
  765. #define PR_CONTAINER_CLASS PROP_TAG( PT_TSTRING, 0x3613)
  766. #define PR_CONTAINER_CLASS_W PROP_TAG( PT_UNICODE, 0x3613)
  767. #define PR_CONTAINER_CLASS_A PROP_TAG( PT_STRING8, 0x3613)
  768. #define PR_CONTAINER_MODIFY_VERSION PROP_TAG( PT_I8, 0x3614)
  769. #define PR_AB_PROVIDER_ID PROP_TAG( PT_BINARY, 0x3615)
  770. #define PR_DEFAULT_VIEW_ENTRYID PROP_TAG( PT_BINARY, 0x3616)
  771. #define PR_ASSOC_CONTENT_COUNT PROP_TAG( PT_LONG, 0x3617)
  772. /* Reserved 0x36C0-0x36FF */
  773. /*
  774. * Attachment properties
  775. */
  776. #define PR_ATTACHMENT_X400_PARAMETERS PROP_TAG( PT_BINARY, 0x3700)
  777. #define PR_ATTACH_DATA_OBJ PROP_TAG( PT_OBJECT, 0x3701)
  778. #define PR_ATTACH_DATA_BIN PROP_TAG( PT_BINARY, 0x3701)
  779. #define PR_ATTACH_ENCODING PROP_TAG( PT_BINARY, 0x3702)
  780. #define PR_ATTACH_EXTENSION PROP_TAG( PT_TSTRING, 0x3703)
  781. #define PR_ATTACH_EXTENSION_W PROP_TAG( PT_UNICODE, 0x3703)
  782. #define PR_ATTACH_EXTENSION_A PROP_TAG( PT_STRING8, 0x3703)
  783. #define PR_ATTACH_FILENAME PROP_TAG( PT_TSTRING, 0x3704)
  784. #define PR_ATTACH_FILENAME_W PROP_TAG( PT_UNICODE, 0x3704)
  785. #define PR_ATTACH_FILENAME_A PROP_TAG( PT_STRING8, 0x3704)
  786. #define PR_ATTACH_METHOD PROP_TAG( PT_LONG, 0x3705)
  787. #define PR_ATTACH_LONG_FILENAME PROP_TAG( PT_TSTRING, 0x3707)
  788. #define PR_ATTACH_LONG_FILENAME_W PROP_TAG( PT_UNICODE, 0x3707)
  789. #define PR_ATTACH_LONG_FILENAME_A PROP_TAG( PT_STRING8, 0x3707)
  790. #define PR_ATTACH_PATHNAME PROP_TAG( PT_TSTRING, 0x3708)
  791. #define PR_ATTACH_PATHNAME_W PROP_TAG( PT_UNICODE, 0x3708)
  792. #define PR_ATTACH_PATHNAME_A PROP_TAG( PT_STRING8, 0x3708)
  793. #define PR_ATTACH_RENDERING PROP_TAG( PT_BINARY, 0x3709)
  794. #define PR_ATTACH_TAG PROP_TAG( PT_BINARY, 0x370A)
  795. #define PR_RENDERING_POSITION PROP_TAG( PT_LONG, 0x370B)
  796. #define PR_ATTACH_TRANSPORT_NAME PROP_TAG( PT_TSTRING, 0x370C)
  797. #define PR_ATTACH_TRANSPORT_NAME_W PROP_TAG( PT_UNICODE, 0x370C)
  798. #define PR_ATTACH_TRANSPORT_NAME_A PROP_TAG( PT_STRING8, 0x370C)
  799. #define PR_ATTACH_LONG_PATHNAME PROP_TAG( PT_TSTRING, 0x370D)
  800. #define PR_ATTACH_LONG_PATHNAME_W PROP_TAG( PT_UNICODE, 0x370D)
  801. #define PR_ATTACH_LONG_PATHNAME_A PROP_TAG( PT_STRING8, 0x370D)
  802. #define PR_ATTACH_MIME_TAG PROP_TAG( PT_TSTRING, 0x370E)
  803. #define PR_ATTACH_MIME_TAG_W PROP_TAG( PT_UNICODE, 0x370E)
  804. #define PR_ATTACH_MIME_TAG_A PROP_TAG( PT_STRING8, 0x370E)
  805. #define PR_ATTACH_ADDITIONAL_INFO PROP_TAG( PT_BINARY, 0x370F)
  806. /*
  807. * AB Object properties
  808. */
  809. #define PR_DISPLAY_TYPE PROP_TAG( PT_LONG, 0x3900)
  810. #define PR_TEMPLATEID PROP_TAG( PT_BINARY, 0x3902)
  811. #define PR_PRIMARY_CAPABILITY PROP_TAG( PT_BINARY, 0x3904)
  812. /*
  813. * Mail user properties
  814. */
  815. #define PR_7BIT_DISPLAY_NAME PROP_TAG( PT_STRING8, 0x39FF)
  816. #define PR_ACCOUNT PROP_TAG( PT_TSTRING, 0x3A00)
  817. #define PR_ACCOUNT_W PROP_TAG( PT_UNICODE, 0x3A00)
  818. #define PR_ACCOUNT_A PROP_TAG( PT_STRING8, 0x3A00)
  819. #define PR_ALTERNATE_RECIPIENT PROP_TAG( PT_BINARY, 0x3A01)
  820. #define PR_CALLBACK_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A02)
  821. #define PR_CALLBACK_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A02)
  822. #define PR_CALLBACK_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A02)
  823. #define PR_CONVERSION_PROHIBITED PROP_TAG( PT_BOOLEAN, 0x3A03)
  824. #define PR_DISCLOSE_RECIPIENTS PROP_TAG( PT_BOOLEAN, 0x3A04)
  825. #define PR_GENERATION PROP_TAG( PT_TSTRING, 0x3A05)
  826. #define PR_GENERATION_W PROP_TAG( PT_UNICODE, 0x3A05)
  827. #define PR_GENERATION_A PROP_TAG( PT_STRING8, 0x3A05)
  828. #define PR_GIVEN_NAME PROP_TAG( PT_TSTRING, 0x3A06)
  829. #define PR_GIVEN_NAME_W PROP_TAG( PT_UNICODE, 0x3A06)
  830. #define PR_GIVEN_NAME_A PROP_TAG( PT_STRING8, 0x3A06)
  831. #define PR_GOVERNMENT_ID_NUMBER PROP_TAG( PT_TSTRING, 0x3A07)
  832. #define PR_GOVERNMENT_ID_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A07)
  833. #define PR_GOVERNMENT_ID_NUMBER_A PROP_TAG( PT_STRING8, 0x3A07)
  834. #define PR_BUSINESS_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A08)
  835. #define PR_BUSINESS_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A08)
  836. #define PR_BUSINESS_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A08)
  837. #define PR_OFFICE_TELEPHONE_NUMBER PR_BUSINESS_TELEPHONE_NUMBER
  838. #define PR_OFFICE_TELEPHONE_NUMBER_W PR_BUSINESS_TELEPHONE_NUMBER_W
  839. #define PR_OFFICE_TELEPHONE_NUMBER_A PR_BUSINESS_TELEPHONE_NUMBER_A
  840. #define PR_HOME_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A09)
  841. #define PR_HOME_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A09)
  842. #define PR_HOME_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A09)
  843. #define PR_INITIALS PROP_TAG( PT_TSTRING, 0x3A0A)
  844. #define PR_INITIALS_W PROP_TAG( PT_UNICODE, 0x3A0A)
  845. #define PR_INITIALS_A PROP_TAG( PT_STRING8, 0x3A0A)
  846. #define PR_KEYWORD PROP_TAG( PT_TSTRING, 0x3A0B)
  847. #define PR_KEYWORD_W PROP_TAG( PT_UNICODE, 0x3A0B)
  848. #define PR_KEYWORD_A PROP_TAG( PT_STRING8, 0x3A0B)
  849. #define PR_LANGUAGE PROP_TAG( PT_TSTRING, 0x3A0C)
  850. #define PR_LANGUAGE_W PROP_TAG( PT_UNICODE, 0x3A0C)
  851. #define PR_LANGUAGE_A PROP_TAG( PT_STRING8, 0x3A0C)
  852. #define PR_LOCATION PROP_TAG( PT_TSTRING, 0x3A0D)
  853. #define PR_LOCATION_W PROP_TAG( PT_UNICODE, 0x3A0D)
  854. #define PR_LOCATION_A PROP_TAG( PT_STRING8, 0x3A0D)
  855. #define PR_MAIL_PERMISSION PROP_TAG( PT_BOOLEAN, 0x3A0E)
  856. #define PR_MHS_COMMON_NAME PROP_TAG( PT_TSTRING, 0x3A0F)
  857. #define PR_MHS_COMMON_NAME_W PROP_TAG( PT_UNICODE, 0x3A0F)
  858. #define PR_MHS_COMMON_NAME_A PROP_TAG( PT_STRING8, 0x3A0F)
  859. #define PR_ORGANIZATIONAL_ID_NUMBER PROP_TAG( PT_TSTRING, 0x3A10)
  860. #define PR_ORGANIZATIONAL_ID_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A10)
  861. #define PR_ORGANIZATIONAL_ID_NUMBER_A PROP_TAG( PT_STRING8, 0x3A10)
  862. #define PR_SURNAME PROP_TAG( PT_TSTRING, 0x3A11)
  863. #define PR_SURNAME_W PROP_TAG( PT_UNICODE, 0x3A11)
  864. #define PR_SURNAME_A PROP_TAG( PT_STRING8, 0x3A11)
  865. #define PR_ORIGINAL_ENTRYID PROP_TAG( PT_BINARY, 0x3A12)
  866. #define PR_ORIGINAL_DISPLAY_NAME PROP_TAG( PT_TSTRING, 0x3A13)
  867. #define PR_ORIGINAL_DISPLAY_NAME_W PROP_TAG( PT_UNICODE, 0x3A13)
  868. #define PR_ORIGINAL_DISPLAY_NAME_A PROP_TAG( PT_STRING8, 0x3A13)
  869. #define PR_ORIGINAL_SEARCH_KEY PROP_TAG( PT_BINARY, 0x3A14)
  870. #define PR_POSTAL_ADDRESS PROP_TAG( PT_TSTRING, 0x3A15)
  871. #define PR_POSTAL_ADDRESS_W PROP_TAG( PT_UNICODE, 0x3A15)
  872. #define PR_POSTAL_ADDRESS_A PROP_TAG( PT_STRING8, 0x3A15)
  873. #define PR_COMPANY_NAME PROP_TAG( PT_TSTRING, 0x3A16)
  874. #define PR_COMPANY_NAME_W PROP_TAG( PT_UNICODE, 0x3A16)
  875. #define PR_COMPANY_NAME_A PROP_TAG( PT_STRING8, 0x3A16)
  876. #define PR_TITLE PROP_TAG( PT_TSTRING, 0x3A17)
  877. #define PR_TITLE_W PROP_TAG( PT_UNICODE, 0x3A17)
  878. #define PR_TITLE_A PROP_TAG( PT_STRING8, 0x3A17)
  879. #define PR_DEPARTMENT_NAME PROP_TAG( PT_TSTRING, 0x3A18)
  880. #define PR_DEPARTMENT_NAME_W PROP_TAG( PT_UNICODE, 0x3A18)
  881. #define PR_DEPARTMENT_NAME_A PROP_TAG( PT_STRING8, 0x3A18)
  882. #define PR_OFFICE_LOCATION PROP_TAG( PT_TSTRING, 0x3A19)
  883. #define PR_OFFICE_LOCATION_W PROP_TAG( PT_UNICODE, 0x3A19)
  884. #define PR_OFFICE_LOCATION_A PROP_TAG( PT_STRING8, 0x3A19)
  885. #define PR_PRIMARY_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A1A)
  886. #define PR_PRIMARY_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A1A)
  887. #define PR_PRIMARY_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A1A)
  888. #define PR_BUSINESS2_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A1B)
  889. #define PR_BUSINESS2_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A1B)
  890. #define PR_BUSINESS2_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A1B)
  891. #define PR_OFFICE2_TELEPHONE_NUMBER PR_BUSINESS2_TELEPHONE_NUMBER
  892. #define PR_OFFICE2_TELEPHONE_NUMBER_W PR_BUSINESS2_TELEPHONE_NUMBER_W
  893. #define PR_OFFICE2_TELEPHONE_NUMBER_A PR_BUSINESS2_TELEPHONE_NUMBER_A
  894. #define PR_MOBILE_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A1C)
  895. #define PR_MOBILE_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A1C)
  896. #define PR_MOBILE_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A1C)
  897. #define PR_CELLULAR_TELEPHONE_NUMBER PR_MOBILE_TELEPHONE_NUMBER
  898. #define PR_CELLULAR_TELEPHONE_NUMBER_W PR_MOBILE_TELEPHONE_NUMBER_W
  899. #define PR_CELLULAR_TELEPHONE_NUMBER_A PR_MOBILE_TELEPHONE_NUMBER_A
  900. #define PR_RADIO_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A1D)
  901. #define PR_RADIO_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A1D)
  902. #define PR_RADIO_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A1D)
  903. #define PR_CAR_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A1E)
  904. #define PR_CAR_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A1E)
  905. #define PR_CAR_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A1E)
  906. #define PR_OTHER_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A1F)
  907. #define PR_OTHER_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A1F)
  908. #define PR_OTHER_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A1F)
  909. #define PR_TRANSMITABLE_DISPLAY_NAME PROP_TAG( PT_TSTRING, 0x3A20)
  910. #define PR_TRANSMITABLE_DISPLAY_NAME_W PROP_TAG( PT_UNICODE, 0x3A20)
  911. #define PR_TRANSMITABLE_DISPLAY_NAME_A PROP_TAG( PT_STRING8, 0x3A20)
  912. #define PR_PAGER_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A21)
  913. #define PR_PAGER_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A21)
  914. #define PR_PAGER_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A21)
  915. #define PR_BEEPER_TELEPHONE_NUMBER PR_PAGER_TELEPHONE_NUMBER
  916. #define PR_BEEPER_TELEPHONE_NUMBER_W PR_PAGER_TELEPHONE_NUMBER_W
  917. #define PR_BEEPER_TELEPHONE_NUMBER_A PR_PAGER_TELEPHONE_NUMBER_A
  918. #define PR_USER_CERTIFICATE PROP_TAG( PT_BINARY, 0x3A22)
  919. #define PR_PRIMARY_FAX_NUMBER PROP_TAG( PT_TSTRING, 0x3A23)
  920. #define PR_PRIMARY_FAX_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A23)
  921. #define PR_PRIMARY_FAX_NUMBER_A PROP_TAG( PT_STRING8, 0x3A23)
  922. #define PR_BUSINESS_FAX_NUMBER PROP_TAG( PT_TSTRING, 0x3A24)
  923. #define PR_BUSINESS_FAX_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A24)
  924. #define PR_BUSINESS_FAX_NUMBER_A PROP_TAG( PT_STRING8, 0x3A24)
  925. #define PR_HOME_FAX_NUMBER PROP_TAG( PT_TSTRING, 0x3A25)
  926. #define PR_HOME_FAX_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A25)
  927. #define PR_HOME_FAX_NUMBER_A PROP_TAG( PT_STRING8, 0x3A25)
  928. #define PR_COUNTRY PROP_TAG( PT_TSTRING, 0x3A26)
  929. #define PR_COUNTRY_W PROP_TAG( PT_UNICODE, 0x3A26)
  930. #define PR_COUNTRY_A PROP_TAG( PT_STRING8, 0x3A26)
  931. #define PR_BUSINESS_ADDRESS_COUNTRY PR_COUNTRY
  932. #define PR_BUSINESS_ADDRESS_COUNTRY_W PR_COUNTRY_W
  933. #define PR_BUSINESS_ADDRESS_COUNTRY_A PR_COUNTRY_A
  934. #define PR_LOCALITY PROP_TAG( PT_TSTRING, 0x3A27)
  935. #define PR_LOCALITY_W PROP_TAG( PT_UNICODE, 0x3A27)
  936. #define PR_LOCALITY_A PROP_TAG( PT_STRING8, 0x3A27)
  937. #define PR_BUSINESS_ADDRESS_CITY PR_LOCALITY
  938. #define PR_BUSINESS_ADDRESS_CITY_W PR_LOCALITY_W
  939. #define PR_BUSINESS_ADDRESS_CITY_A PR_LOCALITY_A
  940. #define PR_STATE_OR_PROVINCE PROP_TAG( PT_TSTRING, 0x3A28)
  941. #define PR_STATE_OR_PROVINCE_W PROP_TAG( PT_UNICODE, 0x3A28)
  942. #define PR_STATE_OR_PROVINCE_A PROP_TAG( PT_STRING8, 0x3A28)
  943. #define PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE PR_STATE_OR_PROVINCE
  944. #define PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_W PR_STATE_OR_PROVINCE_W
  945. #define PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_A PR_STATE_OR_PROVINCE_A
  946. #define PR_STREET_ADDRESS PROP_TAG( PT_TSTRING, 0x3A29)
  947. #define PR_STREET_ADDRESS_W PROP_TAG( PT_UNICODE, 0x3A29)
  948. #define PR_STREET_ADDRESS_A PROP_TAG( PT_STRING8, 0x3A29)
  949. #define PR_BUSINESS_ADDRESS_STREET PR_STREET_ADDRESS
  950. #define PR_BUSINESS_ADDRESS_STREET_W PR_STREET_ADDRESS_W
  951. #define PR_BUSINESS_ADDRESS_STREET_A PR_STREET_ADDRESS_A
  952. #define PR_POSTAL_CODE PROP_TAG( PT_TSTRING, 0x3A2A)
  953. #define PR_POSTAL_CODE_W PROP_TAG( PT_UNICODE, 0x3A2A)
  954. #define PR_POSTAL_CODE_A PROP_TAG( PT_STRING8, 0x3A2A)
  955. #define PR_BUSINESS_ADDRESS_POSTAL_CODE PR_POSTAL_CODE
  956. #define PR_BUSINESS_ADDRESS_POSTAL_CODE_W PR_POSTAL_CODE_W
  957. #define PR_BUSINESS_ADDRESS_POSTAL_CODE_A PR_POSTAL_CODE_A
  958. #define PR_POST_OFFICE_BOX PROP_TAG( PT_TSTRING, 0x3A2B)
  959. #define PR_POST_OFFICE_BOX_W PROP_TAG( PT_UNICODE, 0x3A2B)
  960. #define PR_POST_OFFICE_BOX_A PROP_TAG( PT_STRING8, 0x3A2B)
  961. #define PR_BUSINESS_ADDRESS_POST_OFFICE_BOX PR_POST_OFFICE_BOX
  962. #define PR_BUSINESS_ADDRESS_POST_OFFICE_BOX_W PR_POST_OFFICE_BOX_W
  963. #define PR_BUSINESS_ADDRESS_POST_OFFICE_BOX_A PR_POST_OFFICE_BOX_A
  964. #define PR_TELEX_NUMBER PROP_TAG( PT_TSTRING, 0x3A2C)
  965. #define PR_TELEX_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A2C)
  966. #define PR_TELEX_NUMBER_A PROP_TAG( PT_STRING8, 0x3A2C)
  967. #define PR_ISDN_NUMBER PROP_TAG( PT_TSTRING, 0x3A2D)
  968. #define PR_ISDN_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A2D)
  969. #define PR_ISDN_NUMBER_A PROP_TAG( PT_STRING8, 0x3A2D)
  970. #define PR_ASSISTANT_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A2E)
  971. #define PR_ASSISTANT_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A2E)
  972. #define PR_ASSISTANT_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A2E)
  973. #define PR_HOME2_TELEPHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A2F)
  974. #define PR_HOME2_TELEPHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A2F)
  975. #define PR_HOME2_TELEPHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A2F)
  976. #define PR_ASSISTANT PROP_TAG( PT_TSTRING, 0x3A30)
  977. #define PR_ASSISTANT_W PROP_TAG( PT_UNICODE, 0x3A30)
  978. #define PR_ASSISTANT_A PROP_TAG( PT_STRING8, 0x3A30)
  979. #define PR_SEND_RICH_INFO PROP_TAG( PT_BOOLEAN, 0x3A40)
  980. #define PR_WEDDING_ANNIVERSARY PROP_TAG( PT_SYSTIME, 0x3A41)
  981. #define PR_BIRTHDAY PROP_TAG( PT_SYSTIME, 0x3A42)
  982. #define PR_HOBBIES PROP_TAG( PT_TSTRING, 0x3A43)
  983. #define PR_HOBBIES_W PROP_TAG( PT_UNICODE, 0x3A43)
  984. #define PR_HOBBIES_A PROP_TAG( PT_STRING8, 0x3A43)
  985. #define PR_MIDDLE_NAME PROP_TAG( PT_TSTRING, 0x3A44)
  986. #define PR_MIDDLE_NAME_W PROP_TAG( PT_UNICODE, 0x3A44)
  987. #define PR_MIDDLE_NAME_A PROP_TAG( PT_STRING8, 0x3A44)
  988. #define PR_DISPLAY_NAME_PREFIX PROP_TAG( PT_TSTRING, 0x3A45)
  989. #define PR_DISPLAY_NAME_PREFIX_W PROP_TAG( PT_UNICODE, 0x3A45)
  990. #define PR_DISPLAY_NAME_PREFIX_A PROP_TAG( PT_STRING8, 0x3A45)
  991. #define PR_PROFESSION PROP_TAG( PT_TSTRING, 0x3A46)
  992. #define PR_PROFESSION_W PROP_TAG( PT_UNICODE, 0x3A46)
  993. #define PR_PROFESSION_A PROP_TAG( PT_STRING8, 0x3A46)
  994. #define PR_PREFERRED_BY_NAME PROP_TAG( PT_TSTRING, 0x3A47)
  995. #define PR_PREFERRED_BY_NAME_W PROP_TAG( PT_UNICODE, 0x3A47)
  996. #define PR_PREFERRED_BY_NAME_A PROP_TAG( PT_STRING8, 0x3A47)
  997. #define PR_SPOUSE_NAME PROP_TAG( PT_TSTRING, 0x3A48)
  998. #define PR_SPOUSE_NAME_W PROP_TAG( PT_UNICODE, 0x3A48)
  999. #define PR_SPOUSE_NAME_A PROP_TAG( PT_STRING8, 0x3A48)
  1000. #define PR_COMPUTER_NETWORK_NAME PROP_TAG( PT_TSTRING, 0x3A49)
  1001. #define PR_COMPUTER_NETWORK_NAME_W PROP_TAG( PT_UNICODE, 0x3A49)
  1002. #define PR_COMPUTER_NETWORK_NAME_A PROP_TAG( PT_STRING8, 0x3A49)
  1003. #define PR_CUSTOMER_ID PROP_TAG( PT_TSTRING, 0x3A4A)
  1004. #define PR_CUSTOMER_ID_W PROP_TAG( PT_UNICODE, 0x3A4A)
  1005. #define PR_CUSTOMER_ID_A PROP_TAG( PT_STRING8, 0x3A4A)
  1006. #define PR_TTYTDD_PHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A4B)
  1007. #define PR_TTYTDD_PHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A4B)
  1008. #define PR_TTYTDD_PHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A4B)
  1009. #define PR_FTP_SITE PROP_TAG( PT_TSTRING, 0x3A4C)
  1010. #define PR_FTP_SITE_W PROP_TAG( PT_UNICODE, 0x3A4C)
  1011. #define PR_FTP_SITE_A PROP_TAG( PT_STRING8, 0x3A4C)
  1012. #define PR_GENDER PROP_TAG( PT_SHORT, 0x3A4D)
  1013. #define PR_MANAGER_NAME PROP_TAG( PT_TSTRING, 0x3A4E)
  1014. #define PR_MANAGER_NAME_W PROP_TAG( PT_UNICODE, 0x3A4E)
  1015. #define PR_MANAGER_NAME_A PROP_TAG( PT_STRING8, 0x3A4E)
  1016. #define PR_NICKNAME PROP_TAG( PT_TSTRING, 0x3A4F)
  1017. #define PR_NICKNAME_W PROP_TAG( PT_UNICODE, 0x3A4F)
  1018. #define PR_NICKNAME_A PROP_TAG( PT_STRING8, 0x3A4F)
  1019. #define PR_PERSONAL_HOME_PAGE PROP_TAG( PT_TSTRING, 0x3A50)
  1020. #define PR_PERSONAL_HOME_PAGE_W PROP_TAG( PT_UNICODE, 0x3A50)
  1021. #define PR_PERSONAL_HOME_PAGE_A PROP_TAG( PT_STRING8, 0x3A50)
  1022. #define PR_BUSINESS_HOME_PAGE PROP_TAG( PT_TSTRING, 0x3A51)
  1023. #define PR_BUSINESS_HOME_PAGE_W PROP_TAG( PT_UNICODE, 0x3A51)
  1024. #define PR_BUSINESS_HOME_PAGE_A PROP_TAG( PT_STRING8, 0x3A51)
  1025. #define PR_CONTACT_VERSION PROP_TAG( PT_CLSID, 0x3A52)
  1026. #define PR_CONTACT_ENTRYIDS PROP_TAG( PT_MV_BINARY, 0x3A53)
  1027. #define PR_CONTACT_ADDRTYPES PROP_TAG( PT_MV_TSTRING, 0x3A54)
  1028. #define PR_CONTACT_ADDRTYPES_W PROP_TAG( PT_MV_UNICODE, 0x3A54)
  1029. #define PR_CONTACT_ADDRTYPES_A PROP_TAG( PT_MV_STRING8, 0x3A54)
  1030. #define PR_CONTACT_DEFAULT_ADDRESS_INDEX PROP_TAG( PT_LONG, 0x3A55)
  1031. #define PR_CONTACT_EMAIL_ADDRESSES PROP_TAG( PT_MV_TSTRING, 0x3A56)
  1032. #define PR_CONTACT_EMAIL_ADDRESSES_W PROP_TAG( PT_MV_UNICODE, 0x3A56)
  1033. #define PR_CONTACT_EMAIL_ADDRESSES_A PROP_TAG( PT_MV_STRING8, 0x3A56)
  1034. #define PR_COMPANY_MAIN_PHONE_NUMBER PROP_TAG( PT_TSTRING, 0x3A57)
  1035. #define PR_COMPANY_MAIN_PHONE_NUMBER_W PROP_TAG( PT_UNICODE, 0x3A57)
  1036. #define PR_COMPANY_MAIN_PHONE_NUMBER_A PROP_TAG( PT_STRING8, 0x3A57)
  1037. #define PR_CHILDRENS_NAMES PROP_TAG( PT_MV_TSTRING, 0x3A58)
  1038. #define PR_CHILDRENS_NAMES_W PROP_TAG( PT_MV_UNICODE, 0x3A58)
  1039. #define PR_CHILDRENS_NAMES_A PROP_TAG( PT_MV_STRING8, 0x3A58)
  1040. #define PR_HOME_ADDRESS_CITY PROP_TAG( PT_TSTRING, 0x3A59)
  1041. #define PR_HOME_ADDRESS_CITY_W PROP_TAG( PT_UNICODE, 0x3A59)
  1042. #define PR_HOME_ADDRESS_CITY_A PROP_TAG( PT_STRING8, 0x3A59)
  1043. #define PR_HOME_ADDRESS_COUNTRY PROP_TAG( PT_TSTRING, 0x3A5A)
  1044. #define PR_HOME_ADDRESS_COUNTRY_W PROP_TAG( PT_UNICODE, 0x3A5A)
  1045. #define PR_HOME_ADDRESS_COUNTRY_A PROP_TAG( PT_STRING8, 0x3A5A)
  1046. #define PR_HOME_ADDRESS_POSTAL_CODE PROP_TAG( PT_TSTRING, 0x3A5B)
  1047. #define PR_HOME_ADDRESS_POSTAL_CODE_W PROP_TAG( PT_UNICODE, 0x3A5B)
  1048. #define PR_HOME_ADDRESS_POSTAL_CODE_A PROP_TAG( PT_STRING8, 0x3A5B)
  1049. #define PR_HOME_ADDRESS_STATE_OR_PROVINCE PROP_TAG( PT_TSTRING, 0x3A5C)
  1050. #define PR_HOME_ADDRESS_STATE_OR_PROVINCE_W PROP_TAG( PT_UNICODE, 0x3A5C)
  1051. #define PR_HOME_ADDRESS_STATE_OR_PROVINCE_A PROP_TAG( PT_STRING8, 0x3A5C)
  1052. #define PR_HOME_ADDRESS_STREET PROP_TAG( PT_TSTRING, 0x3A5D)
  1053. #define PR_HOME_ADDRESS_STREET_W PROP_TAG( PT_UNICODE, 0x3A5D)
  1054. #define PR_HOME_ADDRESS_STREET_A PROP_TAG( PT_STRING8, 0x3A5D)
  1055. #define PR_HOME_ADDRESS_POST_OFFICE_BOX PROP_TAG( PT_TSTRING, 0x3A5E)
  1056. #define PR_HOME_ADDRESS_POST_OFFICE_BOX_W PROP_TAG( PT_UNICODE, 0x3A5E)
  1057. #define PR_HOME_ADDRESS_POST_OFFICE_BOX_A PROP_TAG( PT_STRING8, 0x3A5E)
  1058. #define PR_OTHER_ADDRESS_CITY PROP_TAG( PT_TSTRING, 0x3A5F)
  1059. #define PR_OTHER_ADDRESS_CITY_W PROP_TAG( PT_UNICODE, 0x3A5F)
  1060. #define PR_OTHER_ADDRESS_CITY_A PROP_TAG( PT_STRING8, 0x3A5F)
  1061. #define PR_OTHER_ADDRESS_COUNTRY PROP_TAG( PT_TSTRING, 0x3A60)
  1062. #define PR_OTHER_ADDRESS_COUNTRY_W PROP_TAG( PT_UNICODE, 0x3A60)
  1063. #define PR_OTHER_ADDRESS_COUNTRY_A PROP_TAG( PT_STRING8, 0x3A60)
  1064. #define PR_OTHER_ADDRESS_POSTAL_CODE PROP_TAG( PT_TSTRING, 0x3A61)
  1065. #define PR_OTHER_ADDRESS_POSTAL_CODE_W PROP_TAG( PT_UNICODE, 0x3A61)
  1066. #define PR_OTHER_ADDRESS_POSTAL_CODE_A PROP_TAG( PT_STRING8, 0x3A61)
  1067. #define PR_OTHER_ADDRESS_STATE_OR_PROVINCE PROP_TAG( PT_TSTRING, 0x3A62)
  1068. #define PR_OTHER_ADDRESS_STATE_OR_PROVINCE_W PROP_TAG( PT_UNICODE, 0x3A62)
  1069. #define PR_OTHER_ADDRESS_STATE_OR_PROVINCE_A PROP_TAG( PT_STRING8, 0x3A62)
  1070. #define PR_OTHER_ADDRESS_STREET PROP_TAG( PT_TSTRING, 0x3A63)
  1071. #define PR_OTHER_ADDRESS_STREET_W PROP_TAG( PT_UNICODE, 0x3A63)
  1072. #define PR_OTHER_ADDRESS_STREET_A PROP_TAG( PT_STRING8, 0x3A63)
  1073. #define PR_OTHER_ADDRESS_POST_OFFICE_BOX PROP_TAG( PT_TSTRING, 0x3A64)
  1074. #define PR_OTHER_ADDRESS_POST_OFFICE_BOX_W PROP_TAG( PT_UNICODE, 0x3A64)
  1075. #define PR_OTHER_ADDRESS_POST_OFFICE_BOX_A PROP_TAG( PT_STRING8, 0x3A64)
  1076. /*
  1077. * Profile section properties
  1078. */
  1079. #define PR_STORE_PROVIDERS PROP_TAG( PT_BINARY, 0x3D00)
  1080. #define PR_AB_PROVIDERS PROP_TAG( PT_BINARY, 0x3D01)
  1081. #define PR_TRANSPORT_PROVIDERS PROP_TAG( PT_BINARY, 0x3D02)
  1082. #define PR_DEFAULT_PROFILE PROP_TAG( PT_BOOLEAN, 0x3D04)
  1083. #define PR_AB_SEARCH_PATH PROP_TAG( PT_MV_BINARY, 0x3D05)
  1084. #define PR_AB_DEFAULT_DIR PROP_TAG( PT_BINARY, 0x3D06)
  1085. #define PR_AB_DEFAULT_PAB PROP_TAG( PT_BINARY, 0x3D07)
  1086. #define PR_FILTERING_HOOKS PROP_TAG( PT_BINARY, 0x3D08)
  1087. #define PR_SERVICE_NAME PROP_TAG( PT_TSTRING, 0x3D09)
  1088. #define PR_SERVICE_NAME_W PROP_TAG( PT_UNICODE, 0x3D09)
  1089. #define PR_SERVICE_NAME_A PROP_TAG( PT_STRING8, 0x3D09)
  1090. #define PR_SERVICE_DLL_NAME PROP_TAG( PT_TSTRING, 0x3D0A)
  1091. #define PR_SERVICE_DLL_NAME_W PROP_TAG( PT_UNICODE, 0x3D0A)
  1092. #define PR_SERVICE_DLL_NAME_A PROP_TAG( PT_STRING8, 0x3D0A)
  1093. #define PR_SERVICE_ENTRY_NAME PROP_TAG( PT_STRING8, 0x3D0B)
  1094. #define PR_SERVICE_UID PROP_TAG( PT_BINARY, 0x3D0C)
  1095. #define PR_SERVICE_EXTRA_UIDS PROP_TAG( PT_BINARY, 0x3D0D)
  1096. #define PR_SERVICES PROP_TAG( PT_BINARY, 0x3D0E)
  1097. #define PR_SERVICE_SUPPORT_FILES PROP_TAG( PT_MV_TSTRING, 0x3D0F)
  1098. #define PR_SERVICE_SUPPORT_FILES_W PROP_TAG( PT_MV_UNICODE, 0x3D0F)
  1099. #define PR_SERVICE_SUPPORT_FILES_A PROP_TAG( PT_MV_STRING8, 0x3D0F)
  1100. #define PR_SERVICE_DELETE_FILES PROP_TAG( PT_MV_TSTRING, 0x3D10)
  1101. #define PR_SERVICE_DELETE_FILES_W PROP_TAG( PT_MV_UNICODE, 0x3D10)
  1102. #define PR_SERVICE_DELETE_FILES_A PROP_TAG( PT_MV_STRING8, 0x3D10)
  1103. #define PR_AB_SEARCH_PATH_UPDATE PROP_TAG( PT_BINARY, 0x3D11)
  1104. #define PR_PROFILE_NAME PROP_TAG( PT_TSTRING, 0x3D12)
  1105. #define PR_PROFILE_NAME_A PROP_TAG( PT_STRING8, 0x3D12)
  1106. #define PR_PROFILE_NAME_W PROP_TAG( PT_UNICODE, 0x3D12)
  1107. /*
  1108. * Status object properties
  1109. */
  1110. #define PR_IDENTITY_DISPLAY PROP_TAG( PT_TSTRING, 0x3E00)
  1111. #define PR_IDENTITY_DISPLAY_W PROP_TAG( PT_UNICODE, 0x3E00)
  1112. #define PR_IDENTITY_DISPLAY_A PROP_TAG( PT_STRING8, 0x3E00)
  1113. #define PR_IDENTITY_ENTRYID PROP_TAG( PT_BINARY, 0x3E01)
  1114. #define PR_RESOURCE_METHODS PROP_TAG( PT_LONG, 0x3E02)
  1115. #define PR_RESOURCE_TYPE PROP_TAG( PT_LONG, 0x3E03)
  1116. #define PR_STATUS_CODE PROP_TAG( PT_LONG, 0x3E04)
  1117. #define PR_IDENTITY_SEARCH_KEY PROP_TAG( PT_BINARY, 0x3E05)
  1118. #define PR_OWN_STORE_ENTRYID PROP_TAG( PT_BINARY, 0x3E06)
  1119. #define PR_RESOURCE_PATH PROP_TAG( PT_TSTRING, 0x3E07)
  1120. #define PR_RESOURCE_PATH_W PROP_TAG( PT_UNICODE, 0x3E07)
  1121. #define PR_RESOURCE_PATH_A PROP_TAG( PT_STRING8, 0x3E07)
  1122. #define PR_STATUS_STRING PROP_TAG( PT_TSTRING, 0x3E08)
  1123. #define PR_STATUS_STRING_W PROP_TAG( PT_UNICODE, 0x3E08)
  1124. #define PR_STATUS_STRING_A PROP_TAG( PT_STRING8, 0x3E08)
  1125. #define PR_X400_DEFERRED_DELIVERY_CANCEL PROP_TAG( PT_BOOLEAN, 0x3E09)
  1126. #define PR_HEADER_FOLDER_ENTRYID PROP_TAG( PT_BINARY, 0x3E0A)
  1127. #define PR_REMOTE_PROGRESS PROP_TAG( PT_LONG, 0x3E0B)
  1128. #define PR_REMOTE_PROGRESS_TEXT PROP_TAG( PT_TSTRING, 0x3E0C)
  1129. #define PR_REMOTE_PROGRESS_TEXT_W PROP_TAG( PT_UNICODE, 0x3E0C)
  1130. #define PR_REMOTE_PROGRESS_TEXT_A PROP_TAG( PT_STRING8, 0x3E0C)
  1131. #define PR_REMOTE_VALIDATE_OK PROP_TAG( PT_BOOLEAN, 0x3E0D)
  1132. /*
  1133. * Display table properties
  1134. */
  1135. #define PR_CONTROL_FLAGS PROP_TAG( PT_LONG, 0x3F00)
  1136. #define PR_CONTROL_STRUCTURE PROP_TAG( PT_BINARY, 0x3F01)
  1137. #define PR_CONTROL_TYPE PROP_TAG( PT_LONG, 0x3F02)
  1138. #define PR_DELTAX PROP_TAG( PT_LONG, 0x3F03)
  1139. #define PR_DELTAY PROP_TAG( PT_LONG, 0x3F04)
  1140. #define PR_XPOS PROP_TAG( PT_LONG, 0x3F05)
  1141. #define PR_YPOS PROP_TAG( PT_LONG, 0x3F06)
  1142. #define PR_CONTROL_ID PROP_TAG( PT_BINARY, 0x3F07)
  1143. #define PR_INITIAL_DETAILS_PANE PROP_TAG( PT_LONG, 0x3F08)
  1144. }
  1145. procedure TIdCoderTNEF.DoLog(const AMsg: String; const AAppendSize: Boolean = True);
  1146. begin
  1147. if AAppendSize then begin
  1148. FLog := FLog + IntToStr(FData.Size - FData.Position) + ':' + AMsg + EOL; {Do not localize}
  1149. end else begin
  1150. FLog := FLog + AMsg + EOL;
  1151. end;
  1152. end;
  1153. procedure TIdCoderTNEF.DoLogFmt(const AFormat: string; const Args: array of const; AAppendSize: Boolean = True);
  1154. begin
  1155. DoLog(IndyFormat(AFormat, Args), AAppendSize);
  1156. end;
  1157. function TIdCoderTNEF.GetStringForMapiType(AType: Word): string;
  1158. begin
  1159. case AType of
  1160. IdTNEF_PT_UNSPECIFIED: begin
  1161. Result := 'Unspecified'; {Do not localize}
  1162. end;
  1163. IdTNEF_PT_NULL: begin
  1164. Result := 'Null'; {Do not localize}
  1165. end;
  1166. IdTNEF_PT_I2: begin
  1167. Result := 'Short'; {Do not localize}
  1168. end;
  1169. IdTNEF_PT_LONG: begin
  1170. Result := 'Long'; {Do not localize}
  1171. end;
  1172. IdTNEF_PT_R4: begin
  1173. Result := 'Float'; {Do not localize}
  1174. end;
  1175. IdTNEF_PT_DOUBLE: begin
  1176. Result := 'Double'; {Do not localize}
  1177. end;
  1178. IdTNEF_PT_CURRENCY: begin
  1179. Result := 'Currency'; {Do not localize}
  1180. end;
  1181. IdTNEF_PT_APPTIME: begin
  1182. Result := 'Application time'; {Do not localize}
  1183. end;
  1184. IdTNEF_PT_ERROR: begin
  1185. Result := 'Error code'; {Do not localize}
  1186. end;
  1187. IdTNEF_PT_BOOLEAN: begin
  1188. Result := 'Boolean'; {Do not localize}
  1189. end;
  1190. IdTNEF_PT_OBJECT: begin
  1191. Result := 'Object'; {Do not localize}
  1192. end;
  1193. IdTNEF_PT_I8: begin
  1194. Result := '64-bit integer'; {Do not localize}
  1195. end;
  1196. IdTNEF_PT_STRING8: begin
  1197. Result := 'String8'; {Do not localize}
  1198. end;
  1199. IdTNEF_PT_UNICODE: begin
  1200. Result := 'Unicode'; {Do not localize}
  1201. end;
  1202. IdTNEF_PT_SYSTIME: begin
  1203. Result := 'SysTime'; {Do not localize}
  1204. end;
  1205. IdTNEF_PT_CLSID: begin
  1206. Result := 'ClsId'; {Do not localize}
  1207. end;
  1208. IdTNEF_PT_BINARY: begin
  1209. Result := 'Binary'; {Do not localize}
  1210. end;
  1211. else
  1212. Result := 'Unknown'; {Do not localize}
  1213. end;
  1214. end;
  1215. function TIdCoderTNEF.GetStringForType(AType: Word): string;
  1216. begin
  1217. case AType of
  1218. IdTNEFAtpTriples: begin
  1219. Result := 'Triples'; {Do not localize}
  1220. end;
  1221. IdTNEFAtpString: begin
  1222. Result := 'String'; {Do not localize}
  1223. end;
  1224. IdTNEFAtpText: begin
  1225. Result := 'Text'; {Do not localize}
  1226. end;
  1227. IdTNEFAtpDate: begin
  1228. Result := 'Date'; {Do not localize}
  1229. end;
  1230. IdTNEFAtpShort: begin
  1231. Result := 'Short'; {Do not localize}
  1232. end;
  1233. IdTNEFAtpLong: begin
  1234. Result := 'Long'; {Do not localize}
  1235. end;
  1236. IdTNEFAtpByte: begin
  1237. Result := 'Byte'; {Do not localize}
  1238. end;
  1239. IdTNEFAtpWord: begin
  1240. Result := 'Word'; {Do not localize}
  1241. end;
  1242. IdTNEFAtpDWord: begin
  1243. Result := 'DWord'; {Do not localize}
  1244. end;
  1245. IdTNEFAtpMax: begin
  1246. Result := 'Max'; {Do not localize}
  1247. end;
  1248. else
  1249. Result := 'Unknown'; {Do not localize}
  1250. end;
  1251. end;
  1252. function TIdCoderTNEF.GetStringForAttribute(AAttribute: Word): string;
  1253. begin
  1254. case AAttribute of
  1255. IdTNEFattNull: begin
  1256. Result := 'Null'; {Do not localize}
  1257. end;
  1258. IdTNEFattFrom: begin
  1259. Result := 'From'; {Do not localize}
  1260. end;
  1261. IdTNEFattSubject: begin
  1262. Result := 'Subject'; {Do not localize}
  1263. end;
  1264. IdTNEFattDateSent: begin
  1265. Result := 'DateSent'; {Do not localize}
  1266. end;
  1267. IdTNEFattDateRecd: begin
  1268. Result := 'DateRecd'; {Do not localize}
  1269. end;
  1270. IdTNEFattMessageStatus: begin
  1271. Result := 'MessageStatus'; {Do not localize}
  1272. end;
  1273. IdTNEFattMessageClass: begin
  1274. Result := 'MessageClass'; {Do not localize}
  1275. end;
  1276. IdTNEFattMessageID: begin
  1277. Result := 'MessageID'; {Do not localize}
  1278. end;
  1279. IdTNEFattParentID: begin
  1280. Result := 'ParentID'; {Do not localize}
  1281. end;
  1282. IdTNEFattConversationID: begin
  1283. Result := 'ConversationID'; {Do not localize}
  1284. end;
  1285. IdTNEFattPriority: begin
  1286. Result := 'Priority'; {Do not localize}
  1287. end;
  1288. IdTNEFattAttachData: begin
  1289. Result := 'AttachData'; {Do not localize}
  1290. end;
  1291. IdTNEFattAttachTitle: begin
  1292. Result := 'AttachTitle'; {Do not localize}
  1293. end;
  1294. IdTNEFattAttachMetaFile: begin
  1295. Result := 'AttachMetaFile'; {Do not localize}
  1296. end;
  1297. IdTNEFattAttachCreateDate: begin
  1298. Result := 'AttachCreateDate'; {Do not localize}
  1299. end;
  1300. IdTNEFattAttachModifyDate: begin
  1301. Result := 'AttachModifyDate'; {Do not localize}
  1302. end;
  1303. IdTNEFattDateModified: begin
  1304. Result := 'DateModified'; {Do not localize}
  1305. end;
  1306. IdTNEFattAttachTransportFilename: begin
  1307. Result := 'AttachTransportFilename'; {Do not localize}
  1308. end;
  1309. IdTNEFattAttachRenddata: begin
  1310. Result := 'AttachRenddata'; {Do not localize}
  1311. end;
  1312. IdTNEFattMAPIProps: begin
  1313. Result := 'MAPIProps'; {Do not localize}
  1314. end;
  1315. IdTNEFattRecipTable: begin
  1316. Result := 'RecipTable'; {Do not localize}
  1317. end;
  1318. IdTNEFattAttachment: begin
  1319. Result := 'Null'; {Do not localize}
  1320. end;
  1321. IdTNEFattTnefVersion: begin
  1322. Result := 'TnefVersion'; {Do not localize}
  1323. end;
  1324. IdTNEFattOemCodepage: begin
  1325. Result := 'OemCodepage'; {Do not localize}
  1326. end;
  1327. IdTNEFattOriginalMessageClass: begin
  1328. Result := 'OriginalMessageClass'; {Do not localize}
  1329. end;
  1330. //IdTNEFattOwner: begin
  1331. // Result := 'Owner'; {Do not localize}
  1332. //end;
  1333. IdTNEFattSentFor: begin
  1334. Result := 'SentFor'; {Do not localize}
  1335. end;
  1336. IdTNEFattDelegate: begin
  1337. Result := 'Delegate'; {Do not localize}
  1338. end;
  1339. //IdTNEFattDateStart: begin
  1340. // Result := 'DateStart'; {Do not localize}
  1341. //end;
  1342. IdTNEFattDateEnd: begin
  1343. Result := 'DateEnd'; {Do not localize}
  1344. end;
  1345. IdTNEFattAidOwner: begin
  1346. Result := 'OwnerAID'; {Do not localize}
  1347. end;
  1348. IdTNEFattRequestRes: begin
  1349. Result := 'ResponseRequested'; {Do not localize}
  1350. end;
  1351. else
  1352. Result := 'Unknown'; {Do not localize}
  1353. end;
  1354. end;
  1355. class function TIdCoderTNEF.IsFilenameTnef(const AFilename: string): Boolean;
  1356. begin
  1357. Result := IdCoderTNEF.IsFilenameTnef(AFilename);
  1358. end;
  1359. function IsFilenameTnef(const AFilename: string): Boolean;
  1360. begin
  1361. if TextIsSame(AFilename, 'winmail.dat') then begin
  1362. Result := True;
  1363. end
  1364. else if TextStartsWith(AFilename, 'att') and TextEndsWith(AFilename, '.dat') then begin
  1365. Result := IndyStrToInt(Copy(AFilename, 4, Length(AFilename)-7), -1) > -1;
  1366. end else begin
  1367. Result := False;
  1368. end;
  1369. end;
  1370. function TIdCoderTNEF.GetMultipleUnicodeOrString8String(AType: Word): TIdUnicodeString;
  1371. var
  1372. LIndex, LCount: LongWord;
  1373. begin
  1374. //Usually this will only contain one string, but if there are more, return
  1375. //them as a single string concatenated with semicolons.
  1376. LCount := GetLongWord;
  1377. if FDoLogging then begin
  1378. DoLogFmt(' Found %d %s String(s):', [LCount, GetStringForMapiType(AType)]); {Do not localize}
  1379. end;
  1380. if LCount = 0 then begin //Very unlikely, just paranoia
  1381. Result := '';
  1382. Exit;
  1383. end;
  1384. Result := GetUnicodeOrString8String(AType);
  1385. for LIndex := 2 to LCount do begin
  1386. Result := ';' + GetUnicodeOrString8String(AType); {Do not localize}
  1387. end;
  1388. end;
  1389. function TIdCoderTNEF.GetUnicodeOrString8String(AType: Word): TIdUnicodeString;
  1390. var
  1391. LLength: LongWord;
  1392. LBuf: TIdBytes;
  1393. begin
  1394. Result := '';
  1395. LLength := GetLongWord;
  1396. if LLength = 0 then begin
  1397. Exit;
  1398. end;
  1399. //Note the length count includes a terminating null.
  1400. case AType of
  1401. IdTNEF_PT_UNICODE: begin
  1402. LBuf := GetBytes(LLength);
  1403. SetString(Result, PWideChar(LBuf), (LLength div SizeOf(TIdWideChar))-1);
  1404. end;
  1405. IdTNEF_PT_STRING8: begin
  1406. LBuf := GetBytes(LLength);
  1407. // TODO: use the value from the attOemCodepage attribute to decode the data:
  1408. Result := {IndyTextEncoding(attOemCodepage)}IndyTextEncoding_8Bit.GetString(LBuf, 0, Length(LBuf)-1);
  1409. end;
  1410. else begin
  1411. Skip(LLength);
  1412. end;
  1413. end;
  1414. if FDoLogging then begin
  1415. DoLog(' Found string value: ' + Result); {Do not localize}
  1416. end;
  1417. //Note the strings are padded to 4-byte boundaries...
  1418. if (LLength mod 4) > 0 then begin
  1419. Skip(4 - (LLength mod 4));
  1420. end;
  1421. end;
  1422. function TIdCoderTNEF.PadWithZeroes(const AStr: string; ACount: integer): string;
  1423. begin
  1424. if Length(AStr) < ACount then begin
  1425. Result := StringOfChar('0', ACount-Length(AStr)) + AStr;
  1426. end else begin
  1427. Result := AStr;
  1428. end;
  1429. end;
  1430. function TIdCoderTNEF.GetByteAsChar(AByte: Byte): Char;
  1431. begin
  1432. //Return a displayable char or '.' if not displayable.
  1433. if (Ord(AByte) > 31) and (Ord(AByte) < 127) then begin
  1434. Result := Chr(AByte);
  1435. end else begin
  1436. Result := '.'; {Do not localize}
  1437. end;
  1438. end;
  1439. function TIdCoderTNEF.GetByteAsHexString(AByte: Byte): string;
  1440. var
  1441. LsTemp: string;
  1442. begin
  1443. LsTemp := IndyFormat('%x', [AByte]); {Do not localize}
  1444. Result := PadWithZeroes(LsTemp, 2);
  1445. end;
  1446. function TIdCoderTNEF.GetByteAsHexString: string;
  1447. var
  1448. LnTemp: Byte;
  1449. LsTemp: string;
  1450. begin
  1451. LnTemp := GetByte;
  1452. LsTemp := IndyFormat('%x', [LnTemp]); {Do not localize}
  1453. Result := PadWithZeroes(LsTemp, 2);
  1454. end;
  1455. function TIdCoderTNEF.GetBytesAsHexString(ACount: integer): string;
  1456. var
  1457. i: integer;
  1458. begin
  1459. Result := '';
  1460. for i := 0 to ACount-1 do begin
  1461. Result := Result + GetByteAsHexString + ' '; {Do not localize}
  1462. end;
  1463. end;
  1464. function TIdCoderTNEF.GetByte: Byte;
  1465. var
  1466. LTemp: TIdBytes;
  1467. begin
  1468. LTemp := GetBytes(SizeOf(Byte));
  1469. Result := LTemp[0];
  1470. end;
  1471. function TIdCoderTNEF.GetBytes(ALength: Integer; APeek: Boolean = False): TIdBytes;
  1472. var
  1473. LPos: TIdStreamSize;
  1474. begin
  1475. Result := nil;
  1476. CheckForEof(ALength);
  1477. LPos := FData.Position;
  1478. try
  1479. //Note the length count includes a terminating null.
  1480. ReadTIdBytesFromStream(FData, Result, ALength);
  1481. finally
  1482. if APeek then begin
  1483. FData.Position := LPos;
  1484. end;
  1485. end;
  1486. end;
  1487. function TIdCoderTNEF.GetWord: Word;
  1488. var
  1489. LTemp: TIdBytes;
  1490. begin
  1491. LTemp := GetBytes(SizeOf(Word));
  1492. Result := PWord(LTemp)^;
  1493. end;
  1494. function TIdCoderTNEF.GetLongWord: LongWord;
  1495. var
  1496. LTemp: TIdBytes;
  1497. begin
  1498. LTemp := GetBytes(SizeOf(LongWord));
  1499. Result := PLongWord(LTemp)^;
  1500. end;
  1501. function TIdCoderTNEF.GetInt64: Int64;
  1502. var
  1503. LTemp: TIdBytes;
  1504. begin
  1505. LTemp := GetBytes(SizeOf(Int64));
  1506. Result := PInt64(@LTemp[0])^;
  1507. end;
  1508. function TIdCoderTNEF.GetString(ALength: Word): string;
  1509. begin
  1510. if ALength > 0 then begin
  1511. Result := ReadStringFromStream(FData, ALength-1, IndyTextEncoding_8Bit{$IFDEF STRING_IS_ANSI}, IndyTextEncoding_8Bit{$ENDIF});
  1512. Skip(1) //Skip terminating null
  1513. end else begin
  1514. Result := '';
  1515. end;
  1516. end;
  1517. function TIdCoderTNEF.GetDate(ALength: Word): TDateTime;
  1518. var
  1519. LYear, LMonth, LDay, LHour, LMinute, LSecond: Word;
  1520. begin
  1521. LYear := GetWord;
  1522. LMonth := GetWord;
  1523. LDay := GetWord;
  1524. LHour := GetWord;
  1525. LMinute := GetWord;
  1526. LSecond := GetWord;
  1527. Skip(SizeOf(Word)); //Day-of-week
  1528. Result := EncodeDateTime(LYear, LMonth, LDay, LHour, LMinute, LSecond, 0);
  1529. end;
  1530. procedure TIdCoderTNEF.Skip(ACount: integer);
  1531. begin
  1532. CheckForEof(ACount);
  1533. FData.Seek(ACount, soFromCurrent);
  1534. end;
  1535. procedure TIdCoderTNEF.Checksum(ANumBytesToCheck: integer);
  1536. var
  1537. LChecksum: Word;
  1538. i: integer;
  1539. LBytes: TIdBytes;
  1540. LTNEFChecksum: Word;
  1541. begin
  1542. //Do a checksum on ANumBytesToCheck bytes from the current position.
  1543. //Compare to the recorded TNEF value in the word after these bytes.
  1544. //DONT move our stream pointer forward.
  1545. LBytes := GetBytes(ANumBytesToCheck + SizeOf(Word), True);
  1546. LChecksum := 0;
  1547. for i := 0 to ANumBytesToCheck-1 do begin
  1548. Inc(LChecksum, LBytes[i]);
  1549. end;
  1550. LTNEFChecksum := PWord(@LBytes[ANumBytesToCheck])^;
  1551. if LChecksum <> LTNEFChecksum then begin
  1552. raise EIdTnefChecksumFailure.Create('Checksum failure - TNEF is corrupt or truncated'); {Do not localize}
  1553. end;
  1554. end;
  1555. procedure TIdCoderTNEF.CheckForEof(ANumBytesRequested: integer);
  1556. begin
  1557. //See if you have enough bytes left to satisfy the request for nNumBytesRequested...
  1558. if (FData.Size - FData.Position) < TIdStreamSize(ANumBytesRequested) then begin
  1559. raise EIdTnefRanOutOfBytes.Create('Hit end of file prematurely - TNEF is corrupt or truncated'); {Do not localize}
  1560. end;
  1561. end;
  1562. procedure TIdCoderTNEF.Parse(const AIn: string; AMsg: TIdMessage; ALog: Boolean = False);
  1563. var
  1564. LIn: TMemoryStream;
  1565. begin
  1566. LIn := TMemoryStream.Create;
  1567. try
  1568. WriteStringToStream(LIn, AIn, IndyTextEncoding_8Bit{$IFDEF STRING_IS_ANSI}, IndyTextEncoding_8Bit{$ENDIF});
  1569. LIn.Position := 0;
  1570. Parse(LIn, AMsg, ALog);
  1571. finally
  1572. LIn.Free;
  1573. end;
  1574. end;
  1575. procedure TIdCoderTNEF.Parse(const AIn: TIdAttachment; AMsg: TIdMessage; ALog: Boolean = False);
  1576. var
  1577. LTempStream: TStream;
  1578. begin
  1579. LTempStream := AIn.OpenLoadStream;
  1580. try
  1581. Parse(LTempStream, AMsg, ALog);
  1582. finally
  1583. AIn.CloseLoadStream;
  1584. end;
  1585. end;
  1586. procedure TIdCoderTNEF.Parse(const AIn: TIdBytes; AMsg: TIdMessage; ALog: Boolean = False);
  1587. var
  1588. LIn: TMemoryStream;
  1589. begin
  1590. LIn := TMemoryStream.Create;
  1591. try
  1592. WriteTIdBytesToStream(LIn, AIn);
  1593. LIn.Position := 0;
  1594. Parse(LIn, AMsg, ALog);
  1595. finally
  1596. LIn.Free;
  1597. end;
  1598. end;
  1599. procedure TIdCoderTNEF.ParseMessageBlock;
  1600. var
  1601. LType, LAttribute: Word;
  1602. begin
  1603. LAttribute := GetWord;
  1604. LType := GetWord;
  1605. ParseAttribute(LAttribute, LType);
  1606. end;
  1607. procedure TIdCoderTNEF.IsCurrentAttachmentValid;
  1608. begin
  1609. if FCurrentAttachment = nil then begin
  1610. raise EIdTnefCurrentAttachmentInvalid.Create('Attempt to access invalid attachment - invalid TNEF missing attAttachRenddata attribute at start of attachment?'); {Do not localize}
  1611. end;
  1612. end;
  1613. function TIdCoderTNEF.GetAttributeString(const AAttributeName: string; AType: Word): string;
  1614. var
  1615. LLength: LongWord;
  1616. begin
  1617. LLength := GetLongWord;
  1618. if FDoLogging then begin
  1619. DoLogFmt(' ParseAttachmentBlock found %s type, length: %d', [AAttributeName, LLength]); {Do not localize}
  1620. end;
  1621. if AType <> IdTNEFAtpString then begin
  1622. raise EIdTnefAttributeUnexpectedType.Create(AAttributeName + ' not a String'); {Do not localize}
  1623. end;
  1624. Checksum(LLength);
  1625. Result := GetString(LLength);
  1626. Skip(2); //Checksum
  1627. end;
  1628. procedure TIdCoderTNEF.ParseAttachmentBlock;
  1629. var
  1630. LType, LAttribute: Word;
  1631. LLength: LongWord;
  1632. LDestStream: TStream;
  1633. begin
  1634. LAttribute := GetWord;
  1635. LType := GetWord;
  1636. if FDoLogging then begin
  1637. DoLogFmt(' ParseAttachmentBlock passed a %s type %s', [GetStringForAttribute(LAttribute), GetStringForType(LType)]); {Do not localize}
  1638. end;
  1639. case LAttribute of
  1640. IdTNEFattAttachRenddata: begin
  1641. //Per Microsoft, you get this first, at the start of every attachment,
  1642. //create a new attachment when you encounter this.
  1643. LLength := GetLongWord;
  1644. if FDoLogging then begin
  1645. DoLog(' ParseAttachmentBlock found IdTNETattAttachRenddata type, length: ' + IntToStr(LLength)); {Do not localize}
  1646. end;
  1647. Checksum(LLength);
  1648. Skip(LLength);
  1649. Skip(2); //Checksum
  1650. if FDoLogging then begin
  1651. DoLog(' Adding attachment to decoded message.'); {Do not localize}
  1652. end;
  1653. FMsg.DoCreateAttachment(nil, FCurrentAttachment);
  1654. FCurrentAttachment.ParentPart := -1;
  1655. end;
  1656. IdTNEFattAttachTitle: begin
  1657. //This is the filename of the attachment, set the already-created attachment's
  1658. //filename to this.
  1659. IsCurrentAttachmentValid;
  1660. FCurrentAttachment.FileName := GetAttributeString('IdTNEFattAttachTitle', LType); {Do not localize}
  1661. if FDoLogging then begin
  1662. DoLog(' ParseAttachmentBlock parsed attachment filename: ' + FCurrentAttachment.FileName); {Do not localize}
  1663. end;
  1664. end;
  1665. IdTNEFattAttachData: begin
  1666. //This is the attachment file contents, set it for the already-created
  1667. //attachment.
  1668. LLength := GetLongWord;
  1669. if FDoLogging then begin
  1670. DoLog(' ParseAttachmentBlock found IdTNEFattAttachData type, length: ' + IntToStr(LLength)); {Do not localize}
  1671. end;
  1672. if LType <> IdTNEFAtpByte then begin
  1673. raise EIdTnefAttributeUnexpectedType.Create('TNEF AttachmentData not a Byte'); {Do not localize}
  1674. end;
  1675. Checksum(LLength);
  1676. if LLength > 0 then begin
  1677. IsCurrentAttachmentValid;
  1678. LDestStream := FCurrentAttachment.PrepareTempStream;
  1679. try
  1680. LDestStream.CopyFrom(FData, LLength);
  1681. finally
  1682. FCurrentAttachment.FinishTempStream;
  1683. end;
  1684. end;
  1685. if FDoLogging then begin
  1686. DoLogFmt(' ParseAttachmentBlock copied %d bytes to attachment.', [LLength]); {Do not localize}
  1687. end;
  1688. Skip(2); //Checksum
  1689. end;
  1690. else
  1691. if FDoLogging then begin
  1692. DoLogFmt(' ParseAttachmentBlock found unknown attribute: %d, type: %d, passing to ParseAttribute.', [LAttribute, LType]); {Do not localize}
  1693. end;
  1694. ParseAttribute(LAttribute, LType);
  1695. end;
  1696. end;
  1697. function TIdCoderTNEF.GetMapiBoolean(AType: Word; const AText: string): Smallint;
  1698. begin
  1699. if AType <> IdTNEF_PT_BOOLEAN then begin
  1700. raise EIdTnefUnexpectedType.CreateFmt('Expected Boolean for %s', [AText]); {Do not localize}
  1701. end;
  1702. Result := GetWord;
  1703. Skip(SizeOf(Word)); //Skip next two bytes (padded to 4 bytes)
  1704. if FDoLogging then begin
  1705. DoLogFmt(' ParseMapiProp found %s Boolean, value: %d', [AText, Result]); {Do not localize}
  1706. end;
  1707. end;
  1708. function TIdCoderTNEF.GetMapiLong(AType: Word; const AText: string): Longint;
  1709. begin
  1710. if AType <> IdTNEF_PT_LONG then begin
  1711. raise EIdTnefUnexpectedType.CreateFmt('Expected Long for %s', [AText]); {Do not localize}
  1712. end;
  1713. Result := GetLongWord;
  1714. if FDoLogging then begin
  1715. DoLogFmt(' ParseMapiProp found %s Long, value: %d', [AText, Result]); {Do not localize}
  1716. end;
  1717. end;
  1718. function TIdCoderTNEF.GetMapiSysTime(AType: Word; const AText: string): TDateTime;
  1719. var
  1720. LHour, LMinute, LSecond, LMilliSecond: Word;
  1721. LVal: Int64;
  1722. LTime: Double;
  1723. begin
  1724. //MAPI's SysTime is a 64-bit integer holding the number of 100ns intervals
  1725. //since 1st Jan 1601.
  1726. if AType <> IdTNEF_PT_SYSTIME then begin
  1727. raise EIdTnefUnexpectedType.CreateFmt('Expected SysTime for %s', [AText]); {Do not localize}
  1728. end;
  1729. LVal := GetInt64;
  1730. //I am sure there is a better way of doing the following...
  1731. LVal := LVal div 10; //Ditch the 100ns
  1732. LVal := LVal div 1000; //Ditch the ms
  1733. LMilliSecond := LVal mod 1000;
  1734. LVal := LVal div 1000;
  1735. LSecond := LVal mod 60;
  1736. LVal := LVal div 60;
  1737. LMinute := LVal mod 60;
  1738. LVal := LVal div 60;
  1739. LHour := LVal mod 24;
  1740. LVal := LVal div 24;
  1741. //LVal is now the days since 1/1/1601. Subtract Delphi's 300-year offset...
  1742. Result := LVal;
  1743. Result := Result + EncodeDate(1601, 1, 1); {Do not localize}
  1744. //Is the hour out by 1 or is it WET vs GMT time? Or is it GetDate that is the hour out?
  1745. LTime := ((((((LHour*60)+LMinute)*60)+LSecond)*1000)+LMilliSecond)/(24*60*60*1000);
  1746. Result := Result + LTime;
  1747. if FDoLogging then begin
  1748. DoLogFmt(' ParseMapiProp found %s SysTime, value: %s', [AText, DateTimeToStr(Result)]); {Do not localize}
  1749. end;
  1750. end;
  1751. function TIdCoderTNEF.GetMapiStrings(AType: Word; const AText: string): string;
  1752. begin
  1753. //May be PT_UNICODE or PT_STRING8 (PT_TSTRING will be aliased to one of these)...
  1754. if (AType <> IdTNEF_PT_UNICODE) and (AType <> IdTNEF_PT_STRING8) then begin
  1755. raise EIdTnefUnexpectedType.CreateFmt('Expected Unicode or String8 for %s', [AText]); {Do not localize}
  1756. end;
  1757. Result := GetMultipleUnicodeOrString8String(AType);
  1758. if FDoLogging then begin
  1759. DoLogFmt(' ParseMapiProp found %s String, value: %s', [AText, Result]); {Do not localize}
  1760. end;
  1761. end;
  1762. { GetMapiObject was previously needed, may be needed later in development...
  1763. function TIdCoderTNEF.GetMapiObject(AType: Word; const AText: string): TIdBytes;
  1764. begin
  1765. if AType <> IdTNEF_PT_OBJECT then begin
  1766. raise EIdTnefUnexpectedType.CreateFmt('Expected Object for %s', [AText]); {Do not localize}
  1767. { end;
  1768. Result := GetMapiItemAsBytes(AType, AText);
  1769. end;
  1770. }
  1771. function TIdCoderTNEF.GetMapiBinaryAsString(AType: Word; const AText: string): string;
  1772. var
  1773. LBinary: TIdBytes;
  1774. LStrLen: integer;
  1775. LIndex: integer;
  1776. begin
  1777. //You MUST know that the binary data is really a null-terminated string.
  1778. LBinary := GetMapiBinary(AType, AText);
  1779. LStrLen := Length(LBinary)-1;
  1780. Result := '';
  1781. for LIndex := 0 to LStrLen-1 do begin
  1782. Result := Result + Chr(LBinary[LIndex]);
  1783. end;
  1784. end;
  1785. function TIdCoderTNEF.GetMapiBinaryAsEmailName(AType: Word; const AText: string): string;
  1786. begin
  1787. Result := GetMapiBinaryAsString(AType, AText);
  1788. //If it starts SMTP: then remove SMTP:, but leave anything else (e.g. FAX:)
  1789. if TextStartsWith(Result, 'SMTP:') then begin {Do not localize}
  1790. Result := Trim(Copy(Result, 6, MaxInt));
  1791. end;
  1792. Result := LowerCase(Result);
  1793. end;
  1794. function TIdCoderTNEF.GetMapiBinary(AType: Word; const AText: string): TIdBytes;
  1795. begin
  1796. if AType <> IdTNEF_PT_BINARY then begin
  1797. raise EIdTnefUnexpectedType.CreateFmt('Expected Binary for %s', [AText]); {Do not localize}
  1798. end;
  1799. Result := GetMapiItemAsBytesPossiblyCompressed(AType, AText);
  1800. end;
  1801. function TIdCoderTNEF.GetMapiItemAsBytesPossiblyCompressed(AType: Word; const AText: string): TIdBytes;
  1802. var
  1803. LCount, LLength: LongWord;
  1804. LMagicNumber: LongWord;
  1805. LCompressedSize, LUncompressedSize: LongWord;
  1806. LPos: TIdStreamSize;
  1807. begin
  1808. SetLength(Result, 0);
  1809. LCount := GetLongWord;
  1810. if FDoLogging then begin
  1811. DoLogFmt(' Found %d %s:', [LCount, GetStringForMapiType(AType)]); {Do not localize}
  1812. end;
  1813. if LCount = 0 then begin //Very unlikely, just paranoia
  1814. Exit;
  1815. end;
  1816. if LCount <> 1 then begin
  1817. raise EIdTnefNotSupported.Create('Binary/Object not supported with a count > 1'); {Do not localize}
  1818. end;
  1819. LLength := GetLongWord;
  1820. if LLength >= 12 then begin
  1821. //Peek ahead to see if it has an optional magic number, indicating that it
  1822. //has another header here.
  1823. //If it has a valid magic number, then the next long is the
  1824. //uncompressed size, then the compressed size, next is the magic (long) number,
  1825. //next is a CRC.
  1826. //We initially only want to see if it has a magic number...
  1827. LPos := FData.Position;
  1828. try
  1829. Skip(8);
  1830. LMagicNumber := GetLongWord;
  1831. finally
  1832. FData.Position := LPos;
  1833. end;
  1834. if LMagicNumber = $414C454D then begin
  1835. //It has a header, but this magic number means it is NOT compressed.
  1836. //Note: I have never seen this option existing in reality.
  1837. LCompressedSize := GetLongWord;
  1838. LUncompressedSize := GetLongWord;
  1839. Skip(SizeOf(LongWord)); //Magic word
  1840. Skip(SizeOf(LongWord)); //Checksum, ignore this, this block was crc-checked already
  1841. if FDoLogging then begin
  1842. DoLogFmt(' Is uncompressed, uncompressed size %d, compressed size %d', {Do not localize}
  1843. [LUncompressedSize, LCompressedSize]);
  1844. end;
  1845. Result := InternalGetMapiItemAsBytes(LCount, LLength-16, AType, AText);
  1846. Exit;
  1847. end
  1848. else if LMagicNumber = $75465A4C then begin
  1849. //It is compressed. Decompress it.
  1850. Result := DecompressRtf(LCount, LLength, AType, AText);
  1851. Exit;
  1852. end;
  1853. end;
  1854. //Not compressed (or not compressed in a format we recognise)...
  1855. Result := InternalGetMapiItemAsBytes(LCount, LLength, AType, AText);
  1856. end;
  1857. function TIdCoderTNEF.DecompressRtf(ACount, ALength: LongWord; AType: Word; const AText: string): TIdBytes;
  1858. var
  1859. LCompressedSize, LUncompressedSize: LongWord;
  1860. LData: TIdBytes;
  1861. LInIndex, LOutIndex: LongWord;
  1862. LFlags: Byte;
  1863. LShifts: integer;
  1864. LFlag: Byte;
  1865. LCodePosition: integer;
  1866. LCodeLength: integer;
  1867. LDecodeString: string;
  1868. LDecodeStringLength: LongWord;
  1869. LTemp: Integer;
  1870. LOutBufferSize: LongWord;
  1871. begin
  1872. //Read header...
  1873. LCompressedSize := GetLongWord; //Length AFTER this field (LLength - 4)
  1874. LUncompressedSize := GetLongWord;
  1875. GetLongWord; //Magic number
  1876. GetLongWord; //Checksum, ignore this, this block was crc-checked already
  1877. if FDoLogging then begin
  1878. DoLogFmt(' Is compressed, uncompressed size %d, compressed size %d', {Do not localize}
  1879. [LUncompressedSize, LCompressedSize]);
  1880. end;
  1881. //Get the compressed bytes...
  1882. LData := InternalGetMapiItemAsBytes(ACount, ALength-16, AType, AText);
  1883. LDecodeStringLength := Length(IdTNEF_decode_string);
  1884. LOutBufferSize := LDecodeStringLength + LUncompressedSize;
  1885. SetLength(Result, LOutBufferSize);
  1886. //Copy the preload decode string into the output...
  1887. LDecodeString := IdTNEF_decode_string;
  1888. for LTemp := 0 to LDecodeStringLength-1 do begin
  1889. Result[LTemp] := Byte(LDecodeString[LTemp+1]);
  1890. end;
  1891. LInIndex := 0;
  1892. LOutIndex := LDecodeStringLength;
  1893. Dec(ALength, 16); //Adjust for the header.
  1894. LShifts := 8; //Force an initial load of the first flag byte
  1895. LFlags := 0; //Stop warning
  1896. while LInIndex < ALength do begin
  1897. //This scheme blocks that contain a starting byte of eight flags followed by
  1898. //eight 1 or 2-byte entries. If the flag is 0, its entry is a single
  1899. //literal byte, if 1 then its entry is a two-byte compression code.
  1900. if LShifts = 8 then begin
  1901. LFlags := LData[LInIndex];
  1902. LShifts := 0;
  1903. Inc(LInIndex);
  1904. end;
  1905. LFlag := LFlags and 1;
  1906. LFlags := LFlags shr 1;
  1907. Inc(LShifts);
  1908. if LFlag = 0 then begin
  1909. //A single literal byte...
  1910. Result[LOutIndex] := LData[LInIndex];
  1911. Inc(LInIndex);
  1912. Inc(LOutIndex);
  1913. end else begin
  1914. //A two-byte code telling us that the bytes we want to output are
  1915. //a copy of bytes that were previously outputted. The position of
  1916. //the previous bytes is the first three nibbles, the number of
  1917. //bytes to copy is the last nibble.
  1918. LCodePosition := LData[LInIndex];
  1919. Inc(LInIndex);
  1920. LCodeLength := LData[LInIndex];
  1921. Inc(LInIndex);
  1922. LCodePosition := LCodePosition shl 4;
  1923. LCodePosition := LCodePosition or (LCodeLength shr 4);
  1924. LCodeLength := LCodeLength and $F; //The low nibble
  1925. //Since repetitions of 0 or 1 byte would be a waste of time, the
  1926. //length runs from 2 to 17 instead of 0 to 15...
  1927. LCodeLength := LCodeLength + 2;
  1928. //LCodePosition points to the byte sequence we are to copy from the
  1929. //previously-decoded output data. The output data is viewed as a
  1930. //4096-byte circular buffer into which LCodePosition points. It is
  1931. //further complicated by the fact that the buffer is preloaded with
  1932. //the string IdTNEF_decode_string. Rather than using a real buffer,
  1933. //we just calculate the corresponding position in the output data.
  1934. LCodePosition := ((Integer(LOutIndex) div 4096) * 4096) + LCodePosition;
  1935. //The flag byte always has 8 bits, but at the end of the data, the
  1936. //last bits may be padding. In this case, both LOutPosition and
  1937. //LOutIndex will equal LOutBufferSize (1 byte past our output).
  1938. //If we don't filter them out, we will get an access violation.
  1939. if LOutIndex >= LOutBufferSize then begin
  1940. if FDoLogging then begin
  1941. DoLogFmt(' Ignoring EOD padding: %d bytes from offset %d to %d destlen %d', {Do not localize}
  1942. [LCodeLength, LCodePosition, LOutIndex, LOutBufferSize],
  1943. False);
  1944. end;
  1945. end else begin
  1946. if LCodePosition >= Integer(LOutIndex) then begin
  1947. //The buffer is supposed to be a circular buffer. Since we
  1948. //made it a linear buffer, we need to wrap around...
  1949. LCodePosition := LCodePosition - 4096;
  1950. end;
  1951. if LCodePosition < 0 then begin
  1952. //This should never happen, would cause an AV...
  1953. raise EIdTnefCorruptData.Create('Corrupt compressed rtf: negative code position'); {Do not localize}
  1954. end;
  1955. if FDoLogging then begin
  1956. DoLogFmt(' Copying %d bytes from offset %d to %d destlen %d', {Do not localize}
  1957. [LCodeLength, LCodePosition, LOutIndex, LOutBufferSize], False);
  1958. end;
  1959. for LTemp := 0 to LCodeLength-1 do begin
  1960. Result[LOutIndex] := Result[LCodePosition+LTemp]; //GPFs here
  1961. Inc(LOutIndex);
  1962. end;
  1963. end;
  1964. end;
  1965. end;
  1966. //Remove the decode string from the output...
  1967. for LOutIndex := 0 to LUncompressedSize-1 do begin
  1968. Result[LOutIndex] := Result[LOutIndex+LDecodeStringLength];
  1969. end;
  1970. SetLength(Result, LUncompressedSize);
  1971. if FDoLogging then begin
  1972. DoLog(' Uncompressed bytes:'); {Do not localize}
  1973. DumpBytes(Result);
  1974. end;
  1975. end;
  1976. function TIdCoderTNEF.GetMapiItemAsBytes(AType: Word; const AText: string): TIdBytes;
  1977. var
  1978. LCount, LLength: LongWord;
  1979. begin
  1980. SetLength(Result, 0);
  1981. LCount := GetLongWord;
  1982. if FDoLogging then begin
  1983. DoLogFmt(' Found %d %s:', [LCount, GetStringForMapiType(AType)]); {Do not localize}
  1984. end;
  1985. if LCount = 0 then begin //Very unlikely, just paranoia
  1986. Exit;
  1987. end;
  1988. if LCount <> 1 then begin
  1989. raise EIdTnefNotSupported.Create('Binary/Object not supported with a count > 1'); {Do not localize}
  1990. end;
  1991. LLength := GetLongWord;
  1992. Result := InternalGetMapiItemAsBytes(LCount, LLength, AType, AText);
  1993. end;
  1994. function TIdCoderTNEF.InternalGetMapiItemAsBytes(ACount, ALength: LongWord; AType: Word; const AText: string): TIdBytes;
  1995. var
  1996. LPos: TIdStreamSize;
  1997. begin
  1998. if FDoLogging then begin
  1999. DoLogFmt(' Item had %d bytes.', [ALength]); {Do not localize}
  2000. end;
  2001. LPos := FData.Position;
  2002. Result := GetBytes(ALength);
  2003. if FDoLogging then begin
  2004. DumpBytes(Result);
  2005. end;
  2006. //Note the bytes are padded to 4-byte boundaries...
  2007. if (ALength mod 4) > 0 then begin
  2008. ALength := ((ALength div 4) + 1) * 4;
  2009. end;
  2010. FData.Position := LPos + ALength;
  2011. if FDoLogging then begin
  2012. DoLogFmt(' ParseMapiProp found %s Bytes, count: %d', [AText, ACount]); {Do not localize}
  2013. end;
  2014. end;
  2015. procedure TIdCoderTNEF.DumpBytes(const ABytes: TIdBytes);
  2016. var
  2017. LIndex: integer;
  2018. LLHS, LRHS: string;
  2019. begin
  2020. LLHS := '';
  2021. LRHS := '';
  2022. for LIndex := 0 to Length(ABytes)-1 do begin
  2023. LLHS := LLHS + GetByteAsHexString(ABytes[LIndex])+' '; {Do not localize}
  2024. LRHS := LRHS + GetByteAsChar(ABytes[LIndex]);
  2025. if ((LIndex+1) mod 16) = 0 then begin
  2026. DoLog(' ' + LLHS + ' ' + LRHS, False); {Do not localize}
  2027. LLHS := '';
  2028. LRHS := '';
  2029. end;
  2030. end;
  2031. if LLHS <> '' then begin
  2032. while Length(LLHS) < 48 do begin
  2033. LLHS := LLHS + ' '; {Do not localize}
  2034. end;
  2035. DoLog(' ' + LLHS + ' ' + LRHS, False); {Do not localize}
  2036. end;
  2037. end;
  2038. procedure TIdCoderTNEF.ParseMapiProp;
  2039. var
  2040. LType, LAttribute: Word;
  2041. LLength, LCount, I: LongWord;
  2042. //LGUIDType: LongWord;
  2043. LShort: Smallint;
  2044. LStr: string;
  2045. LGUID: string;
  2046. LTextPart: TIdText;
  2047. LDate: TDateTime;
  2048. begin
  2049. LType := GetWord;
  2050. LAttribute := GetWord;
  2051. //Initially, just parse out the common attributes and the ones we are interested in.
  2052. if LAttribute >= $8000 then begin
  2053. //A named property: this has a GUID and some other optional stuff...
  2054. LGUID := GetBytesAsHexString(16);
  2055. if FDoLogging then begin
  2056. DoLog(' MAPI item has a named property, GUID: ' + LGUID); {Do not localize}
  2057. end;
  2058. LLength := GetLongWord;
  2059. if LLength = 0 then begin
  2060. //In this case, the named property uses an identifier...
  2061. //TODO: What is the LGUIDType below?
  2062. {LGUIDType :=} GetLongWord;
  2063. end else begin
  2064. //In this case, the named property uses a string...
  2065. //TODO: Following code not tested...
  2066. //Skip strings for now
  2067. LCount := LLength;
  2068. for I := 1 to LCount do begin
  2069. LLength := GetLongWord;
  2070. if LLength = 0 then begin
  2071. Continue;
  2072. end;
  2073. Skip(LLength);
  2074. //Note the strings are padded to 4-byte boundaries...
  2075. if (LLength mod 4) > 0 then begin
  2076. Skip(4 - (LLength mod 4));
  2077. end;
  2078. end;
  2079. end;
  2080. end;
  2081. case LAttribute of
  2082. IdTNEF_PR_ALTERNATE_RECIPIENT_ALLOWED: begin
  2083. {LShort := } GetMapiBoolean(LType, 'ALTERNATE_RECIPIENT_ALLOWED'); {Do not localize}
  2084. end;
  2085. IdTNEF_PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED: begin
  2086. //A delivery receipt, not supported by most systems, implement as a read receipt
  2087. LShort := GetMapiBoolean(LType, 'ORIGINATOR_DELIVERY_REPORT_REQUESTED'); {Do not localize}
  2088. if LShort > 0 then begin
  2089. //Have we already parsed the sender?
  2090. if FMsg.From.Address <> '' then begin
  2091. FMsg.ReceiptRecipient.Address := FMsg.From.Address;
  2092. end else begin
  2093. FReceiptRequested := True;
  2094. end;
  2095. if FDoLogging then begin
  2096. DoLog(' Delivery receipt requested.'); {Do not localize}
  2097. end;
  2098. end else begin
  2099. if FDoLogging then begin
  2100. DoLog(' Delivery receipt not requested.'); {Do not localize}
  2101. end;
  2102. end;
  2103. end;
  2104. IdTNEF_PR_PRIORITY: begin
  2105. {LLong := } GetMapiLong(LType, 'PRIORITY'); {Do not localize}
  2106. end;
  2107. IdTNEF_PR_READ_RECEIPT_REQUESTED: begin
  2108. LShort := GetMapiBoolean(LType, 'READ_RECEIPT_REQUESTED'); {Do not localize}
  2109. if LShort > 0 then begin
  2110. //Have we already parsed the sender?
  2111. if FMsg.From.Address <> '' then begin
  2112. FMsg.ReceiptRecipient.Address := FMsg.From.Address;
  2113. end else begin
  2114. FReceiptRequested := True;
  2115. end;
  2116. if FDoLogging then begin
  2117. DoLog(' Read receipt requested.'); {Do not localize}
  2118. end;
  2119. end else begin
  2120. if FDoLogging then begin
  2121. DoLog(' Read receipt not requested.'); {Do not localize}
  2122. end;
  2123. end;
  2124. end;
  2125. IdTNEF_PR_ORIGINAL_SENSITIVITY: begin
  2126. {LLong := } GetMapiLong(LType, 'ORIGINAL_SENSITIVITY'); {Do not localize}
  2127. end;
  2128. IdTNEF_PR_SENSITIVITY: begin
  2129. {LLong := } GetMapiLong(LType, 'SENSITIVITY'); {Do not localize}
  2130. end;
  2131. IdTNEF_PR_SUBJECT_PREFIX: begin
  2132. {LStr := } GetMapiStrings(LType, 'SUBJECT_PREFIX'); {Do not localize}
  2133. end;
  2134. IdTNEF_PR_ORIGINAL_AUTHOR_NAME: begin
  2135. {LStr := } GetMapiStrings(LType, 'ORIGINAL_AUTHOR_NAME'); {Do not localize}
  2136. end;
  2137. IdTNEF_PR_CONVERSATION_TOPIC: begin
  2138. LStr := GetMapiStrings(LType, 'CONVERSATION_TOPIC'); {Do not localize}
  2139. if FMsg.Subject = '' then begin //Only use this as subject if did not find subject at a higher level
  2140. FMsg.Subject := LStr;
  2141. if FDoLogging then begin
  2142. DoLog(' Message has subject (from CONVERSATION_TOPIC): ' + LStr); {Do not localize}
  2143. end;
  2144. end else begin
  2145. if FDoLogging then begin
  2146. DoLog(' CONVERSATION_TOPIC ignored, already have subject. CONVERSATION_TOPIC: ' + LStr); {Do not localize}
  2147. end;
  2148. end;
  2149. end;
  2150. IdTNEF_PR_CLIENT_SUBMIT_TIME: begin
  2151. LDate := GetMapiSysTime(LType, 'CLIENT_SUBMIT_TIME'); {Do not localize}
  2152. if FMsg.Date = 0 then begin //Only use this as date if did not find date at a higher level
  2153. FMsg.Date := LDate;
  2154. if FDoLogging then begin
  2155. DoLog(' Message has date (from CLIENT_SUBMIT_TIME): ' + DateTimeToStr(LDate)); {Do not localize}
  2156. end;
  2157. end else begin
  2158. if FDoLogging then begin
  2159. DoLog(' CLIENT_SUBMIT_TIME ignored, already have date. CLIENT_SUBMIT_TIME: ' + DateTimeToStr(LDate)); {Do not localize}
  2160. end;
  2161. end;
  2162. end;
  2163. IdTNEF_PR_CONVERSATION_INDEX: begin
  2164. GetMapiBinary(LType, 'CONVERSATION_INDEX'); {Do not localize}
  2165. end;
  2166. IdTNEF_PR_MESSAGE_SUBMISSION_ID: begin
  2167. GetMapiBinary(LType, 'MESSAGE_SUBMISSION_ID'); {Do not localize}
  2168. end;
  2169. IdTNEF_PR_ORIGINAL_SUBJECT: begin
  2170. {LStr :=} GetMapiStrings(LType, 'ORIGINAL_SUBJECT'); {Do not localize}
  2171. end;
  2172. IdTNEF_PR_REPLY_REQUESTED: begin
  2173. {LShort :=} GetMapiBoolean(LType, 'REPLY_REQUESTED'); {Do not localize}
  2174. end;
  2175. IdTNEF_PR_SENDER_SEARCH_KEY: begin
  2176. LStr := GetMapiBinaryAsEmailName(LType, 'SENDER_SEARCH_KEY'); {Do not localize}
  2177. FMsg.From.Address := LStr;
  2178. if FReceiptRequested = True then begin
  2179. FMsg.ReceiptRecipient.Address := FMsg.From.Address;
  2180. end;
  2181. if FDoLogging then begin
  2182. DoLog(' Message sender: ' + LStr); {Do not localize}
  2183. end;
  2184. end;
  2185. IdTNEF_PR_DELETE_AFTER_SUBMIT: begin
  2186. GetMapiBoolean(LType, 'DELETE_AFTER_SUBMIT'); {Do not localize}
  2187. end;
  2188. IdTNEF_PR_MESSAGE_DELIVERY_TIME: begin
  2189. GetMapiSysTime(LType, 'MESSAGE_DELIVERY_TIME'); {Do not localize}
  2190. end;
  2191. IdTNEF_PR_ORIGINAL_SUBMIT_TIME: begin
  2192. GetMapiSysTime(LType, 'ORIGINAL_SUBMIT_TIME'); {Do not localize}
  2193. end;
  2194. IdTNEF_PR_SENTMAIL_ENTRYID: begin
  2195. GetMapiBinary(LType, 'SENTMAIL_ENTRYID'); {Do not localize}
  2196. end;
  2197. IdTNEF_PR_RTF_IN_SYNC: begin
  2198. GetMapiBoolean(LType, 'RTF_IN_SYNC'); {Do not localize}
  2199. end;
  2200. IdTNEF_PR_MAPPING_SIGNATURE: begin
  2201. GetMapiBinary(LType, 'MAPPING_SIGNATURE'); {Do not localize}
  2202. end;
  2203. IdTNEF_PR_STORE_RECORD_KEY: begin
  2204. GetMapiBinary(LType, 'STORE_RECORD_KEY'); {Do not localize}
  2205. end;
  2206. IdTNEF_PR_STORE_ENTRYID: begin
  2207. GetMapiBinary(LType, 'STORE_ENTRYID'); {Do not localize}
  2208. end;
  2209. IdTNEF_PR_ORIGINAL_SENDER_NAME: begin
  2210. LStr := GetMapiStrings(LType, 'ORIGINAL_SENDER_NAME'); {Do not localize}
  2211. if FMsg.From.Address = '' then begin
  2212. FMsg.From.Address := LStr;
  2213. if FDoLogging then begin
  2214. DoLog(' Message has From (from ORIGINAL_SENDER_NAME): ' + LStr); {Do not localize}
  2215. end;
  2216. end else begin
  2217. if FDoLogging then begin
  2218. DoLog(' ORIGINAL_SENDER_NAME ignored, already have From. ORIGINAL_SENDER_NAME: ' + LStr); {Do not localize}
  2219. end;
  2220. end;
  2221. if FDoLogging then begin
  2222. DoLog(' Message From: ' + FMsg.From.Address); {Do not localize}
  2223. end;
  2224. end;
  2225. IdTNEF_PR_ORIGINAL_SENDER_ENTRYID: begin
  2226. GetMapiBinary(LType, 'ORIGINAL_SENDER_ENTRYID'); {Do not localize}
  2227. end;
  2228. IdTNEF_PR_ORIGINAL_SENDER_SEARCH_KEY: begin
  2229. GetMapiBinary(LType, 'ORIGINAL_SENDER_SEARCH_KEY'); {Do not localize}
  2230. end;
  2231. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_NAME: begin
  2232. GetMapiStrings(LType, 'ORIGINAL_SENT_REPRESENTING_NAME'); {Do not localize}
  2233. end;
  2234. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_ENTRYID: begin
  2235. GetMapiBinary(LType, 'ORIGINAL_SENT_REPRESENTING_ENTRYID'); {Do not localize}
  2236. end;
  2237. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY: begin
  2238. GetMapiBinary(LType, 'ORIGINAL_SENT_REPRESENTING_SEARCH_KEY'); {Do not localize}
  2239. end;
  2240. IdTNEF_PR_ORIGINAL_SENDER_ADDRTYPE: begin
  2241. GetMapiStrings(LType, 'ORIGINAL_SENDER_ADDRTYPE'); {Do not localize}
  2242. end;
  2243. IdTNEF_PR_ORIGINAL_SENDER_EMAIL_ADDRESS: begin
  2244. GetMapiStrings(LType, 'ORIGINAL_SENDER_EMAIL_ADDRESS'); {Do not localize}
  2245. end;
  2246. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE: begin
  2247. GetMapiStrings(LType, 'ORIGINAL_SENT_REPRESENTING_ADDRTYPE'); {Do not localize}
  2248. end;
  2249. IdTNEF_PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS: begin
  2250. GetMapiStrings(LType, 'ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS'); {Do not localize}
  2251. end;
  2252. IdTNEF_PR_SENDER_NAME: begin
  2253. GetMapiStrings(LType, 'SENDER_NAME'); {Do not localize}
  2254. end;
  2255. IdTNEF_PR_NORMALIZED_SUBJECT: begin
  2256. GetMapiStrings(LType, 'NORMALIZED_SUBJECT'); {Do not localize}
  2257. end;
  2258. IdTNEF_PR_ORIGINAL_DISPLAY_CC: begin
  2259. GetMapiStrings(LType, 'ORIGINAL_DISPLAY_CC'); {Do not localize}
  2260. end;
  2261. IdTNEF_PR_ORIGINAL_DISPLAY_TO: begin
  2262. GetMapiStrings(LType, 'ORIGINAL_DISPLAY_TO'); {Do not localize}
  2263. end;
  2264. IdTNEF_PR_OBJECT_TYPE: begin
  2265. {LLong := } GetMapiLong(LType, 'OBJECT_TYPE'); {Do not localize}
  2266. end;
  2267. IdTNEF_PR_STORE_SUPPORT_MASK: begin
  2268. {LLong := } GetMapiLong(LType, 'STORE_SUPPORT_MASK'); {Do not localize}
  2269. end;
  2270. IdTNEF_PR_TNEF_CORRELATION_KEY: begin
  2271. LStr := GetMapiBinaryAsString(LType, 'CORRELATION_KEY'); {Do not localize}
  2272. if FMsg.MsgId = '' then begin
  2273. FMsg.MsgId := LStr;
  2274. if FDoLogging then begin
  2275. DoLog(' Message has message ID (from CORRELATION_KEY): ' + LStr); {Do not localize}
  2276. end;
  2277. end else begin
  2278. if FDoLogging then begin
  2279. DoLog(' CORRELATION_KEY ignored, already have message ID. CORRELATION_KEY: ' + LStr); {Do not localize}
  2280. end;
  2281. end;
  2282. if FDoLogging then begin
  2283. DoLog(' Message ID: ' + FMsg.MsgId); {Do not localize}
  2284. end;
  2285. end;
  2286. IdTNEF_PR_RTF_SYNC_BODY_CRC: begin
  2287. {LLong := } GetMapiLong(LType, 'RTF_SYNC_BODY_CRC'); {Do not localize}
  2288. end;
  2289. IdTNEF_PR_RTF_SYNC_BODY_COUNT: begin
  2290. {LLong := } GetMapiLong(LType, 'RTF_SYNC_BODY_COUNT'); {Do not localize}
  2291. end;
  2292. IdTNEF_PR_RTF_SYNC_BODY_TAG: begin
  2293. {LStr :=} GetMapiStrings(LType, 'RTF_SYNC_BODY_TAG'); {Do not localize}
  2294. end;
  2295. IdTNEF_PR_BODY: begin
  2296. LStr := GetMapiStrings(LType, 'BODY'); {Do not localize}
  2297. FMsg.Body.Text := LStr;
  2298. end;
  2299. IdTNEF_PR_RTF_COMPRESSED: begin
  2300. LStr := GetMapiBinaryAsString(LType, 'RTF_COMPRESSED'); {Do not localize}
  2301. //Add this as a TIdText part of type text/rtf...
  2302. LTextPart := TIdText.Create(FMsg.MessageParts);
  2303. LTextPart.ContentType := 'text/rtf'; {Do not localize}
  2304. LTextPart.Body.Text := LStr;
  2305. end;
  2306. IdTNEF_PR_RTF_SYNC_PREFIX_COUNT: begin
  2307. {LLong := } GetMapiLong(LType, 'RTF_SYNC_PREFIX_COUNT'); {Do not localize}
  2308. end;
  2309. IdTNEF_PR_RTF_SYNC_TRAILING_COUNT: begin
  2310. {LLong := } GetMapiLong(LType, 'RTF_SYNC_TRAILING_COUNT'); {Do not localize}
  2311. end;
  2312. IdTNEF_PR_ORIGINALLY_INTENDED_RECIP_ENTRYID: begin
  2313. GetMapiBinary(LType, 'ORIGINALLY_INTENDED_RECIP_ENTRYID'); {Do not localize}
  2314. end;
  2315. else
  2316. //For the types we are not interested in, skip past them...
  2317. case LType of
  2318. IdTNEF_PT_BOOLEAN,
  2319. IdTNEF_PT_LONG,
  2320. IdTNEF_PT_I2,
  2321. IdTNEF_PT_R4,
  2322. IdTNEF_PT_ERROR,
  2323. IdTNEF_PT_APPTIME: begin
  2324. if FDoLogging then begin
  2325. DoLogFmt(' Skipping MAPI attribute 0x%x of type %s', [LAttribute, GetStringForMapiType(LType)]); {Do not localize}
  2326. end;
  2327. Skip(4); //Only 2 bytes used, but padded to 4
  2328. end;
  2329. IdTNEF_PT_BINARY,
  2330. IdTNEF_PT_OBJECT: begin
  2331. if FDoLogging then begin
  2332. DoLogFmt(' Skipping MAPI attribute 0x%x of type %s', [LAttribute, GetStringForMapiType(LType)]); {Do not localize}
  2333. end;
  2334. GetMapiItemAsBytes(LType, 'ignored data');
  2335. end;
  2336. IdTNEF_PT_UNICODE,
  2337. IdTNEF_PT_STRING8: begin
  2338. if FDoLogging then begin
  2339. DoLogFmt(' Skipping MAPI attribute 0x%x of type %s', [LAttribute, GetStringForMapiType(LType)]); {Do not localize}
  2340. end;
  2341. GetMapiStrings(LType, 'ignored data');
  2342. end;
  2343. IdTNEF_PT_SYSTIME,
  2344. IdTNEF_PT_DOUBLE,
  2345. IdTNEF_PT_I8,
  2346. IdTNEF_PT_CURRENCY: begin
  2347. if FDoLogging then begin
  2348. DoLogFmt(' Skipping MAPI attribute 0x%x of type %s', [LAttribute, GetStringForMapiType(LType)]); {Do not localize}
  2349. end;
  2350. Skip(8);
  2351. end;
  2352. else
  2353. raise EIdTnefUnknownMapiType.CreateFmt('Encountered unknown MAPI type: %d, attribute: %d', [LType, LAttribute]); {Do not localize}
  2354. end;
  2355. end;
  2356. end;
  2357. procedure TIdCoderTNEF.ParseMapiProps(ALength: LongWord);
  2358. var
  2359. LNumEntries: LongWord;
  2360. LIndex: LongWord;
  2361. begin
  2362. if FDoLogging then begin
  2363. DoLogFmt(' Parsing MAPI block, %d bytes.', [ALength]); {Do not localize}
  2364. end;
  2365. LNumEntries := GetLongWord;
  2366. if FDoLogging then begin
  2367. DoLogFmt(' Contains %d entries.', [LNumEntries]); {Do not localize}
  2368. end;
  2369. if LNumEntries > 0 then begin
  2370. for LIndex := 0 to LNumEntries-1 do begin
  2371. if FDoLogging then begin
  2372. DoLogFmt(' Entry %d:', [LIndex]); {Do not localize}
  2373. end;
  2374. ParseMapiProp;
  2375. end;
  2376. end;
  2377. end;
  2378. procedure TIdCoderTNEF.ParseAttribute(AAttribute, AType: Word);
  2379. var
  2380. LLength: LongWord;
  2381. LMajor, LMinor: Word;
  2382. LShort: Smallint;
  2383. begin
  2384. LLength := GetLongWord;
  2385. Checksum(LLength);
  2386. case AAttribute of
  2387. IdTNEFattTnefVersion: begin
  2388. if AType <> IdTNEFAtpDWord then begin
  2389. raise EIdTnefUnexpectedType.Create('Expected DWord for TnefVersion'); {Do not localize}
  2390. end;
  2391. LMinor := GetWord;
  2392. LMajor := GetWord;
  2393. if FDoLogging then begin
  2394. DoLogFmt(' ParseAttribute found TNef Version DWord. Major version: %d Minor version: %d', [LMajor, LMinor]); {Do not localize}
  2395. end;
  2396. if (LMajor <> 1) and (LMinor <> 0) then begin
  2397. if FDoLogging then begin
  2398. DoLog(' Expected a version with Major = 1, Minor = 0. Some elements may not parse correctly.'); {Do not localize}
  2399. end;
  2400. end else begin
  2401. if FDoLogging then begin
  2402. DoLog(' This is the expected version.'); {Do not localize}
  2403. end;
  2404. end;
  2405. end;
  2406. IdTNEFattSubject: begin
  2407. if AType <> IdTNEFAtpString then begin
  2408. raise EIdTnefUnexpectedType.Create('Expected String for TnefSubject'); {Do not localize}
  2409. end;
  2410. FMsg.Subject := GetString(LLength);
  2411. if FDoLogging then begin
  2412. DoLog(' ParseAttribute found TNef Subject String: ' + FMsg.Subject); {Do not localize}
  2413. DoLog(' Message has subject: ' + FMsg.Subject); {Do not localize}
  2414. end;
  2415. end;
  2416. IdTNEFattDateSent: begin
  2417. if AType <> IdTNEFAtpDate then begin
  2418. raise EIdTnefUnexpectedType.Create('Expected Date for TnefDateSent'); {Do not localize}
  2419. end;
  2420. FMsg.Date := GetDate(LLength);
  2421. if FDoLogging then begin
  2422. DoLog(' ParseAttribute found TNef Date Sent.'); {Do not localize}
  2423. DoLog(' Message has date: ' + DateTimeToStr(FMsg.Date)); {Do not localize}
  2424. end;
  2425. end;
  2426. IdTNEFattMessageID: begin
  2427. if AType <> IdTNEFAtpString then begin
  2428. raise EIdTnefUnexpectedType.Create('Expected String for TnefMessageID'); {Do not localize}
  2429. end;
  2430. FMsg.MsgId := GetString(LLength);
  2431. if FDoLogging then begin
  2432. DoLog(' ParseAttribute found TNef Message ID.'); {Do not localize}
  2433. DoLog(' Message has ID: ' + FMsg.MsgId); {Do not localize}
  2434. end;
  2435. end;
  2436. IdTNEFattPriority: begin
  2437. if AType <> IdTNEFAtpShort then begin
  2438. raise EIdTnefUnexpectedType.Create('Expected Short for TnefPriority'); {Do not localize}
  2439. end;
  2440. LShort := GetWord;
  2441. if FDoLogging then begin
  2442. DoLog(' ParseAttribute found Priority Short.'); {Do not localize}
  2443. end;
  2444. case LShort of
  2445. IdTNEFprioLow: begin
  2446. FMsg.Priority := mpLow;
  2447. if FDoLogging then begin
  2448. DoLog(' Message has low priority.'); {Do not localize}
  2449. end;
  2450. end;
  2451. IdTNEFprioNorm: begin
  2452. FMsg.Priority := mpNormal;
  2453. if FDoLogging then begin
  2454. DoLog(' Message has normal priority.'); {Do not localize}
  2455. end;
  2456. end;
  2457. IdTNEFprioHigh: begin
  2458. FMsg.Priority := mpHigh;
  2459. if FDoLogging then begin
  2460. DoLog(' Message has high priority.'); {Do not localize}
  2461. end;
  2462. end;
  2463. else
  2464. raise EIdTnefUnexpectedValue.Create('Unexpected value for priority.'); {Do not localize}
  2465. end;
  2466. end;
  2467. IdTNEFattMAPIProps: begin
  2468. ParseMapiProps(LLength);
  2469. end;
  2470. else
  2471. case AType of
  2472. IdTNEFAtpTriples: begin
  2473. if FDoLogging then begin
  2474. DoLogFmt(' ParseAttribute found AtpTriples type, %s, length: %d', {Do not localize}
  2475. [GetStringForAttribute(AAttribute), LLength]);
  2476. end;
  2477. Skip(LLength);
  2478. end;
  2479. IdTNEFAtpString: begin
  2480. if FDoLogging then begin
  2481. DoLogFmt(' ParseAttribute found AtpString type, %s, length: %d', {Do not localize}
  2482. [GetStringForAttribute(AAttribute), LLength]);
  2483. end;
  2484. Skip(LLength);
  2485. end;
  2486. IdTNEFAtpText: begin
  2487. if FDoLogging then begin
  2488. DoLogFmt(' ParseAttribute found AtpText type, %s, length: %d', {Do not localize}
  2489. [GetStringForAttribute(AAttribute), LLength]);
  2490. end;
  2491. Skip(LLength);
  2492. end;
  2493. IdTNEFAtpDate: begin
  2494. if FDoLogging then begin
  2495. DoLogFmt(' ParseAttribute found AtpDate type, %s, length: %d', {Do not localize}
  2496. [GetStringForAttribute(AAttribute), LLength]);
  2497. end;
  2498. Skip(LLength);
  2499. end;
  2500. IdTNEFAtpShort: begin
  2501. if FDoLogging then begin
  2502. DoLogFmt(' ParseAttribute found AtpShort type, %s, length: %d', [GetStringForAttribute(AAttribute), LLength]); {Do not localize}
  2503. end;
  2504. Skip(LLength);
  2505. end;
  2506. IdTNEFAtpLong: begin
  2507. if FDoLogging then begin
  2508. DoLogFmt(' ParseAttribute found AtpLong type, %s, length: %d', {Do not localize}
  2509. [GetStringForAttribute(AAttribute), LLength]);
  2510. end;
  2511. Skip(LLength);
  2512. end;
  2513. IdTNEFAtpByte: begin
  2514. if FDoLogging then begin
  2515. DoLogFmt(' ParseAttribute found AtpByte type, %s, length: %d', {Do not localize}
  2516. [GetStringForAttribute(AAttribute), LLength]);
  2517. end;
  2518. Skip(LLength);
  2519. end;
  2520. IdTNEFAtpWord: begin
  2521. if FDoLogging then begin
  2522. DoLogFmt(' ParseAttribute found AtpWord type, %s, length: %d', {Do not localize}
  2523. [GetStringForAttribute(AAttribute), LLength]);
  2524. end;
  2525. Skip(LLength);
  2526. end;
  2527. IdTNEFAtpDWord: begin
  2528. if FDoLogging then begin
  2529. DoLogFmt(' ParseAttribute found AtpDWord type, %s, length: %d', {Do not localize}
  2530. [GetStringForAttribute(AAttribute), LLength]);
  2531. end;
  2532. Skip(LLength);
  2533. end;
  2534. IdTNEFAtpMax: begin
  2535. if FDoLogging then begin
  2536. DoLogFmt(' ParseAttribute found AtpMax type, %s, length: %d', {Do not localize}
  2537. [GetStringForAttribute(AAttribute), LLength]);
  2538. end;
  2539. Skip(LLength);
  2540. end;
  2541. else
  2542. if FDoLogging then begin
  2543. DoLogFmt(' ParseAttribute found unknown type, %s, length: %d', {Do not localize}
  2544. [GetStringForAttribute(AAttribute), LLength]);
  2545. end;
  2546. Skip(LLength);
  2547. end;
  2548. end;
  2549. Skip(2); //Checksum
  2550. end;
  2551. procedure TIdCoderTNEF.Parse(const AIn: TStream; AMsg: TIdMessage; ALog: Boolean = False);
  2552. var
  2553. LdwTemp: LongWord;
  2554. LBlockType: Byte;
  2555. begin
  2556. FLog := '';
  2557. FDoLogging := ALog;
  2558. FMsg := AMsg;
  2559. FMsg.Clear;
  2560. FMsg.ContentType := 'multipart/mixed'; //Default: improve on this at a later stage.
  2561. FReceiptRequested := False;
  2562. FCurrentAttachment := nil;
  2563. FData := AIn;
  2564. if FDoLogging then begin
  2565. DoLogFmt('Bytes in TNEF: %d', [FData.Size - FData.Position], False); {Do not localize}
  2566. end;
  2567. //Check for a valid TNEF signature...
  2568. LdwTemp := GetLongWord;
  2569. if LdwTemp <> IdTNEFSignature then begin
  2570. if FDoLogging then begin
  2571. DoLog('Invalid TNEF signature', False); {Do not localize}
  2572. end;
  2573. raise EIdTnefInvalidTNEFSignature.Create('Invalid TNEF signature'); {Do not localize}
  2574. end;
  2575. FKey := GetWord;
  2576. if FDoLogging then begin
  2577. DoLogFmt('Key: %d' + EOL + 'Bytes left plus message:', [FKey], False); {Do not localize}
  2578. end;
  2579. repeat
  2580. LBlockType := GetByte;
  2581. case LBlockType of
  2582. IdTNEFLvlMessage: begin
  2583. if FDoLogging then begin
  2584. DoLog(' Calling ParseMessageBlock:'); {Do not localize}
  2585. end;
  2586. ParseMessageBlock;
  2587. end;
  2588. IdTNEFLvlAttachment: begin
  2589. if FDoLogging then begin
  2590. DoLog(' Calling ParseAttachmentBlock:'); {Do not localize}
  2591. end;
  2592. ParseAttachmentBlock;
  2593. end;
  2594. else
  2595. begin
  2596. if FDoLogging then begin
  2597. DoLogFmt(' Hit unknown block type: %d', [LBlockType]); {Do not localize}
  2598. end;
  2599. raise EIdTnefUnknownBlockType.Create('Hit unknown block type in TNEF - corrupt TNEF?'); {Do not localize}
  2600. end;
  2601. end;
  2602. until FData.Position >= FData.Size;
  2603. if FDoLogging then begin
  2604. DoLog(' Finished processing TNEF.'); {Do not localize}
  2605. end;
  2606. end;
  2607. end.