none
Outlook 2003 security dialog using C++ MFC RRS feed

  • Question

  • Hi,

    I am trying to create an application that captures an email sent event on outlook 2003. Which i am able to get fine. But when i try to access anything from the MailItem object a pop up appears saying "an application is trying access outlook adress......"  - "alllow" (the object gaurd message) . Is there any way i can turn this feature off, using registry or any other way I can By pass the prompt. 

    I have read somewhere that third party applications like redemption can help with C# or VB add ins. Can it help me in C++ as well?  Want to make sure before i buy the licence 

    this is the code :

    ///Part where i createdispatch for outlook and start the event sink
    initializeOutlookEventSink()
    {
    	
    	CoInitializeEx(0,COINIT_MULTITHREADED);
    	if(m_pAppEventListener==NULL)
    	{
    		
    	if( m_OutlookApplication.CreateDispatch(_T("Outlook.Application") ) == 0 )
        {
            AfxMessageBox(_T("FAILURE"), MB_SETFOREGROUND);
            return;
        }
    //	CNameSpace olNs(m_OutlookApplication.GetNamespace(_T("MAPI")));
    	//Add an event handler for the Application object.
        m_pAppEventListener = new CAppEventListener();
        m_pAppEventListener->AddRef();
        m_pAppEventListener->AttachToSource( m_OutlookApplication.m_lpDispatch );
    
    
    /////////////////////////////////////
    ///THE PART OF CODE THAT CAUSES THE PROMPT
    
    hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pMail, L"SenderEmailAddress", 0);
    	if (FAILED(hr)) return FALSE;
    	senderemail = result.bstrVal;
    
    ///Where pMail is a pointer to the MailItem captured in the send event

    Any help will be appriciated

    Thanks

    Friday, March 21, 2014 9:47 AM

Answers

  • Hello Vidur,

    It seems you get a standard security prompt. You can read more about this in the Outlook "Object Model Guard" Security Issues for Developers article. It describes all possible ways for suppressing such messages.

    The most easiest way is to use Extended MAPI. It doesn't trigger security prompts. Note, Redemption and Outlook are just wrappers around that API. However, Redemption doesn't generate security prompts. Also you can consider using security manager.

    Friday, March 21, 2014 11:53 AM
  • In this particular case, you app will need to

    1. call MAPIInitialize()

    2. Read the pMail.MAPIOBJECT property

    3. QI it for the IMessage interface

    4. call HrGetOneProp or IMessage::GetProps() to read the PR_SENDER_EMAIL_ADDRESS property

    5. Read the PSPropValue->Value.lpszW or PSPropValue->Value.lpszA (depending on whether you ask for an ANSI or Unicode flavor of the property).

    5. Free the returned PSPropValue structure using MAPIFreeBuffer()


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Friday, March 21, 2014 1:28 PM
  • Hello Vidur,

    It looks like you need to remove the space in the MAPIOBJECT name.

    hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pMail, L"MAPIOBJECT", 0);  
    

    Where did you get the pMail object?

    Saturday, March 22, 2014 9:52 AM
  • Hi Vidur,

    I have noticed that you specified the PR_BODY tag. I'd recommend using the OpenProperty method for getting the value instead. The GetProps method can't return the value if the property is 4 KB or larger.

    Here is what MSDN states for MAPI_W_ERRORS_RETURNED:

    If GetProps returns MAPI_W_ERRORS_RETURNED because it could not access one or more properties, check the property tags of the returned properties. The failed properties will have the following values set in their property value structure: 

    •           Property type in the ulPropTag member set to PT_ERROR.
    •           Property value in the Value member set to a status code for the error, such as MAPI_E_NOT_FOUND.

    Properties that fail because they are too large to be returned in the property value structure have their Value member set to MAPI_E_NOT_ENOUGH_MEMORY. Typically, this occurs with string or binary properties of type PT_STRING8, PT_UNICODE, or PT_BINARY when the value of the property is 4 KB or larger. Call IMAPIProp::OpenProperty to retrieve large properties.

    Sunday, March 23, 2014 10:31 AM
  • The error is MAPI_E_NOT_FOUND. Again, *when* is that code invoked?

    PR_SENDER_EMAIL_ADDRESS will only be set afterafter the message is moved to the Sent Items folder.

    PR_DISPLAYNAME property is never set on messages.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Tuesday, March 25, 2014 1:48 PM

