Fun with Email: VB6, CDO, MAPI, and a Remote Exchange Server - The MAPI Approach (Page 2 of 3 )
First, you must have an Inbox profile (obviously). This profile points to the remote Exchange Server you wish to use. On the screen, ‘right click’ on ‘INBOX’ and select properties. If no Profile exists you will be prompted to create one, do it. The next screen will have check boxes, select the exchange server and move on to Profile name. Enter the Profile name. Follow the directions on the next screen to complete the setup. If you already have a profile, if will be displayed in the upper left corner or ‘click’ ‘show profile’ to see the profile name.
Next, we must add the MAPI controls to our VB form. Click on PROJECTS / COMPONENTS / BROWSE and locate the MAPI ocx in "../systerm32/msmapi32.ocx". ADD the control to the form.
Our new Function to send mail with MAPI looks like this (profile name = Matt):
Call MapiClass.blnSendMail("burnettm@hotmail.com", "burnettmFROM@hotmail.com", "mail", "MAPI mail is functional", "Matt")
Public Function blnSendMail (strTo As String, strFrom As String, strSubject As String, _ strBody As String, pName As String) As Boolean Dim MAPISession3 As MAPISession Set MAPISession3 = MAPISession1 With MAPISession3 .DownLoadMail = False .LogonUI = True .UserName = "Matt" 'This is the Profile Name in the InBox .Password = "" If MAPIMessages1.SessionID = 0 Then .SignOn .NewSession = True End If MAPIMessages1.SessionID = .SessionID End With
Dim MAPIMessages3 As MAPIMessages Set MAPIMessages3 = MAPIMessages1 With MAPIMessages3 .Compose .RecipAddress = strTo .AddressResolveUI = True .ResolveName .MsgSubject = strSubject .MsgNoteText = strBody .Send False End With
Set MAPIMessages3 = Nothing Set MAPISession3 = Nothing
If Err.Number <> 0 Then blnSendMail2 = False Else blnSendMail2 = True End If End Function
I ran this function within the VB form and it worked great!
Step 2 of my plan was to insert the function into a class. The class function had exactly the same code base as the form function. I ran the program with the following call:
Call MapiClass.blnSendMail("burnettm@hotmail.com", "burnettm@hotmail.com", "MAPI mail", "MAPI mail is functional", "Matt")
The program failed!!! The "Set MAPISession3 = MAPISession1" produced a type error. There are some examples of how to compile a form in a dll, then reference ActiveX controls from the form. However, a "form" is explicitly a UI and does not belong in a dll (IMO). This issue is related to the fact that ActiveX controls require a valid "Control Container", which a "class object" is not. To solve this problem, VB6 allows ‘late binding’ to OCX controls for use. This fact is significant in and by itself!
To late bind the MAPI ActiveX control:
Set objSession = CreateObject("MAPI.SESSION")
Additionally, you can late bind the CDO control for use in a class object:
Set mail = CreateObject("CDONTS.NewMail.1")
Having the MAPI object created successfully, I put the previous code in place and ran the program. Again, the program failed. Creating the object within the class exposes a different set of properties and methods. The following code allows the creation of a MAPI object and sends the mail. NOTE: the difference in properties between the VB form OCX and the late bound object.
Call MapiClass.blnSendMail("burnettm@hotmail.com", "burnettm@hotmail.com", "MAPI mail", "MAPI mail is functional", "Matt")
Public Function blnSendMail (strTo As String, strFrom As String, strSubject As String, _ strBody As String, pName As String) As Boolean On Error Resume Next Dim objSession As Object 'MAPI.Session Dim objMessage As Object 'MAPI.Message Dim objRecip As Object 'MAPI.Recipient Set objSession = CreateObject("MAPI.SESSION") objSession.Logon ProfileName:=pName, showDialog:=False Set objMessage = objSession.Outbox.Messages.Add objMessage.Subject = strSubject objMessage.Text = strBody Set objRecip = objMessage.Recipients.Add objRecip.Name = strTo objRecip.Type = 1 ' 1 is the value of the "mapiTo" constant. objRecip.Resolve objMessage.Update objMessage.Send showDialog:=False objSession.Logoff If Err.Number <> 0 Then blnSendMail = False Else blnSendMail = True End If End Function
This class function will send email using the remote Exchange server referred to in the Inbox profile.
The final class function took the shape of CDO and MAPI. The reason is that our dlls our built and tested on workstations but ultimately run on a server. MAPI was implemented to allow for testing on workstation. However, when the class is on a server there is no reason to load such a heavy class (MAPI) when CDO will do the job. Additionally, CDO does not require the Inbox profile setup.
Public Function blnSendMail(strTo As String, strFrom As String, strSubject As String, _ strBody As String, pName As String) As Boolean 'The CDO object is located on NT server, usually with the resource kit installed. On Error Resume Next Dim mail As Object Set mail = CreateObject("CDONTS.NewMail.1") mail.To = strTo mail.From = strFrom mail.Subject = strSubject mail.Body = strBody mail.Send Set mail = Nothing If (Err.Number = 0) Then blnSendMail77 = True Exit Function Else Err.Clear 'This script requires that a profile is setup in the local computer's INBOX properties 'Uses the profile info for return information. Dim objSession As Object 'MAPI.Session Dim objMessage As Object 'MAPI.Message Dim objRecip As Object 'MAPI.Recipient Set objSession = CreateObject("MAPI.SESSION") objSession.Logon ProfileName:=pName, showDialog:=False Set objMessage = objSession.Outbox.Messages.Add objMessage.Subject = strSubject objMessage.Text = strBody Set objRecip = objMessage.Recipients.Add objRecip.Name = strTo objRecip.Type = 1 ' 1 is the value of the "mapiTo" constant. objRecip.Resolve objMessage.Update objMessage.Send showDialog:=False objSession.Logoff If Err.Number <> 0 Then blnSendMail77 = False Else blnSendMail77 = True End If End If End Function
Additional Notes and Research
Calling the Logon Method of MAPI object with server and account: