News:

This week IPhone 15 Pro winner is karn
You can be too a winner! Become the top poster of the week and win valuable prizes.  More details are You are not allowed to view links. Register or Login 

Main Menu

Fun with email (VB6, CDO, MAPI, and a remote Exchange server)

Started by ben2ong2, October 07, 2006, 04:45:32 PM

Previous topic - Next topic

0 Members and 3 Guests are viewing this topic.

ben2ong2

Yesterday, I was really unhappy with my computer. The programming at hand was clear and seemed to be a straightforward deal. In the end, it was not so easy.

The Deal: A client machine (workstation, Win98, 2000, or ME) will actively send emails from within a custom VB6 application (exe). Additionally, the application instantiated a custom local object (dll) that contained a public SendMail function with parameters to send the mail.

NOTE: I found some software that makes development a lot faster and improves windows in general: Firefox with Google Toolbar

I stepped through this process by first (my machine is an NT workstation with transaction server):

         1. Creating a VB form in MS Visual Basic 6 to hold the Click event and Public SendMail function
         2. Transfer the Public SendMail function to a class object
         3. Compile and run, calling the function from the class

So easy (I thought!). I created a button to fire my SendMail function in the form (form1). I did not think that CDONTS is a server library and not available on other client types!

Private Sub Command1_Click()

Call blnSendMail ("burnettm@hotmail.com", "burnettm@hotmail.com", "mail", "functional")

End Sub

Private Function blnSendMail(strTo As String, strFrom As String, strSubject As String, strBody As String) As Boolean

'The CDO object is located on NT server, usually with the resource kit installed, ADCSRV4 is properly configured.

On Error Resume Next
Dim mail As CDONTS.NewMail
Set mail = New CDONTS.NewMail
mail.To = strTo
mail.From = strFrom
mail.Subject = strSubject
mail.Body = strBody
mail.Send
Set mail = Nothing
If Err.Number <> 0 Then
blnSendMail = False
Else
blnSendMail = True
End If
End Function

Ok, so this script failed miserably when run on my workstation, but ran successfully on a server. However, this was not what I needed and I turned to MAPI. Now, MAPI is like an extended CDO object and is about having a ‘Profile’ setup in the "Inbox" on your computer. My next attempt, below, called a MAPI object in a VB form using an Inbox profile.

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

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:

strProfileInfo = "ADCSRV1" & vbLf & "mburnett@adctech.com"

objSession.Logon "", "", False, True, 0, True, strProfileInfo

You will find some permission issues with exchange server: Refer to MS Q195681 "Configure an Exchange Mailbox for Anonymous Access", to get started.

The Logon Method of the MAPI object also has an anonymous profile string"

'strProfileInfo = "/o=" + strEnterprise + "/ou=" + strSite + "/cn=Configuration/cn=Servers/cn=" + strServer + vbLf + "anon" + vbLf + "anon"

'strProfileInfo = "/o=1ADCTECH/ou=1ADCTECH/cn=Configuration/cn=Servers/cn=ADCSRV1" & vbLf & "anon" & vbLf & "anon"

Article By, Matthew P. Burnett.
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login