IdCoderTNEF.pas 121 KB

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