All replies

  • Hello Vidur,

    It seems you get a standard security prompt. You can read more about this in the Outlook "Object Model Guard" Security Issues for Developers article. It describes all possible ways for suppressing such messages.

    The most easiest way is to use Extended MAPI. It doesn't trigger security prompts. Note, Redemption and Outlook are just wrappers around that API. However, Redemption doesn't generate security prompts. Also you can consider using security manager.

    Friday, March 21, 2014 11:53 AM
  • In this particular case, you app will need to

    1. call MAPIInitialize()

    2. Read the pMail.MAPIOBJECT property

    3. QI it for the IMessage interface

    4. call HrGetOneProp or IMessage::GetProps() to read the PR_SENDER_EMAIL_ADDRESS property

    5. Read the PSPropValue->Value.lpszW or PSPropValue->Value.lpszA (depending on whether you ask for an ANSI or Unicode flavor of the property).

    5. Free the returned PSPropValue structure using MAPIFreeBuffer()


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Friday, March 21, 2014 1:28 PM
  • Hi Dimitry,

    Thanks for your reply. Allthough i encountered a problem when trying to get the MAPIOBJECT from the MailItem. It returned saying "Unknown Name"

    Here is my code, am i doing something wrong

    MAPIInitialize(0);
    
    	 IMessage* pMsg = NULL;
    
    	
    
    	OutputDebugString(L"HandleNewMail\n");
    	CString to, senderemail, senderemailt, sendername, subject, body, cc, bcc,emailtype;
    	HRESULT hr = S_FALSE;
    	VARIANT result;
    	VariantInit(&result);
    
    //////////HERE IS WHERE IT FAILS////////
    	hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pMail, L"MAPIOBJECT ", 0);  
    	if (FAILED(hr)) return FALSE;
    ///////////////////////////////
    	
    	result.pdispVal->QueryInterface(IID_IMessagex1,(void**)&pMsg);
    	//HRESULT hr           = E_FAIL;
        SPropValue * rgprops = NULL;
    	ULONG rgTags[]       = {3, PR_SENDER_EMAIL_ADDRESS, PR_SUBJECT, PR_BODY};
        ULONG cCount         = 0;
        // Get the message's properties.
        hr = pMsg->GetProps((LPSPropTagArray) rgTags, MAPI_UNICODE, &cCount, &rgprops);
    	
    
    	  if (SUCCEEDED(hr))
        {
            // Check that the ulPropTag member of each property value is of the property type requested, 
            // and that it does not have a value of PT_ERROR.
            if (rgprops[0].ulPropTag == PR_SENDER_EMAIL_ADDRESS)
            {
               // DEBUGMSG(TRUE, (L"From: %s \r\n", rgprops[0].Value.lpszW));
            }
            if (rgprops[1].ulPropTag == PR_SUBJECT)
            {
                //DEBUGMSG(TRUE, (L"Subject: %s \r\n", rgprops[1].Value.lpszW));
            }
            if (rgprops[2].ulPropTag == PR_BODY)
            {
               // DEBUGMSG(TRUE, (L"Importance: %d \r\n", );
    			body =rgprops[2].Value.lpszW;
            }
            // Free the returned SPropValue structure.
            MAPIFreeBuffer(rgprops);
        }
    	  MAPIUninitialize();


    Thanks again for your reply

    *EDIT

    Hi again, When i try to get prop It returns an error "Mapi_w_Errors_Returned(40380)"

    Any ideas?

    Saturday, March 22, 2014 6:11 AM
  • Hello Vidur,

    It looks like you need to remove the space in the MAPIOBJECT name.

    hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pMail, L"MAPIOBJECT", 0);  
    

    Where did you get the pMail object?

    Saturday, March 22, 2014 9:52 AM
  • Hi Eugene,

    Thanks for the Replies. 

    I got the MAPIOBJECT with your fix. Didnt see the space there. But i still have problems gettings any properties from the IMessage. Dont know if im doing anything wrong. I get the pMail object from an event handler , here is my code for getting the Pmail object:

    STDMETHODIMP CAppEventListener::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,                               WORD wFlags, DISPPARAMS* pDispParams,                                 VARIANT* pVarResult, EXCEPINFO* pExcepInfo,                                 UINT* puArgErr)
    {
    	CString szText;
    
    	szText.Format( L"DISP_ID: %x\n", dispIdMember );
    	OutputDebugString( szText );
    
    	switch(dispIdMember)
    	{
    		case 0x0000f002:		//Vidur - send mail NewMail()
    			if(pDispParams->cArgs !=2)
    				return E_INVALIDARG;
    			else
    			{
    				
    				HandleNewMail(pDispParams->rgvarg[1].pdispVal,(VARIANT_BOOL*) pDispParams->rgvarg[0].pboolVal);	 \\Here is were i Get the pMail object
    				
    				
    				break;
    				
    			}

    Here is where I'm Trying to retrive the data of the mail being sent out.

    STDMETHODIMP CAppEventListener::HandleNewMail(IDispatch * pMail, VARIANT_BOOL * bCancel)
    {
    	MAPIInitialize(0);
    
    	IMessage* pMsg = NULL;
    
    	// CMailItem mailitem = pMail;
    	
    //	LPUNKNOWN 
    
    	OutputDebugString(L"HandleNewMail\n");
    	CString to, senderemail, senderemailt, sendername, subject, body, cc, bcc,emailtype;
    	HRESULT hr = S_FALSE;
    	VARIANT result;
    	VariantInit(&result);
    
    
    	hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pMail, L"MAPIOBJECT", 0);
    	if (FAILED(hr)) return FALSE;
    
    	
    	hr= result.pdispVal->QueryInterface(IID_IMessagex1,(void**)&pMsg);
    	HRESULT hr2        = E_FAIL;
        SPropValue * rgprops = NULL;
    	ULONG rgTags[]       = {3, PR_SENDER_EMAIL_ADDRESS,PR_DISPLAY_NAME_W,PR_BODY };
        ULONG cCount         = 0;
    
    	hr2 = pMsg->GetProps((LPSPropTagArray) rgTags, MAPI_UNICODE, &cCount, &rgprops); \\hr2 returns Mpai_w_errors_returned(40380)
    
    
    	if (SUCCEEDED(hr2))
        {
            // Check that the ulPropTag member of each property value is of the property type requested, 
            // and that it does not have a value of PT_ERROR.
    		if (rgprops[0].ulPropTag == PR_SENDER_EMAIL_ADDRESS)
            {
               to = rgprops[0].Value.lpszW;
    			// DEBUGMSG(TRUE, (L"From: %s \r\n", rgprops[0].Value.lpszW));
            }
            if (rgprops[1].ulPropTag == PR_DISPLAY_NAME_W)
            {
    			to = rgprops[1].Value.lpszW;
               // DEBUGMSG(TRUE, (L"Subject: %s \r\n", rgprops[1].Value.lpszW));
            }
            if (rgprops[2].ulPropTag == PR_BODY)
            {
             //   DEBUGMSG(TRUE, (L"Importance: %d \r\n", );
    			body =rgprops[2].Value.lpszW;
            }
            // Free the returned SPropValue structure.
            MAPIFreeBuffer(rgprops);
        }
        
    	MAPIUninitialize();


    Also note the variable "IID_IMessagex1" had to be defined as i kept getting unresolved symbol error

    DEFINE_OLEGUID(IID_IMessagex1,		0x00020307, 0, 0);

    Don't know what I'm doing wrong here. am I missing something? Is there a better way to handle emails being sent out on event? 

    Do i have to logon to a mapi session for this work? or can i retrieve it via EntryID?

    Please advise.

    And thank you for your answers



    Sunday, March 23, 2014 3:57 AM
  • And what exactly does not work? Which line of your code returns an error or an unexpected result?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Sunday, March 23, 2014 5:14 AM
  • Hi Dimitri,

    The error is here: I am unable to get any of the properties 

    hr2 = pMsg->GetProps((LPSPropTagArray) rgTags, MAPI_UNICODE, &cCount, &rgprops); \\hr2 returns Mpai_w_errors_returned(40380)

    It returns error code : 0x00040380


    Sunday, March 23, 2014 5:49 AM
  • Hi Vidur,

    I have noticed that you specified the PR_BODY tag. I'd recommend using the OpenProperty method for getting the value instead. The GetProps method can't return the value if the property is 4 KB or larger.

    Here is what MSDN states for MAPI_W_ERRORS_RETURNED:

    If GetProps returns MAPI_W_ERRORS_RETURNED because it could not access one or more properties, check the property tags of the returned properties. The failed properties will have the following values set in their property value structure: 

    •           Property type in the ulPropTag member set to PT_ERROR.
    •           Property value in the Value member set to a status code for the error, such as MAPI_E_NOT_FOUND.

    Properties that fail because they are too large to be returned in the property value structure have their Value member set to MAPI_E_NOT_ENOUGH_MEMORY. Typically, this occurs with string or binary properties of type PT_STRING8, PT_UNICODE, or PT_BINARY when the value of the property is 4 KB or larger. Call IMAPIProp::OpenProperty to retrieve large properties.

    Sunday, March 23, 2014 10:31 AM
  • Hi Eugene, 

    Thanks for your reply again. I will try this and see if it works, Allthough i doubt my data is larger than 4kb, i tried the getprops with only the PR_SENDER_EMAIL_ADDRESS. Still get the same error. 

    Maybe im getting the concept wrong here. Do i have to wait for the message to be sent before i can access the mapi object? in other when we sue a MAPI object is it trying to read the .pst or .ost file? 

    Thanks again.

    Your help is much appreciated

    Sunday, March 23, 2014 12:51 PM
  • Where is that code invoked? Application.ItemSend event? Keep in mind that sender related properties are not yet set. The earliest you will be able to see them is in the Items.ItemAdd event on the Sent Items folder.

    You must also save the message (MailItem.Save()) before you will be able to see PR_BODY etc.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Sunday, March 23, 2014 5:01 PM
  • Hi Dimitry and Eugene,

    Thank you guys for you replies and help.

    @Eugene - I was able to get the Body using open property, can i do the same for the other properties?

    @Dimity  - What do you mean by where is the code Invoked? I'm not using the "ApplicationEvent" interface to invoke the code. Here is how im doing it:

    	
    CApplication m_OutlookApplication;
    	CAppEventListener* m_pAppEventListener;
    
    if( m_OutlookApplication.CreateDispatch(_T("Outlook.Application") ) == 0 )
        {
            AfxMessageBox(_T("FAILURE"), MB_SETFOREGROUND);
            return;
        }
    	
    	
    //	CNameSpace olNs(m_OutlookApplication.GetNamespace(_T("MAPI")));
    	//Add an event handler for the Application object.
    	 /*  CNameSpace olNs(m_OutlookApplication.GetNamespace(_T("MAPI")));
       COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
       olNs.Logon(covOptional, covOptional, covOptional, covOptional);*/
        m_pAppEventListener = new CAppEventListener();
        m_pAppEventListener->AddRef();
        m_pAppEventListener->AttachToSource( m_OutlookApplication.m_lpDispatch ); 


    STDMETHODIMP CAppEventListener::AttachToSource( IUnknown* pEventSource ) \\Where pEventSource is an Appliation Object
    {
       HRESULT hr = S_OK;
    
       IConnectionPointContainer* pCPC = NULL;
       hr = pEventSource->QueryInterface( IID_IConnectionPointContainer, 
          (void**)&pCPC );
       if (SUCCEEDED(hr)){
          
          hr = pCPC->FindConnectionPoint( IID_ApplicationEvents, 
             &m_pConnectionPoint );
          if (SUCCEEDED(hr)){
             
             hr = m_pConnectionPoint->Advise( this, &m_dwConnection );
          }
          pCPC->Release();
       }
    
       return hr;
    }

    My application is based on This example : codeproject.com/Articles/4230/Implementing-Outlook-XP-Event-Sinks-in-MFC-C 


    And as shown in my code earlier I get the events, and Based on thier DISPID i perform actions.

    Also i tried to use MailItem.save() but i still coudnt get the properties :/ .

    Monday, March 24, 2014 3:27 AM
  • So which event are you handling? NewMail?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Monday, March 24, 2014 6:26 AM
  • Hello Vidur,

    Yes, you can use the OpenProperty method for other properties. But I'd recommend continue using the GetProps method. The OpenProperty method is used for large properties.

    Did you try to find the problematic properties when the GetProps fails?

    Property type in the ulPropTag member set to PT_ERROR.

    • * Property value in the Value member set to a status code for the error, such as MAPI_E_NOT_FOUND.
     

    Which one fails? Or both? What status code for the error do you get?

    Monday, March 24, 2014 6:30 AM
  • Hi Eugine,

    From the Getprops function i get the following status code is retunred : "0x00040380", which i believeis MAPI_W_ERRORS_RETURNED

    the porp tag for the first property which is supposed to be "PR_SENDER_EMAIL_ADDRESS" is :"203358218" and the value is -2147221233

    the porp tag for the second property which is supposed to be "PR_DISPLAYNAME_W" is :"805371914" and the value is also -2147221233


    My Company has decided to buy the licence for a thrid party app, right now i am using a trail version Security Manager. I was advised to use the activeX control. But i am facing a problem when i try to use the ConnectTo method. Do you have any experice with Security manager. Here is my code

    	SecurityManager = new COutlookSecurityManager();
    
    	HRESULT hr = CoCreateInstance(SecurityManager->GetClsid(), NULL, CLSCTX_SERVER, 
    			IID_IDispatch, (void **) (IDispatch *) &SecurityManager);
    
    	CLSID clsid;
    //	HRESULT hr;
    
    	// Option 1. Get CLSID from ProgID using CLSIDFromProgID.
    	LPCOLESTR progID = L"Outlook.Application";
    	hr = CLSIDFromProgID(progID, &clsid);
    	IDispatchPtr pOutlookApp;
    	hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, 
    				IID_IDispatch, (void **) (IDispatch *) &pOutlookApp);		// [-or-] CoCreateInstanceEx, CoGetObject
    		
    	CComDispatchDriver spDispOutlook(pOutlookApp);
    
    		
    	SecurityManager->ConnectTo((CComVariant((IDispatch *)pOutlookApp))); // FAILS IN this line
    
    	 BOOL warning =   SecurityManager->get_DisableOOMWarnings();
    	 if(!warning)
    	 {
    		 SecurityManager->put_DisableOOMWarnings(TRUE);
    	 }

    I get the following crash: Unhandled exception at 0x5614447F (mfc110ud.dll) in AutomateOutlookWithMFC.exe: 0xC0000005: Access violation reading location 0x0000027B.

    Thank you guys again for all your help.

    Tuesday, March 25, 2014 9:29 AM
  • The error is MAPI_E_NOT_FOUND. Again, *when* is that code invoked?

    PR_SENDER_EMAIL_ADDRESS will only be set afterafter the message is moved to the Sent Items folder.

    PR_DISPLAYNAME property is never set on messages.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Tuesday, March 25, 2014 1:48 PM
  • Hello Vidur,

    You can try to pass an instance of the Explorer class to the ConnectTo method of the security manager component. Is there any Outlook window visible when you are trying to connect?

    Anyway, I'd recommend contacting the Outlook security manager component developers directly. They're aware of such issues.

    Finally, what event handler do you use for getting the property values? Where and when do you try to get their values?

    Tuesday, March 25, 2014 2:16 PM