How to avoid security prompts in Visual Basic programs for Outlook
Working with MAPI from Visual Basic without any third-party libraries
Notwithstanding the common opinion that there is no way to work with MAPI from Visual Basic, we dare to say to the contrary. Certainly, it is virtually impossible to access all the MAPI riches from Visual Basic, but the task of getting object properties shouldn't come difficult to an experienced developer.
There is the following function in MAPI:
HrGetOneProp(
LPMAPIPROP pmp,
ULONG ulPropTag,
LPSPropValue FAR * ppprop
);
This function receives the pointer to the object interface (stored in MAPIOBJECT), tag, and returns the pointer to value. The most difficult problem here is how to deal with the returned value. In MAPI SDK it is described as follows:
typedef struct _SPropValue
{
ULONG ulPropTag;
ULONG dwAlignPad;
union _PV Value;
} SPropValue, FAR *LPSPropValue;
The tag of the requested value is saved in ulPropTag as if the request was processed with no errors, and the Value union is described in MAPIDEFS.H as follows:
typedef union _PV
{
short int i; /* case PT_I2 */
LONG l; /* case PT_LONG */
ULONG ul; /* alias for PT_LONG */
float flt; /* case PT_R4 */
double dbl; /* case PT_DOUBLE */
unsigned short int b; /* case PT_BOOLEAN */
CURRENCY cur; /* case PT_CURRENCY */
double at; /* case PT_APPTIME */
FILETIME ft; /* case PT_SYSTIME */
LPSTR lpszA; /* case PT_STRING8 */
SBinary bin; /* case PT_BINARY */
LPWSTR lpszW; /* case PT_UNICODE */
LPGUID lpguid; /* case PT_CLSID */
LARGE_INTEGER li; /* case PT_I8 */
SShortArray MVi; /* case PT_MV_I2 */
SLongArray MVl; /* case PT_MV_LONG */
SRealArray MVflt; /* case PT_MV_R4 */
SDoubleArray MVdbl; /* case PT_MV_DOUBLE */
SCurrencyArray MVcur; /* case PT_MV_CURRENCY */
SAppTimeArray MVat; /* case PT_MV_APPTIME */
SDateTimeArray MVft; /* case PT_MV_SYSTIME */
SBinaryArray MVbin; /* case PT_MV_BINARY */
SLPSTRArray MVszA; /* case PT_MV_STRING8 */
SWStringArray MVszW; /* case PT_MV_UNICODE */
SGuidArray MVguid; /* case PT_MV_CLSID */
SLargeIntegerArray MVli; /* case PT_MV_I8 */
SCODE err; /* case PT_ERROR */
LONG x; /* case PT_NULL,
PT_OBJECT (no usable value) */
} __UPV;
The example below was written and debugged in Visual Basic 6, and, to make it shorter, we've used a simpler description of the structure:
Private Type SPropValue
ulPropTag As Long
dwAlignPad As Long
val1 As Long
val2 As Long
val3 As Long
End Type
So, the call of HrGetOneProp creates the structure and returns the pointer to it. Once the work with the structure is completed, we must delete it, passing the pointer returned to the MAPIFreeBuffer function:
Private Declare Function HrGetOneProp Lib "mapi32" _
Alias "HrGetOneProp@12" ( _
ByVal lpMapiProp As IUnknown, _
ByVal ulPropTag As Long, _
ByRef lppProp As Long) As Long
Private Declare Function MAPIFreeBuffer Lib "mapi32" ( _
ByVal lppProp As Long) As Long
It should also be noted that if the string properties requested are returned as ANSI-strings, before being used in Visual Basic they need to be converted into Unicode. The following code was borrowed from Chapter 6 of the book "Win32 API Programming with Visual Basic" by Steven Roman:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function lstrlenA Lib "kernel32.dll" ( _
ByVal lpString As Long) As Long
Private Function LPSTRtoBSTR(ByVal lpsz As Long) As String
Dim cChars As Long
cChars = lstrlenA(lpsz)
LPSTRtoBSTR = String$(cChars, 0)
CopyMemory ByVal StrPtr(LPSTRtoBSTR), ByVal lpsz, cChars
LPSTRtoBSTR = Trim(StrConv(LPSTRtoBSTR, vbUnicode))
End Function
Well, now we have everything we need to get the value of the tag PR_SENDER_EMAIL_ADDRESS we've been so keenly interested in:
Private Sub PrintEmail()
Dim objSesson As Object
Dim objItem As Object
Set objSession = CreateObject("MAPI.Session")
objSession.Logon
Set objItem = objSession.Inbox.Messages.GetFirst
Dim ptrSProp As Long
ptrSProp = 0
If HrGetOneProp(objItem.MAPIOBJECT, &H0C1F001E, ptrSProp) = 0 Then
Dim sprop As SPropValue
CopyMemory sprop, ByVal ptrSProp, 20
MsgBox LPSTRtoBSTR(sprop.val1)
MAPIFreeBuffer ptrSProp
End If
Set objItem = Nothing
Set objSession = Nothing
End Sub
The PrintEmail does the following:
- Creates a CDO session
- By the Logon request, performs a MAPI initialization (if you are using OOM, not CDO, you may have to perform this through the invocation of the function MAPIInitialize)
- Receives the first message in the Inbox folder of Outlook into objItem
- Receives the pointer to the SPropValue structure into the ptrSProp variable by the HrGetOneProp call
- Copies the data from the structure in the spprop variable, after which the pointer to the outcome string (in the ANSI format) appears in spprop.val1
- By the LPSTRtoBSTR request, converts the string into the Visual Basic format, and displays it on the screen by the MsgBox request
- By the MAPIFreeBuffer call, frees the memory allocated for the structure by the HrGetOneProp request
- Release the object and closes the CDO session
Now, congratulations! We've managed to bypass the security system without using any third-party libraries and components. But, well, what can components offer us?
|
|