home *** CD-ROM | disk | FTP | other *** search
/ BUG 4 / BUGCD1997_05.BIN / aplic / clip4win / clip4win.exe / C4W30E.HUF / SOURCE / CONTRIB / MAPI.ZIP / MAPI.PRG < prev   
Text File  |  1995-10-17  |  11KB  |  379 lines

  1. ////////////////////
  2. //
  3. //    mapi.prg - Messaging API Sample
  4. //
  5. //    Written by:    John M. Skelton,  12-Jan-95.
  6. //
  7. //    Copyright (C) 1995 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
  8. //    All Rights Reserved.
  9. //
  10. ////////////////////
  11.  
  12.  
  13. #include "windows.ch"
  14. #include "mapi.ch"
  15. #define    NO_C4WCLASS
  16. #include "commands.ch"
  17. #include "dll.ch"
  18.  
  19.  
  20. #define    GETBUF(n)    replicate(chr(0), n)
  21.  
  22.  
  23. #ifdef TESTING
  24.  
  25. static    hMAPI
  26.  
  27.  
  28. function main_mapi()
  29. local    hApp, hWnd, hDLL
  30.  
  31. hDLL = LoadLibrary("MAPI.DLL")
  32.  
  33. CREATE APPLICATION hApp  WINDOW hWnd  TITLE "Clip-4-Win MAPI Test"    ;
  34.     ON INIT MenuSetup(hWnd)                        ;
  35.     ON EXIT FreeLibrary(hDLL)
  36.  
  37. if IsWindow(hWnd)
  38.     DestroyWindow(hWnd)
  39. endif
  40. return 0
  41.  
  42.  
  43. static function DoLogon(hWnd)
  44. local    nRet
  45. // Make the user login (sets hMAPI, required in future MAPI calls).
  46. // Note: using 0 instead of hWnd makes the dialog application modal, so
  47. //       you might prefer to use 0.
  48. // Also: the MAPI_FORCE_DOWNLOAD is only needed if you want to read mail
  49. //       and in date/time order.
  50. if (nRet := MAPILogon(hWnd, "", "",                    ;
  51.                       MAPI_LOGON_UI + MAPI_NEW_SESSION, ;
  52. ;//                      MAPI_LOGON_UI + MAPI_FORCE_DOWNLOAD, ;
  53.                       @hMAPI)) != SUCCESS_SUCCESS
  54.     ? "Login failed.  Error code =", nRet
  55.     wait
  56.     quit
  57. endif
  58. //? "hMAPI", hMAPI
  59. return nil
  60.  
  61.  
  62. static function DoLogoff(hWnd)
  63. MAPILogoff(hMAPI, 0, 0, 0)
  64. return nil
  65.  
  66.  
  67. static function DoSend(hWnd, cFilePath)
  68. local    cFile := substr(cFilePath, rat("\", cFilePath) + 1)
  69. SendDocs(cFilePath, cFile)
  70. return nil
  71.  
  72.  
  73. static function DoReadMail(hWnd)
  74. local    nRet, cCurMsgId := GETBUF(256), cMsgId := GETBUF(256)
  75. local    aMsg    // MAPI Message structure (see MAPI.CH)
  76.  
  77. //do while (nRet := MAPIFindNext(hMAPI, hWnd, , @cCurMsgId, 0,    ;
  78. do while (nRet := MAPIFindNext(hMAPI, 0, "", cCurMsgId, MAPI_GUARANTEE_FIFO,;
  79.                                0, @cMsgId)) == SUCCESS_SUCCESS
  80.     if (nRet := MAPIReadMail(hMAPI, 0, cMsgId,            ;
  81.                              MAPI_PEEK + MAPI_ENVELOPE_ONLY,    ;
  82.                              @aMsg)) == SUCCESS_SUCCESS
  83.         // got a msg header
  84.  
  85.         // Process the aMsg...
  86.         ? "Subject: ", aMsg[MAPI_Subject]
  87.  
  88.     elseif nRet != MAPI_E_NO_MESSAGES
  89.         ? "nRet =", nRet
  90.     endif
  91.     cCurMsgId = cMsgId
  92. enddo
  93. //? "nRet =", nRet
  94. return nil
  95.  
  96.  
  97. static function MenuSetup(hWnd)
  98. static    cFile
  99.  
  100. MENU IN hWnd
  101.     POPUP "&File"
  102.         MENUITEM "&Choose..."    ACTION cFile := GetOpenFileName(hWnd, "*.*", "Set File Name")
  103.         MENUITEM "&Send"    ACTION DoSend(hWnd, iif(empty(cFile), "", cFile))
  104.         MENUITEM SEPARATOR
  105.         MENUITEM "E&xit"    ACTION PostQuitMessage(0)
  106.     ENDPOPUP
  107.     POPUP "&MAPI"
  108.         MENUITEM "&Logon"    ACTION DoLogon(hWnd)
  109.         MENUITEM "&Read Mail"    ACTION DoReadMail(hWnd)
  110.         MENUITEM "Log&off"    ACTION DoLogoff(hWnd)
  111.     ENDPOPUP
  112.     POPUP "&Help"
  113.         MENUITEM "&About"    ACTION MessageBox(hWnd, "By John Skelton", "Clip-4-Win MAPI Test")
  114.     ENDPOPUP
  115. ENDMENU
  116. return nil
  117.  
  118. #endif // TESTING
  119.  
  120.  
  121. // Convert one MapiRecipDesc array to C structure
  122.  
  123. function aRecip2cRecip(aRecip, aToFree)        // --> cRecip
  124. local    a := aclone(aRecip)
  125. local    cDesc
  126.  
  127. a[MAPI_Rsvd]    = 0
  128. //a[MAPI_RecipClass] should be ok
  129. a[MAPI_Name]    = Str2Ptr(aRecip[MAPI_Name])
  130. a[MAPI_Address] = Str2Ptr(aRecip[MAPI_Address])
  131. //a[MAPI_EIDSize] should be ok
  132. a[MAPI_EntryID] = Bin2Ptr(aRecip[MAPI_EntryID])  // not printable
  133.  
  134. cDesc = A2Bin(a, MAPI_RECIP_STRUCT_DEF)
  135.  
  136. aadd(aToFree, a[MAPI_Name])
  137. aadd(aToFree, a[MAPI_Address])
  138. aadd(aToFree, a[MAPI_EntryID])
  139.  
  140. return cDesc
  141.  
  142.  
  143. // Convert array of MapiRecipDesc arrays to C structure
  144.  
  145. function aaRecip2cRecip(aaRecip, aToFree)    // --> cRecip
  146. local    cDesc
  147.  
  148. if valtype(aaRecip) == "A"
  149.     if valtype(aaRecip[1]) == "A"
  150.         // good - looks like an array of arrays
  151.         cDesc = ""
  152.         aeval(aaRecip, {|a| cDesc += aRecip2cRecip(a, aToFree)})
  153.     else
  154.         // not so good - hope it's a single structure
  155.         cDesc = aRecip2cRecip(aaRecip, aToFree)
  156.     endif
  157. else
  158.     // better be nil!
  159. endif
  160. return cDesc
  161.  
  162.  
  163. // Convert MapiFileDesc array to C structure
  164.  
  165. function aFile2cFile(aFile, aToFree)    // --> cFile
  166. local    a := aclone(aFile)
  167. local    cDesc
  168.  
  169. a[MAPI_Rsvd]     = 0
  170. //a[MAPI_FFlags] should be ok
  171. //a[MAPI_Position] should be ok
  172. a[MAPI_PathName] = Str2Ptr(aFile[MAPI_PathName])
  173. a[MAPI_FileName] = Str2Ptr(aFile[MAPI_FileName])
  174. a[MAPI_FileType] = 0
  175.  
  176. cDesc = A2Bin(a, MAPI_FILE_STRUCT_DEF)
  177.  
  178. aadd(aToFree, a[MAPI_PathName])
  179. aadd(aToFree, a[MAPI_FileName])
  180.  
  181. return cDesc
  182.  
  183.  
  184. // Convert array of MapiFileDesc arrays to C structure
  185.  
  186. function aaFile2cFile(aaFile, aToFree)    // --> cFile
  187. local    cDesc
  188.  
  189. if valtype(aaFile) == "A"
  190.     if valtype(aaFile[1]) == "A"
  191.         // good - looks like an array of arrays
  192.         cDesc = ""
  193.         aeval(aaFile, {|a| cDesc += aFile2cFile(a, aToFree)})
  194.     else
  195.         // not so good - hope it's a single structure
  196.         cDesc = aFile2cFile(aaFile, aToFree)
  197.     endif
  198. else
  199.     // better be nil!
  200. endif
  201. return cDesc
  202.  
  203.  
  204. // Convert MapiMessage array to C structure
  205.  
  206. function aMsg2cMsg(aMsg, aToFree)    // --> cMsg
  207. local    a := aclone(aMsg)
  208. local    cMsg
  209.  
  210. a[MAPI_Rsvd]       = 0
  211. a[MAPI_Subject]    = Str2Ptr(aMsg[MAPI_Subject])
  212. a[MAPI_NoteText]   = Str2Ptr(aMsg[MAPI_NoteText])
  213. a[MAPI_MsgType]    = Str2Ptr(aMsg[MAPI_MsgType])
  214. a[MAPI_DateRcvd]   = Str2Ptr(aMsg[MAPI_DateRcvd])
  215. a[MAPI_ConvId]     = Str2Ptr(aMsg[MAPI_ConvId])
  216. //a[MAPI_Flags] should be ok
  217. a[MAPI_Originator] = Str2Ptr(aaRecip2cRecip(aMsg[MAPI_Originator], aToFree))
  218. //a[MAPI_RecipCount] should be ok
  219. a[MAPI_Recips]     = Str2Ptr(aaRecip2cRecip(aMsg[MAPI_Recips], aToFree))
  220. //a[MAPI_FileCount] should be ok
  221. a[MAPI_Files]      = Str2Ptr(aaFile2cFile(aMsg[MAPI_Files], aToFree))
  222.  
  223. cMsg = A2Bin(a, MAPI_MSG_STRUCT_DEF)
  224.  
  225. aadd(aToFree, a[MAPI_Subject])
  226. aadd(aToFree, a[MAPI_NoteText])
  227. aadd(aToFree, a[MAPI_MsgType])
  228. aadd(aToFree, a[MAPI_DateRcvd])
  229. aadd(aToFree, a[MAPI_ConvId])
  230. aadd(aToFree, a[MAPI_Originator])
  231. aadd(aToFree, a[MAPI_Recips])
  232. aadd(aToFree, a[MAPI_Files])
  233.  
  234. return cMsg
  235.  
  236.  
  237. // WARNING: GetProcAddress() understands LPSTR and LPVOID, but not most LP* types
  238. //          So use STR or LPVOID or LPSTR if in doubt.  (It returns NIL if
  239. //          it doesn't like a param.)
  240.  
  241.  
  242. // Logon, and return session handle
  243.  
  244. function MAPILogon(hWnd, cName, cPassword, nFlags, hSession)
  245. local    nPtr := Bin2Ptr(GETBUF(4))    // ptr to space for an LHANDLE (ULONG)
  246. local    nRet, nReserved := 0
  247.  
  248. nRet = _MAPILogon(hWnd, cName, cPassword, nFlags, nReserved, nPtr)
  249.  
  250. if nRet == nil
  251.     MessageBox(hWnd, "MAPI.DLL or another DLL not found!", "MAPI")
  252.     quit
  253. endif
  254.  
  255. // bug in 5.2/5.3: if nRet == SUCCESS_SUCCESS fails if nRet is NIL
  256. if (nRet == SUCCESS_SUCCESS)
  257.     hSession = C4W_PeekL(nPtr)
  258. endif
  259. FreePtr(nPtr)
  260. return nRet
  261.  
  262.  
  263. // This one needs an LPLHANDLE, which needs some effort!
  264.  
  265. _DLL static function _MAPILogon(hWnd AS ULONG, cName AS LPSTR,        ;
  266.                                 cPassword AS LPSTR, nFlags AS ULONG,    ;
  267.                                 nReserved AS ULONG,            ;
  268.                                 nPtr AS DWORD /*LPVOID*/)        ;
  269.                      AS ULONG Pascal:MAPI.MAPILogon
  270.  
  271.  
  272. _DLL function MAPILogoff(hSession AS ULONG, hWnd AS ULONG,        ;
  273.                          nFlags AS ULONG, nReserved AS ULONG)        ;
  274.               AS ULONG Pascal:MAPI.MAPILogoff
  275.  
  276.  
  277.  
  278. // aMsg[1..MAPI_MsgLength] must be set by the caller...
  279.  
  280. function MAPISendMail(hSession, hWnd, aMsg, nFlags, nReserved)
  281. local    aToFree := {}
  282. local    nRet
  283.  
  284. nRet = _MAPISendMail(hSession, hWnd, aMsg2cMsg(aMsg, aToFree), nFlags, nReserved)
  285.  
  286. aeval(aToFree, {|nPtr| FreePtr(nPtr)})    // Warning: Don't forget this!
  287.  
  288. return nRet
  289.  
  290. // This one needs an lpMapiMessage, which needs some effort!
  291.  
  292. _DLL static function _MAPISendMail(hSession AS ULONG, hWnd AS ULONG,    ;
  293.                                    cMsg AS LPVOID,            ;
  294.                                    nFlags AS ULONG, nReserved AS ULONG)    ;
  295.                      AS ULONG Pascal:MAPI.MAPISendMail
  296.  
  297.  
  298. // SendDocs() can be called with no file, to just send a note.
  299. //
  300. // cFilePaths is a list of file path names
  301. //    e.g. "c:\dir1\dir2\NOTES.TXT;d:\dir3\dir4\MYFILE.DOC"
  302. // cFiles is a list of filenames
  303. //    e.g. "NOTES.TXT;MYFILE.DOC"
  304. function SendDocs(cFilePaths, cFiles)
  305. return MAPISendDocuments(0, ";", cFilePaths + chr(0), cFiles + chr(0), 0)
  306.  
  307.  
  308. // nUI should be hWnd or 0:   (note: hSession isn't needed)
  309. _DLL function MAPISendDocuments(nUI AS ULONG, cDelimChar AS LPSTR,    ;
  310.                                 cFilePaths AS LPSTR, cFiles AS LPSTR,    ;
  311.                                 nReserved AS ULONG)            ;
  312.               AS ULONG Pascal:MAPI.MAPISendDocuments
  313.  
  314.  
  315. //_DLL function MAPIResolveName(hSession AS ULONG, hWnd AS ULONG, ...) AS ULONG Pascal:MAPI.MAPIResolveName
  316.  
  317.  
  318. // nUI should be hWnd or 0:
  319. _DLL function MAPIFindNext(hSession AS ULONG, nUI AS ULONG,        ;
  320.                            cMsgType AS LPSTR, cCurMsgId AS LPSTR,    ;
  321.                            nFlags AS ULONG,    ; // MAPI_GUARANTEE_FIFO etc.
  322.                            nReserved AS ULONG,    ; // must be 0
  323.                            cMsgId REF LPSTR)    ; // this is what you want!
  324.               AS ULONG Pascal:MAPI.MAPIFindNext
  325.  
  326.  
  327.  
  328. // cleaned-up version of the MAPIReadMail API function
  329. function MAPIReadMail(hSession,    ; // MAPI session handle from MAPILogon()
  330.                       nUI,    ; // hWnd or 0
  331.                       cMsgId,    ; // the msg you want
  332.                       nFlags,    ; // MAPI_PEEK etc.
  333.                       aMsg)      // msg returned via this!
  334. local    nPtr := Bin2Ptr(GETBUF(4))    // ptr to space for an LPMAPIMESSAGE
  335. local    nRet, nPtrMAPIMsg, cMAPIMsg
  336.  
  337. default nUI to 0
  338.  
  339. nRet = _MAPIReadMail(hSession, nUI, cMsgId, nFlags, 0, nPtr)
  340. // nPtr is now a pointer to the MAPIMessage structure
  341.  
  342. nPtrMAPIMsg = C4W_PeekL(nPtr)
  343. cMAPIMsg = C4W_Peek(nPtrMAPIMsg, 4 * 12)    // 12 ULONG's
  344. aMsg = Bin2A(cMAPIMsg, MAPI_MSG_STRUCT_DEF)
  345.  
  346. // now aMsg is 12 ULONG's - not much help!
  347.  
  348. // convert the ULONG's which are really LPSTR's
  349. //aMsg[MAPI_Rsvd]     = 0
  350. aMsg[MAPI_Subject]    = C4W_Peek(aMsg[MAPI_Subject])
  351. aMsg[MAPI_NoteText]   = C4W_Peek(aMsg[MAPI_NoteText])
  352. aMsg[MAPI_MsgType]    = C4W_Peek(aMsg[MAPI_MsgType])
  353. aMsg[MAPI_DateRcvd]   = C4W_Peek(aMsg[MAPI_DateRcvd])
  354. aMsg[MAPI_ConvId]     = C4W_Peek(aMsg[MAPI_ConvId])
  355. //aMsg[MAPI_Flags] should be ok
  356. // TBD: aMsg[MAPI_Originator]
  357. //aMsg[MAPI_RecipCount] should be ok
  358. // TBD: aMsg[MAPI_Recips]
  359. //aMsg[MAPI_FileCount] should be ok
  360. // TBD: aMsg[MAPI_Files]
  361.  
  362. FreePtr(nPtrMAPIMsg)
  363. FreePtr(nPtr)
  364. return nRet
  365.  
  366.  
  367. // nUI should be hWnd or 0
  368. // Note: nPtr makes this awkward to use from Clipper (see above)...
  369. _DLL function _MAPIReadMail(hSession AS ULONG, nUI AS ULONG,        ;
  370.                            cMsgId AS LPSTR,    ; // the msg you want
  371.                            nFlags AS ULONG,    ; // MAPI_PEEK etc.
  372.                            nReserved AS ULONG,    ; // must be 0
  373.                            nPtr AS DWORD    ; // msg returned via this!
  374.                            ) AS ULONG Pascal:MAPI.MAPIReadMail
  375.  
  376.  
  377. //_DLL function MAPI(hSession AS ULONG, hWnd AS ULONG, ...) AS ULONG Pascal:MAPI.MAPI
  378.  
  379.