_USING THE MICROSOFT MAIL API_ by Jim Conger Listing One // mapiutil.h header file for mapiutil.cpp, jim conger, 1994 #ifndef MAPIUTIL_H #define MAPIUTIL_H // MAPI function types (from mapi.h prototypes) typedef ULONG (FAR PASCAL *LPMAPILOGON)(ULONG, LPSTR, LPSTR, FLAGS, ULONG, LPLHANDLE); typedef ULONG (FAR PASCAL *LPMAPILOGOFF)(LHANDLE, ULONG, FLAGS, ULONG); typedef ULONG (FAR PASCAL *LPMAPISENDMAIL)(LHANDLE, ULONG, lpMapiMessage, FLAGS, ULONG); typedef ULONG (FAR PASCAL *LPMAPIADDRESS)(LHANDLE, ULONG, LPSTR, ULONG, LPSTR, ULONG, lpMapiRecipDesc, FLAGS, ULONG, LPULONG, lpMapiRecipDesc FAR *); typedef ULONG (FAR PASCAL *LPMAPIREADMAIL)(LHANDLE, ULONG, LPSTR, FLAGS, ULONG, lpMapiMessage FAR *); typedef ULONG (FAR PASCAL *LPMAPIRESOLVENAME)(LHANDLE, ULONG, LPSTR, FLAGS, ULONG, lpMapiRecipDesc FAR *); typedef ULONG (FAR PASCAL *LPMAPIFREEBUFFER)(LPVOID); class CMapiUtil { public: CMapiUtil () ; ~CMapiUtil () ; private: HINSTANCE m_hMAPI ; // handle of MAPI.DLL unsigned long m_MailHandle ; // mail session handle MapiRecipDesc m_MapiRecipDesc ; // defined in MAPI.H ULONG m_lRecipients ; // number of recipients lpMapiRecipDesc m_lpRecipList ; // pointer to list of recips ULONG m_lOldRecipients ; // number of recipients lpMapiRecipDesc m_lpOldRecipList ; // last list of recips lpMapiMessage m_lpMessage ; // message data in memory CStringList m_NameList ; // string list of recipients LPMAPILOGON lpMAPILogon ; // pointers to functions in LPMAPISENDMAIL lpMAPISendMail ; // mapi.dll LPMAPIFREEBUFFER lpMAPIFreeBuffer ; LPMAPILOGOFF lpMAPILogoff ; LPMAPIADDRESS lpMAPIAddress ; LPMAPIREADMAIL lpMAPIReadMail ; LPMAPIRESOLVENAME lpMAPIResolveName ; public: int Logon (CWnd * pWnd) ; int GetAddressList (CWnd * pWnd) ; int GetUpdatedAddressList (CWnd * pWnd) ; void FreeAddressList () ; int SendMessage (CWnd * pWnd, MapiMessage * lpMessage) ; int ReadMessage (CWnd * pWnd, LPSTR lpMessageID) ; void SaveAddressList () ; void FreeMessage () ; void Logoff (CWnd * pWnd) ; char * NoteText () ; int NoteLong () ; } ; #endif // MAPIUTIL_H Listing Two // mapiutil.cpp utility functions for working with mail api, jim conger, 1994 #include "stdafx.h" // used by VC++ for standard MFC includes #include "mapi.h" #include "mailexts.h" #include "mapiutil.h" #include CMapiUtil::CMapiUtil () { TRACE ("\nCMapiUtil constructor") ; m_hMAPI = NULL ; m_MailHandle = NULL ; m_lRecipients = 0 ; m_lpRecipList = NULL ; m_lOldRecipients = 0 ; m_lpOldRecipList = NULL ; m_lpMessage = NULL ; } CMapiUtil::~CMapiUtil () // allows mindless shutdown of mail { TRACE ("\nCMapiUtil destructor") ; if (m_lpOldRecipList != NULL) delete m_lpOldRecipList ; if (m_lpMessage != NULL) (*lpMAPIFreeBuffer) (m_lpMessage) ; if (m_hMAPI != NULL) ::FreeLibrary (m_hMAPI) ; } // Load mapi.dll into memory, get function addresses, and logon // Returns TRUE if session started OK, or zero if on error int CMapiUtil::Logon (CWnd * pWnd) { TRACE ("\nCMapiUtil::Logon ()") ; ULONG lHwnd = (ULONG)(LPSTR) pWnd->GetSafeHwnd () ; m_hMAPI = ::LoadLibrary ("MAPI.DLL") ;// explicitly load MAPI.DLL if (m_hMAPI < HINSTANCE_ERROR) return 0 ; // get address of MAPILogon() lpMAPILogon = (LPMAPILOGON) ::GetProcAddress (m_hMAPI,"MAPILogon") ; if (lpMAPILogon == NULL) return 0 ; // if MAPILogon() was found, assume the other functions can be found lpMAPISendMail = (LPMAPISENDMAIL) ::GetProcAddress (m_hMAPI, "MAPISendMail") ; lpMAPIFreeBuffer = (LPMAPIFREEBUFFER) ::GetProcAddress (m_hMAPI, "MAPIFreeBuffer") ; lpMAPILogoff = (LPMAPILOGOFF) ::GetProcAddress (m_hMAPI, "MAPILogoff") ; lpMAPIAddress = (LPMAPIADDRESS) ::GetProcAddress (m_hMAPI, "MAPIAddress") ; lpMAPIReadMail = (LPMAPIREADMAIL) ::GetProcAddress (m_hMAPI, "MAPIReadMail") ; lpMAPIResolveName = (LPMAPIRESOLVENAME) ::GetProcAddress (m_hMAPI, "MAPIResolveName") ; // open a mail session - does nothing if a session is running ULONG lStatus = (*lpMAPILogon) (lHwnd, NULL, NULL, MAPI_LOGON_UI, 0, (LPLHANDLE) &m_MailHandle) ; if (lStatus != SUCCESS_SUCCESS) return 0 ; else return TRUE ; } // Show empty address dialog box, and get selections from user int CMapiUtil::GetAddressList (CWnd * pWnd) { TRACE ("\nCMapiUtil::GetAddressList ()") ; ULONG lHwnd = (ULONG)(LPSTR) pWnd->GetSafeHwnd () ; long lStatus = (*lpMAPIAddress) ((LHANDLE) m_MailHandle, lHwnd, NULL, 2,NULL, 0, NULL, 0, 0, &m_lRecipients, &m_lpRecipList) ; return (int) lStatus ; } // Show initialized address dialog box, get final selections int CMapiUtil::GetUpdatedAddressList (CWnd * pWnd) { TRACE ("\nCMapiUtil::GetUpdatedAddressList ()") ; ULONG lHwnd = (ULONG)(LPSTR) pWnd->GetSafeHwnd () ; lpMapiRecipDesc lpRD ; if (m_lOldRecipients > 0) // if there is a list of names { if (m_lpOldRecipList != NULL) delete m_lpOldRecipList ; m_lpOldRecipList = new MapiRecipDesc [m_lOldRecipients] ; ASSERT (m_lpOldRecipList) ; lpMapiRecipDesc lpMRD = m_lpOldRecipList ; for (int i = 0 ; i < (int) m_lOldRecipients ; i++) { POSITION pos = m_NameList.FindIndex (i) ; ULONG lStatus = (*lpMAPIResolveName) ( (LHANDLE) m_MailHandle, lHwnd, (LPSTR) (const char *) m_NameList.GetAt (pos), MAPI_DIALOG, 0, &lpRD) ; if (lStatus == SUCCESS_SUCCESS) lpMRD [i] = * lpRD ; // copy recipient data to array else { delete m_lpOldRecipList ; m_lpOldRecipList = NULL ; m_lOldRecipients = 0 ; break ; } } } long lStatus = (*lpMAPIAddress) ((LHANDLE) m_MailHandle, lHwnd, NULL, 2, NULL, m_lOldRecipients, m_lpOldRecipList, 0, 0, &m_lRecipients, &m_lpRecipList) ; return (int) lStatus ; } // free the buffers tied up by the GetUpdatedAddressList() function void CMapiUtil::FreeAddressList () { TRACE ("\nCMapiUtil::FreeAddressList ()") ; if (m_lpOldRecipList != NULL) { delete m_lpOldRecipList ; // delete array holding copies m_lpOldRecipList = NULL ; m_lOldRecipients = 0 ; } } // Send the message, using addresses from GetAddressList() int CMapiUtil::SendMessage (CWnd * pWnd, MapiMessage * lpMessage) { TRACE ("\nCMapiUtil::SendMessage ()") ; ULONG lHwnd = (ULONG)(LPSTR) pWnd->GetSafeHwnd () ; m_MapiRecipDesc.ulReserved = 0 ; m_MapiRecipDesc.ulRecipClass = MAPI_ORIG ; m_MapiRecipDesc.lpszName = "TSR" ; m_MapiRecipDesc.lpszAddress = NULL ; lpMessage->lpOriginator = &m_MapiRecipDesc ; lpMessage->nRecipCount = m_lRecipients ; lpMessage->lpRecips = m_lpRecipList ; long lStatus = (*lpMAPISendMail) ((LHANDLE) m_MailHandle, lHwnd, lpMessage, 0L, 0L) ; return (int) lStatus ; } // Read message identified by lpMessageID, save pointer to message // Returns TRUE if message was read OK, FALSE on error int CMapiUtil::ReadMessage (CWnd * pWnd, LPSTR lpMessageID) { TRACE ("\nCMapiUtil::ReadMessage ()") ; static lpMapiMessage lpMessage ; ULONG lHwnd = (ULONG)(LPSTR) pWnd->GetSafeHwnd () ; if (m_lpMessage != NULL) // make sure last message is purged (*lpMAPIFreeBuffer) (m_lpMessage) ; if (m_lpRecipList != NULL) // and clean up old address list { (*lpMAPIFreeBuffer) (m_lpRecipList) ; m_lpRecipList = NULL ; } m_lRecipients = 0 ; // read the message ULONG lStatus = (*lpMAPIReadMail) (m_MailHandle, lHwnd, lpMessageID, 0L, 0, &lpMessage) ; if (lStatus == SUCCESS_SUCCESS) { m_lpMessage = lpMessage ; // save pointer to message if OK return TRUE ; // and return TRUE } else { m_lpMessage = NULL ; // otherwise, quit and return FALSE return FALSE ; } } // save the names of all recipients in a message for use // in initializing the address dialog box in next mail send void CMapiUtil::SaveAddressList () { TRACE ("\nCMapiUtil::SaveAddressList ()") ; if (m_lpMessage == NULL) return ; m_NameList.RemoveAll () ; // empty the last list (if any) m_lOldRecipients = (long) m_lpMessage->nRecipCount ; // add all of the cc's to the end of the list for (int i = 0 ; i < (int) m_lpMessage->nRecipCount ; i++) { m_NameList.AddTail (m_lpMessage->lpRecips [i].lpszName) ; } } // Free all buffers associated with a message void CMapiUtil::FreeMessage () { TRACE ("\nCMapiUtil::FreeMessage ()") ; if (m_lpMessage != NULL) { (*lpMAPIFreeBuffer) (m_lpMessage) ; m_lpMessage = NULL ; } if (m_lpRecipList != NULL) { (*lpMAPIFreeBuffer) (m_lpRecipList) ; m_lpRecipList = NULL ; m_lRecipients = 0 ; } } // Log off from mail, and release MAPI.DLL void CMapiUtil::Logoff (CWnd * pWnd) { TRACE ("\nCMapiUtil::Logoff ()") ; ULONG lHwnd = (ULONG)(LPSTR) pWnd->GetSafeHwnd () ; if (m_MailHandle != 0) { (*lpMAPILogoff) (m_MailHandle, lHwnd, 0L, 0L) ; m_MailHandle = 0 ; } if (m_hMAPI != NULL) { ::FreeLibrary (m_hMAPI) ; m_hMAPI = NULL ; } } // Returns a pointer to the text of the message, NULL if no message char * CMapiUtil::NoteText () { TRACE ("\nCMapiUtil::NoteText ()") ; if (m_lpMessage != NULL) return m_lpMessage->lpszNoteText ; else return NULL ; } // Returns number of chars in the text of the message, 0 if none int CMapiUtil::NoteLong () { TRACE ("\nCMapiUtil::NoteLong ()") ; if (m_lpMessage != NULL) return ::lstrlen (m_lpMessage->lpszNoteText) ; else return 0 ; } Example 1: int CTsrApp::ReadMessageFromMemory (char * psCmdLine) { // convert the handle from ASCII hex digits to a number HGLOBAL handle = (HGLOBAL) atol_hex (psCmdLine) ; if (handle == 0) return HANDLE_ERROR ; // get ownership of block from APPEXEC.DLL HGLOBAL hMem = GlobalReAlloc (handle, 0, GMEM_MODIFY | GMEM_MOVEABLE | GMEM_SHARE) ; if (hMem == NULL) return HANDLE_ERROR ; // and lock the block to access it's members PARAMBLK * pParamBlk = (PARAMBLK *) GlobalLock (hMem) ; // use the PARAMBLK data in the memory block here... GlobalUnlock (hMem) ; GlobalFree (hMem) ; return 0 ; } Example 2: typedef struct tagPARAMBLK { WORD wVersion; // eg. 0x0300 for ver 3.0 WORD wCommand; // eg. wcommandOpen (def. MAILEXTS.H) LPSTR lpDllCmdLine; // command line string for msg. type LPSTR lpMessageIDList; // array of message identifiers WORD wMessageIDCount; // no. items in lpmessageIDList HWND hwndMail; // the mail window handle HANDLE hinstMail; // the mail instance handle LPSTR lpHelpPath; // the help file name (if any) DWORD hlpID; // the help file context ID } PARAMBLK; Example 3: [Custom Messages] IPM.MailDemo.Demo=3.0;Mail;&Mail Demo...;2;\maildemo\APPEXEC.DLL;\maildemo\maildemo.EXE -m ;1111111000000000;Mail demo application;;; Example 4: MAPI.H typedef struct { ULONG ulReserved; // Reserved (Must be 0) LPSTR lpszSubject; // Message Subject LPSTR lpszNoteText; // Message Text LPSTR lpszMessageType; // Message Class LPSTR lpszDateReceived; // in YYYY/MM/DD HH:MM format LPSTR lpszConversationID; // conversation thread ID FLAGS flFlags; // unread,return receipt lpMapiRecipDesc lpOriginator; // Originator descriptor ULONG nRecipCount; // Number of recipients lpMapiRecipDesc lpRecips; // Recipient descriptors ULONG nFileCount; // # of file attachments lpMapiFileDesc lpFiles; // Attachment descriptors } MapiMessage, FAR * lpMapiMessage; #define MAPI_UNREAD 0x00000001 // flFlags values #define MAPI_RECEIPT_REQUESTED 0x00000002 #define MAPI_SENT 0x00000004 typedef struct { ULONG ulReserved; // Reserved for future use ULONG ulRecipClass; // Recipient class // MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG LPSTR lpszName; // Recipient name LPSTR lpszAddress; // Recipient address (optional) ULONG ulEIDSize; // Count in bytes of size of pEntryID LPVOID lpEntryID; // System-specific recipient reference } MapiRecipDesc, FAR * lpMapiRecipDesc; #define MAPI_ORIG 0 // Recipient is message originator #define MAPI_TO 1 // Recipient is a primary recipient #define MAPI_CC 2 // Recipient is a copy recipient #define MAPI_BCC 3 // Recipient is blind copy recipient Example 5: void CMainFrame::OnMailSendText() { CMapiUtil MapiUtil ; if (MapiUtil.Logon (this)) { if (MapiUtil.GetAddressList (this) == SUCCESS_SUCCESS) { MapiMessage Message ; Message.ulReserved = 0 ; Message.lpszSubject = "Message subject" ; Message.lpszNoteText = "Text of the message." ; Message.lpszMessageType = NULL ; // standard msg. Message.lpszDateReceived = "1994/01/01 12:00" ; Message.lpszConversationID = NULL ; Message.flFlags = MAPI_UNREAD | MAPI_DIALOG ; Message.lpOriginator = NULL; Message.nRecipCount = 0 ; Message.lpRecips = NULL ; Message.nFileCount = 0 ; Message.lpFiles = NULL ; MapiUtil.SendMessage (this, &Message) ; MapiUtil.FreeMessage () ; } MapiUtil.Logoff (this) ; } else MessageBox ("Could not log on to MS Mail.", "Error", MB_ICONEXCLAMATION | MB_OK) ; }