' ' ddoc_map.bas ' ' Microsoft MAPI declarations and wrapper functions for 32-bit PowerBASIC ' PB/DLL 5 and PB/CC ' ' Written by Don Dickinson - ddickinson@basicguru.com ' ' HISTORY ' -------------------------------------------------------- ' July, 1998 Initial release, has support only for ' the MAPISendDocuments Wrapper ... ' > mapiInit ' > mapiCleanup ' > mapiMailFile ' ' Dec, 1998 Added Simple MAPI Wrappers ... ' > smapiLogon ' > smapiLogoff ' > smapiSendMail ' ' -------------------------------------------------------- ' ' Hereby Public Domain. Deemed reliable, but use at your own risk, etc. ' Do with it as you will, provided you hold the author harmless ' from all effects and side-effects of using this code. ' '============================================================================= ' ' Debug Constants '============================================================================= %DEBUG_MAPI_PBCC = 0 %TEST_MAPI_WITH_PBCC = 1 ' ' MAPI Constants '============================================================================= %MAPI_LOGON_UI = &H1 %MAPI_NEW_SESSION = &H2 %MAPI_DIALOG = &H8 %MAPI_UNREAD_ONLY = &H20 %MAPI_ENVELOPE_ONLY = &H40 %MAPI_PEEK = &H80 %MAPI_GUARANTEE_FIFO = &H100 %MAPI_BODY_AS_FILE = &H200 %MAPI_AB_NOMODIFY = &H400 %MAPI_SUPPRESS_ATTACH = &H800 %MAPI_FORCE_DOWNLOAD = &H1000 %MAPI_USE_DEFAULT = &H40 %MAPI_ORIG = 0 %MAPI_TO = 1 %MAPI_CC = 2 %MAPI_BCC = 3 %MAPI_OLE = &H1 %MAPI_OLE_STATIC = &H2 ' ' MAPI Structures '============================================================================= Type MAPIRECIP iReserved As Long iRecipClass As Long lpszName As Asciiz Ptr lpszAddress As Asciiz Ptr iEIDSize As Long lpEntryID As Dword End Type Type MAPIFILEDESC iReserved As Long iFlags As Long iPosition As Long lpszPathName As Asciiz Ptr lpszFileName As Asciiz Ptr lpFileType As Dword End Type Type MAPIMESSAGE iReserved As Long lpszSubject As Asciiz Ptr lpszNoteText As Asciiz Ptr lpszMessageType As Asciiz Ptr lpszDateReceived As Asciiz Ptr lpszConversationID As Asciiz Ptr iFlags As Long lpOriginator As MAPIRECIP Ptr iRecipCount As Long lpRecips As MAPIRECIP Ptr iFileCount As Long lpFiles As MAPIFILEDESC Ptr End Type ' ' Globals '============================================================================= Global gMAPILib As Long Global gFiles() As MAPIFILEDESC Global gRecip() As MAPIRECIP ' ' Function Prototypes '============================================================================= Declare Sub testmapi() Declare Sub mapiCleanup() Declare Function mapiInit() As Long Declare Function mapiMailFile(sFileNames As String, sFilePaths As String) As Long Declare Function smapiLogon(sAccount As String, sPassword As String) As Long Declare Sub smapiLogoff(iSession As Long) Declare Function smapiSendMail( iSession As Long, Subject$, Note$, _ Addresses$, Names$, Files$, iShowDialog As Long) As Long '- The template declaration is necessary to tell power basic how ' to call the function since the dll is loaded into memory at run-time. ' Here is the actual api declaration ... ' ' Declare Function MAPISendDocuments lib "mapi32.dll" _ ' Alias "MAPISendDocuments" (ByVal ulParam As Dword, _ ' zDelimChar As Asciiz, zFilePaths As Asciiz, zFileNames As Asciiz, _ ' ByVal ulReserved As Dword ) As Dword ' Declare Function mapiTemplate_MAPISendDocuments( ByVal hWnd As Long, _ zDelim As Asciiz, _ zFilePaths As Asciiz, _ zFileNames As Asciiz, _ ByVal dwReserved As Dword ) As Dword Declare Function mapiTemplate_MAPISendMail( ByVal iSession As Long, _ ByVal iParam As Dword, _ lpMapiMessage As Any, _ ByVal iFlags As Long, _ ByVal iReserved As Long ) As Long Declare Function mapiTemplate_MAPILogon( ByVal iParam As Long, _ zName As Asciiz, zPW As Asciiz, _ ByVal iFlags As Long, _ ByVal iReserved As Long, _ iSession As Long ) As Long Declare Function mapiTemplate_MAPILogoff( ByVal iSession As Long, _ ByVal iParam As Long, _ ByVal iFlags As Long, _ ByVal iReserved As Long ) As Long $If %TEST_MAPI_WITH_PBCC $Include "win32api.inc" Function PbMain testmapi End Function ' ' testmapi '============================================================================ Sub testmapi() Dim hSession As Long Dim iReturn As Long Dim Names$, Addresses$, Files$ mapiInit '- To use smapiSendMail, we must first get a ' session handle. When done, we log off ' the session with smapiLogoff. If you pass ' "", "" MS Mail will prompt you for the ' mail profile to use. ' ' e.g. ' hSession = smapiLogon("", "") ' hSession = smapiLogon("Microsoft Outlook", "") If hSession Then Print "Session handle =" + Str$(hSession) '- Provide the list of names, addresses, and attachents ' Note that addresses are OPTIONAL, If you are part of an MS Mail ' post office, you can send mail to others in that post office, ' or to people already in your address book, by simply referring ' to them by name. For example, if I want to send Dave, Troy, and Tim ' interoffice, MS Mail email, I can do this ... ' Addresses$ = "" ' Names$ = "Dave;Troy;Tim" ' ' If you're sending to someone whose alias is not in your address book, ' you need to specify both Names and Addresses. If the address is ' an internet address, you also need to indicate the transport for ' the email by putting it in front of the address and following it ' with a semi-colon. E.G. I have the internet mail service installed, ' so I precede addresses with SMTP: to tell ms mail to deliver via the ' internet. ' Names$ = "Don's Fax at the Office" Addresses$ = "FAX:Don's Office@835-3866" ' Files are optional. If you want to attach things to the email, ' then list the files separated by ;'s. If you don't want ' files, just pass "" ' 'Files$ = "c:\code\winsock\test.txt;c:\code\winsock\test.bas;c:\code\winsock\test.fil" Files$ = "c:\code\ddoc\sample.ddc" '- Send the mail iReturn = smapiSendMail( hSession, "Test Email2", "This is a test mapi email", _ Addresses$, Names$, Files$, %True) If iReturn = 0 Then Print "Message Sent" Else Print "smapiSendMail failure error =" + Str$(iReturn) End If smapiLogoff hSession Else '- This can happen if you specify an invalid account name or ' the user hits the cancel button when prompted for ' a mail profile. ' Print "Unable to obtain mapi session handle" End If mapiCleanup End Sub $EndIf ' ' mapiMailFile ' ' Sends a file or list of files. Prompts the user for futher inforamtion ' via a common mapi send mail interface. This always displays a dialog. ' It also logs on and off for you, so you don't need to call the logon ' or initialization functions. If you want to send mail without the ' logon screen, you should use smapiSendMail instead. '============================================================================= Function mapiMailFile(sFileNames As String, sFilePaths As String) As Long Dim iLoadedMAPIHere As Integer Dim zFileNames As Asciiz * 1024 Dim zFilePaths As Asciiz * 1024 Dim ptrMAPISendDocs As Dword zFileNames = sFileNames zFilePaths = sFilePaths '- If mapi wasn't loaded initially, we load it ' in this routine. If it's loaded in this routine, ' then we will also unload it before returning. This ' allows the programmer to initialize the mapi dll ' themselves and it will stay in memory until manually ' removing it with mapiCleanup. Otherwise, this function ' can also be self contained and initialize and cleanup ' after itself automatically. ' iLoadedMAPIHere = %False If gMAPILib = 0 Then iLoadedMAPIHere = %True mapiInit End If If gMAPILib Then ptrMAPISendDocs = GetProcAddress(gMAPILib, "MAPISendDocuments") If ptrMAPISendDocs Then Call Dword ptrMAPISendDocs Using mapiTemplate_MAPISendDocuments(0, ";", zFilePaths, zFileNames, 0) End If If iLoadedMAPIHere Then mapiCleanup End If Else 'Print "Couldn't find MAPI function" End If End Function ' ' mapiInit ' ' Call to load the mapi dll into memory. Returns ' %True if successful, %False if it fails. It also ' sets the Global gMAPIInit variable to be %True ' on success. '============================================================================= Function mapiInit() As Long If gMAPILib = 0 Then gMAPILib = LoadLibrary("mapi32.dll") If gMAPILib = 0 Then Function = %False Else Function = %True End If Else Function = %True End If End Function ' ' mapiCleanup ' ' Call to release the mapi dll's '============================================================================= Sub mapiCleanup() If gMAPILib Then FreeLibrary gMAPILib gMAPILib = 0 End If End Sub ' ' smapiLogon() ' ' Simple Mapi Logon Wrapper Function ' Returns a Session ID or Zero on failure ' If you pass a blank account, it will prompt you for ' mapi logon. If you pass it a valid MAPI user id / password, it ' will logon without a login box. '============================================================================= Function smapiLogon(sAccount As String, sPassword As String) As Long Dim hSession As Long Dim ptrMAPILogon As Dword Dim zAccount As Asciiz * 200 Dim zPW As Asciiz * 200 zAccount = Trim$(sAccount) zPW = Trim$(sPassword) '- Get MAPI DLL in memory if not already there. It is up to the programmer ' to call mapiCleanup to free the stuff loaded by mapiInit. I suggest ' calling mapiInit yourself when your program starts and then mapiCleanup ' when it exits. ' If mapiInit() = %True Then '- Get the procedure's address ptrMAPILogon = GetProcAddress(gMAPILib, "MAPILogon") If ptrMAPILogon Then '- Now that stuff is done, we logon to obtain a mapi session. Call Dword ptrMAPILogon Using mapiTemplate_MAPILogon( 0, zAccount, zPW, %MAPI_LOGON_UI, 0, hSession ) Function = hSession Else '- Couldn't find the procedure's address. Put error handling code here. 'Print "Couldn't get address" Function = 0 End If Else '- Couldn't get the dll (mapi32.dll) in memory. Put error handling code here. Function = 0 'Print "Couldn't Load mapi32.dll" End If End Function ' ' smapiLogoff ' ' Simple MAPI Logoff Function Wrapper ' Takes a session ID and logs off of mapi '============================================================================= Sub smapiLogoff(iSession As Long) Dim ptrMAPILogoff As Dword If gMAPILib <> 0 Then ptrMAPILogoff = GetProcAddress(gMAPILib, "MAPILogoff") If ptrMAPILogoff Then Call Dword ptrMAPILogoff Using mapiTemplate_MAPILogoff( iSession, 0, 0, 0 ) End If End If End Sub ' ' smapiSendMail ' ' This function sends mail without a dialog to the given list of recipients ' and attaches the given list of files. ' ' The parameters are many, so I'll describe them ... ' ' iSession = the session id as returned by smapiLogon ' Subject$ = subject of the email ' Note$ = email text ' Addresses$ = A list of email addresses separated by ;'s Make sure to ' put in the message type preceded by a : if it's not ' being delivered to an MS Mail post office. For example, if ' you're sending mail out to the internet via MS Mail, the ' mail type is SMTP. You will need to preceed the address ' with SMTP: ' e.g. "SMTP:ddickinson@usinternet.com;SMTP:ddickinson@compuserve.com" ' Names$ = A list of ; delimited names that correspond to the addresses above. ' e.g. "Don on US Internet; Don's Compuserve Account" ' Files$ = A list of ; delimited file names (full drive letter, file ' path and file name must be included). If the file doesn't exist ' (Dir$(FileName) = "") then it will be ignored. ' '============================================================================= Function smapiSendMail( iSession As Long, Subject$, Note$, _ Addresses$, Names$, Files$, iShowDialog As Long) As Long Dim i As Long, iReturn As Long Dim iNumFiles As Long, iNum As Long Dim iNumRecips As Long Dim ptrMAPISendMail As Dword Dim rMessage As MAPIMESSAGE Dim zSubject As Asciiz * 1000 Dim zNote As Asciiz * 32768 Dim zTimeStamp As Asciiz * 50 Dim zFiles() As Asciiz * 300 Dim zAddr() As Asciiz * 300 Dim zNames() As Asciiz * 300 zSubject = Trim$(Subject$) zNote = Trim$(Note$) + Chr$(13) + Chr$(10) + Space$(iNumFiles) zTimeStamp = Date$ + " " + Time$ ptrMAPISendMail = GetProcAddress(gMAPILib, "MAPISendMail") If ptrMAPISendMail Then '- Create array of addresses If Trim$(Names$) = "" Then iNumRecips = 0 Else iNumRecips = ParseCount(Names$, ";") End If ReDim zAddr(0 To iNumRecips) As Asciiz * 300 ReDim zNames(0 To iNumRecips) As Asciiz * 300 ReDim gRecip(0 To iNumRecips) '- Fill the address information $If %DEBUG_MAPI_PBCC Print Format$(iNumRecips) + " recipients" $EndIf If iNumRecips > 0 Then For i = 1 To iNumRecips zNames(i) = Parse$(Names$, ";", i) zAddr(i) = Parse$(Addresses$, ";", i) $If %DEBUG_MAPI_PBCC Print zNames(i), zAddr(i) $EndIf gRecip(i).iReserved = 0 gRecip(i).iRecipClass = %MAPI_TO gRecip(i).lpszName = VarPtr(zNames(i)) gRecip(i).lpszAddress = VarPtr(zAddr(i)) gRecip(i).iEIDSize = 0 gRecip(i).lpEntryID = 0 Next i End If '- Create the array of files If Trim$(Files$) = "" Then iNumFiles = 0 Else iNumFiles = ParseCount(Files$, ";") End If ReDim zFiles(0 To iNumFiles) As Asciiz * 300 '- Fill in the file information $If %DEBUG_MAPI_PBCC Print Print Format$(iNumFiles) + " attachments" $EndIf ReDim gFiles(0 To iNumFiles) i = 0 iNum = 0 For i = 1 To iNumFiles zFiles(i) = Parse$(Files$, ";", i) $If %DEBUG_MAPI_PBCC Print zFiles(i) $EndIf If Dir$(zFiles(i)) <> "" Then iNum = iNum + 1 gFiles(iNum).iReserved = 0 gFiles(iNum).iFlags = 0 gFiles(iNum).iPosition = Len(zNote) - 1 - (iNumFiles - i) gFiles(iNum).lpszPathName = VarPtr(zFiles(i)) gFiles(iNum).lpszFileName = 0 gFiles(iNum).lpFileType = 0 End If Next i iNumFiles = iNum '- Fill the message structure for passing to the MAPI call. rMessage.iReserved = 0 rMessage.lpszSubject = VarPtr(zSubject) rMessage.lpszNoteText = VarPtr(zNote) rMessage.lpszMessageType = 0 rMessage.lpszDateReceived = VarPtr(zTimeStamp) rMessage.lpszConversationID = 0 rMessage.iFlags = 0 rMessage.lpOriginator = 0 rMessage.iRecipCount = iNumRecips If iNumRecips > 0 Then rMessage.lpRecips = VarPtr(gRecip(1)) Else rMessage.lpRecips = 0 End If rMessage.iFileCount = iNumFiles If iNumFiles > 0 Then rMessage.lpFiles = VarPtr(gFiles(1)) Else rMessage.lpFiles = 0 End If '- Make the call. If iShowDialog Then Call Dword ptrMAPISendMail Using mapiTemplate_MAPISendMail( iSession, 0 , rMessage, %MAPI_LOGON_UI Or %MAPI_DIALOG, 0 ) To iReturn Else Call Dword ptrMAPISendMail Using mapiTemplate_MAPISendMail( iSession, 0 , rMessage, %MAPI_LOGON_UI, 0 ) To iReturn End If End If Function = iReturn End Function