Quantcast
Channel: For lack of a better word
Viewing all 62 articles
Browse latest View live

Cool MFCMAPI Feature: Logging every MAPI function called

$
0
0

Wanna learn Extended MAPI?  Sure, we all do.  Well most likely not, but in every project there comes a time when you need to add a feature and you don't know where to start.  MFCMAPI can be helpful in figuring out what to do in Extended MAPI if you don't know where to start. Here is what you do. Open up MFCMAPI and go to "Tools > Debug View…".  If you are a keyboard kind of guy like myself, you can press CTRL+D instead.  This will launch the Debug Viewer Dialog.  The Debug Viewer can be used for lot of things, but in this case try turning on logging for MAPI Functions. To do that, set the Debug Flags to 0x40000000 (DBGMAPIFunctions).

Now as you navigate the store or perform specific operations in the user interface, the Debug Viewer will show you what MAPI functions are being called. This can give you a high level overview of what a program or a feature doing the same thing should do in MAPI.  Want more detail?  It also outputs the line numbers and the source file where the call can be found.  Since the source code is available on CodePlex you can browse it to see exactly how the objects were manipulated.

It's a pretty cool feature and one that is a hidden gem. I plan to share more of these as time permits so you too can be a MFCMAPI Power user.


MAPI \ CDO will not be supported for Exchange 2016

$
0
0

I wanted to point out a significant note for some in the Exchange 2016 Architecture blog post here : http://blogs.technet.com/b/exchange/archive/2015/05/05/exchange-server-2016-architecture.aspx.  Specifically, that Exchange 2016 will not support clients using Exchange's MAPI (aka MAPI \ CDO) to access Exchange Data.  Exchange's MAPI has been out of main stream support for some time now (as it's tied to the lifecycle of Exchange 2003), so it isn't a surprise that Exchange 2016 will no longer allow it.  However, for some ISVs and vendors still relying on MAPI \ CDO this is important note.  The time to start planning and developing the next version of your product is now so you are ready when Exchange 2016 ships.

How to configure an Outlook 2016 profile using MFCMAPI

$
0
0

The process for creating a Outlook profile in Outlook 2016 has changed. This article documents the simple steps to create one using MFCMAPI.  Note: For non-developers this is not the recommended way of creating profiles in Outlook 2016.  It is recommended that you use Outlook to create the profile as the logic for this is all built-in.  However, you can use these steps for troubleshooting purposes.

  1. Open up MFCMAPI, go to Profile > Show Profiles
  2. Click Actions > Create Profile

  1. Give the new profile a name and click OK.

  1. Select the new profile

  1. Type MSEMS for the service name
  2. Uncheck the box which says "Display Service UI"

  1. Click OK
  2. Double-Click the newly created profile.
  3. Single-Click the MSEMS service.
  4. Find the Exchange Profile section. This is a little difficult in Outlook’s MAPI since in 2010 and above we no longer have the global profile section. To find the Exchange Profile Section find the property PR_EMSMDB_SECTION_UID (0x3D150102) in the properties for the service. The value will be the GUID of the profile section persisted in binary form which will be used in the subsequent steps. You will need to remember this value.
  5. Double-Click the MSEMS service.
  6. Find the Exchange profile section by using the UID gathered from Step 10 and single-click it to select the row.
  7. Go to Property > Additional Properties

  1. Click Add and add the following properties PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W (0x6641001F) and PR_DISPLAY_NAME_W.

  1. Click OK
  2. Configure each property using the guidance below.
Property: PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W
Value: SMTP Address of the user
Property: PR_DISPLAY_NAME_W
Value: The display name of the user
  1. Find the property PR_STORE_PROVIDERS in the Exchange profile section.  This is the EMSMDB profile section.  Note the value of it.

  1. Find the corresponding profile section whose UID matches the value of PR_STORE_PROVIDERS.
  2. Repeat Steps 13 - 17 for that profile section too.

  1. Select Session > Logon and display store, and select the profile if it is not already selected.
  2. You may be prompted for credentials, but it should work successfully.

More Information

The display name on the Exchange profile section is not required, but I included it here for simplicity.

In Step 14, it is okay if the property name is not resolved to PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W.

Sample code can be found here that shows you how to do this programmatically.


IMAPISession::OpenMsgStore() returns MAPI_E_VERSION (0x80040110)

$
0
0

As documented previously, Exchange 2016 will not allow connections from Exchange's MAPI (aka MAPI \ CDO).  MAPI client applications may receive the error MAPI_E_VERSION (0x80040110).  If you are running On-Premises Exchange 2016 and have access to the RPC Client Access logs, you will see this error in the log around the time that the connection was attempted:

RpcDispatch: [RpcServerException] Client version 6.0.XXXX.0 is below the minimum required version 10.0.0.0. (StoreError=Version)

The recommended approach is to use Exchange Web Services or the REST APIs to access the Exchange mailbox.  As a temporary workaround you could try porting the MAPI client application to Outlook's MAPI, but Outlook's MAPI can't log into Recovery Databases and have other nuances that may make this not viable.

How to use CDO 1.2.1 to connect to Exchange 2013 using a dynamic profile

$
0
0

NOTE: This article only applies to Exchange’s MAPI \ CDO download.  It doesn’t apply to using CDO 1.2.1 with an Outlook 2007 client.

I was discussing an issue recently with a customer and I asked him to connect to the Exchange server using CDO 1.2.1.  Then I realized that I had never tried that myself.  To that end, I decided to set out to have CDO 1.2.1 create a dynamic profile and connect to Exchange 2013.

First, some things about dynamic profiles. CDO 1.2.1 has a concept of a dynamic profile.  This means that a profile is created on the fly by passing the server name and mailbox name as the last parameter to the Session::Logon() method.

This is different than using a static profile that you configured outside of CDO 1.2.1.

Session::Logon()

http://msdn.microsoft.com/en-us/library/ms526377(v=exchg.10).aspx

One gotcha that I ran into was that the server name and mailbox name need to be delimited by a line feed (character 10).  In Visual Basic 6 the line would look like this:

objSession.Logon , , ,true, ,true, _ 
"e9b5d6f1-89f1-4e02-93a1-7b3762cf2c59@contoso.com" & Chr(10) & "admin"    

Of course, in Exchange 2013 the server name is the personalized server name of the target mailbox.  The mailbox name is just the alias of the user.  That’s the easy part.  The hard part is configuring the registry to make this all work.  The RPCHttpProxyMap registry value is needed to get the dynamic profile created.  I discuss configuring this value in my omniprof article.  The other registry value that needs to be in place is the one which instructs CDO 1.2.1 to proceed even if Public Folders don’t exist in the organization.  This setting is discussed in this blog post article by a former member of my team.  Once those are in place it should work.

The reason why these values are needed is that CDO 1.2.1 needs to know how to properly connect to Exchange.  Telling CDO 1.2.1 to “Ignore No PF” instructs it to pass the CONNECT_IGNORE_NO_PF flag when creating the underlying dynamic profile.  Creating the RPCHttpProxyMap registry value tells the underlying MAPI subsystem what RPC Proxy Server to connect to, what authentication to use, and what to do if a non-trusted certificate is encountered.

The two scenarios that I couldn’t get working are targeting an Office 365 mailbox or an On-Premises mailbox where the RPC Proxy Server has been configured to accept Basic Authentication.  This is because the username and password must be configured on the profile for Exchange’s MAPI to use it. You’ll need to use a static profile for those scenarios.

Lastly, I wanted to point out that CDO 1.2.1 is not the recommended API for connecting to Exchange Server 2013.  However, I understand that some customers have existing applications that they may need to get working for Exchange 2013 before they upgrade. If you fall into this category this article may help you until you can migrate your application to a better API.

Handbook for the Recently Present

$
0
0

Handbook for the IM & P developerOne of the common calls I take in my job are from developers trying to write Instant Messaging and Presence (IM & P) providers to integrate with Office and Sharepoint.  The number of cases I see are increasing so I wanted to start a series dedicated to that topic.  The purposes of this series is to augment the documentation already out there and identify "gotchas" along the way.  The first thing to know is the various terms I am going to use along the way. I will keep this page updated with the definitions that are added in later posts.

Provider Types

  1. OC20 – This is a provider that implements the IMessenger API.  You must have Office 2007 or above.  This is the deprecated API but Office 2010 and Office 2013 still support it.
  2. OCOM – This is a provider that implements the OCOM API.  You must have Office 2010 or above to use this provider type.
  3. OCOM2 – This is a provider that implements the OCOM API. It’s a superset of the OCOM API for Office 2010.  You must have Office 2013 to use this provider type.

Initially, I am going to focus on the OCOM implementation.  This is because this is the provider type that is going to be supported moving forward.  I will write some articles about OC20 but not at first.  With that said, let’s get started.  The first question I am going to answer is how do I get started?

How to get started

First, you need to decide in what language you are going to write your provider in.  The Office implementation of the "client side" is implemented in COM and C/C++.  Therefore, you need to decide if you want to write the provider in C/C++ or use .NET along with COM Interop.  You cannot use Visual Basic 6.0 to build a provider.  Trust me, I have tried.  The problem with Visual Basic 6.0 is that it doesn’t allow you specify UUID’s for source interfaces.  This results in failures when Office attempts to find the connection points for some source interfaces.  For those not familiar with COM eventing this means that Office can’t figure out how to listen to events raised by your provider.  However, you can use Visual Basic.NET if you want.  If you choose the C/C++ route the writing of the IDL will be a little more straight forward.  However, if you choose .NET you will have to write the COM Interface definitions yourself.

Gross! I have to write my own interface definitions?!

Yep that’s right.  Remember, when you use this API you are mimicking the behavior of Office Communicator / Lync on the machine.  However, Office Communicator / Lync will not be present.  Therefore, you need to have a type library or Proxy / Stub Dll that will help COM marshal the objects from your provider to Office and back.  If these are not present then Office will fail to interact with your provider.  The type library that ships with Office Communicator / Lync cannot be redistributed with your solution.  You must build you own and properly register it on the machine. For C/C++ solutions built using the Active Template Library (ATL) this is easy because the work is done for you.  For .NET based solutions you must register the type library yourself.

How to troubleshoot my provider

If using Office 2007 and Office 2010 you can use the Presence Logs to figure out where Office is failing when interacting with your provider.  You can turn on Presence Logging by creating the following registry key:

Hive: HKEY_CURRENT_USER

Key Name: Software\IM Providers

Value: OfficePresenceLogging

Data: 1 | 0 – 1 means enabled, 0 means disabled.

Make sure you create the directory %userprofile%\tracing before you attempt to start the Office application you are working in.

For Office 2013, this is a little more difficult.  The logging mechanism was ported to use the built-in Event Tracing for Windows (ETW) architecture.  Therefore you can no longer use this method in 2013.  However, I am working on a way to enable this functionality.  I will update this post when I have something for you.

Wow, how exciting! I want to start now, do I have to wait for you to finish this series?

No, you can read the documentation that was published on MSDN for a full high level overview.  You can find the article here

PRXF_IGNORE_SEC_WARNING doesn’t work in MAPI CDO

$
0
0

The flag PRXF_IGNORE_SEC_WARNING doesn’t work in MAPI \ CDO as it should.  The flag was introduced to support RPC over HTTP in the updated MAPI \ CDO that was released around the time of Exchange Server 2013’s release.  The flag is supposed to instruct the MAPI subsystem to use this flag RPC_C_HTTP_FLAG_IGNORE_CERT_CN_INVALID when configuring the connection to Exchange using RPC over HTTP.  However, due to a code defect, it only sets this flag on the connection to the Addressbook.  It doesn’t set this flag on the connection to the Exchange Server.  Therefore, it won’t ignore the certificate if the CN is invalid.

Additionally, RPC will not ignore certificates that come from a Certificate Authority that is not trusted.  This is by-design for RPC over HTTP.  This is generally true of self-signed certificates.  In this case you will have to fully trust the certificate to get around this limitation.  You can trust it by adding the certificate to the Trusted Certificate Authorities on the machine.  Note: You should only do this for certificates you trust.

Automatic reply: Your Out of Office code may no longer work

$
0
0

In Exchange 2007, Out of Office (OOF) was improved and how the mechanism worked was changed.  To support legacy Outlook 2003 clients which didn’t use SetUserOofSettings like Outlook 2007 and Outlook Web App 2007 did, the Out of Office Mailbox Assistant was created. The OOF Mailbox Assistant had several responsibilities, here are the ones relevant to the situation:

  • Detect when the legacy OOF message and rule were changed
  • Apply any changes to the legacy OOF message and rule to the new OOF message
  • Update some internal properties as necessary, for example the start and end time of OOF.

Since Exchange Server 2013 does not support Outlook 2003 as a client, this assistant was seen as unnecessary and removed.  The responsibilities of the mailbox assistant were merged into the SetUserOofSettings operation.

Extended MAPI Developers using KB 308281 as their basis for updating Out of Office in their applications may have noticed that the code no longer works in Exchange Server 2013. This is because the Out of Office Mailbox Assistant was removed and therefore won’t do the behind the scenes work to keep the legacy Out of Office message (the one used in the KB) and the new one created in Exchange 2007 in sync.  Since Exchange 2013 only looks at the Exchange 2007 based Out of Office message any changes to the legacy Out of Office message rule are ignored.

To fix this, the recommended approach is to use Exchange Web Services (EWS) and the SetUsersOofSettings operation.

SetUserOofSettings

http://msdn.microsoft.com/en-us/library/office/aa580294(v=exchg.150).aspx


Using the EmailMessage.Normalize method in a transport agent causes issues with Exchange Server 2013 CU7

$
0
0

I received a report that if you have an existing transport agent and use the method Microsoft.Exchange.Data.Transport.Email.EmailMessage.Normalize(), the transport agent won’t work correctly on Exchange Server 2013 CU7.  This is because of a known issue where the public signature of this method was changed and so existing transport agents will need to be recompiled to work with Exchange Server 2013 CU7.  This issue will be addressed in a future update to the product. In the meantime, you should recompile using the new method signature and maintain that code base until the update containing the fix is released publicly.

EmailMessage.Normalize method

https://msdn.microsoft.com/en-us/library/office/microsoft.exchange.data.transport.email.emailmessage.normalize(v=exchg.150).aspx

HrGetServerDN fails with MAPI_E_CALL_FAILED (0x80004005)

$
0
0

In Exchange 2013 Cumulative Update 3, Exchange stopped stamping the property HomeMTA on the user object in Active Directory. As a result PR_EMS_AB_HOME_MTA_A, a property that HrGetServerDN() depends on no longer works.  HrGetServerDN() is a function from the Exchange Development Kit (EDK) for Exchange 5.5.  It is not supported or recommended for any version of Exchange except Exchange 5.5.  You can still get the full source for the EDK if you know who to ask.

To work around this issue use an alternate mechanism to achieve your goal of getting the ServerDN for a particular user.  The recommend approach is to use the Plain Old XML (POX) Autodiscover and pull the necessary information in that way. If you are using Exchange 2013 you should be using the POX Autodicover anyway to retrieve data about the user to build a profile.

More Information

Cool MFCMAPI Feature: Logging every MAPI function called

$
0
0

Wanna learn Extended MAPI?  Sure, we all do.  Well most likely not, but in every project there comes a time when you need to add a feature and you don’t know where to start.  MFCMAPI can be helpful in figuring out what to do in Extended MAPI if you don’t know where to start. Here is what you do. Open up MFCMAPI and go to “Tools > Debug View…”.  If you are a keyboard kind of guy like myself, you can press CTRL+D instead.  This will launch the Debug Viewer Dialog.  The Debug Viewer can be used for lot of things, but in this case try turning on logging for MAPI Functions. To do that, set the Debug Flags to 0x40000000 (DBGMAPIFunctions).

Now as you navigate the store or perform specific operations in the user interface, the Debug Viewer will show you what MAPI functions are being called. This can give you a high level overview of what a program or a feature doing the same thing should do in MAPI.  Want more detail?  It also outputs the line numbers and the source file where the call can be found.  Since the source code is available on CodePlex you can browse it to see exactly how the objects were manipulated.

It’s a pretty cool feature and one that is a hidden gem. I plan to share more of these as time permits so you too can be a MFCMAPI Power user.

MAPI CDO will not be supported for Exchange 2016

$
0
0

I wanted to point out a significant note for some in the Exchange 2016 Architecture blog post here : http://blogs.technet.com/b/exchange/archive/2015/05/05/exchange-server-2016-architecture.aspx.  Specifically, that Exchange 2016 will not support clients using Exchange’s MAPI (aka MAPI \ CDO) to access Exchange Data.  Exchange’s MAPI has been out of main stream support for some time now (as it’s tied to the lifecycle of Exchange 2003), so it isn’t a surprise that Exchange 2016 will no longer allow it.  However, for some ISVs and vendors still relying on MAPI \ CDO this is important note.  The time to start planning and developing the next version of your product is now so you are ready when Exchange 2016 ships.

How to configure an Outlook 2016 profile using MFCMAPI

$
0
0

The process for creating a Outlook profile in Outlook 2016 has changed. This article documents the simple steps to create one using MFCMAPI.  Note: For non-developers this is not the recommended way of creating profiles in Outlook 2016.  It is recommended that you use Outlook to create the profile as the logic for this is all built-in.  However, you can use these steps for troubleshooting purposes.

  1. Open up MFCMAPI, go to Profile > Show Profiles
  2. Click Actions > Create Profile

  1. Give the new profile a name and click OK.

  1. Select the new profile

  1. Type MSEMS for the service name
  2. Uncheck the box which says “Display Service UI”

  1. Click OK
  2. Double-Click the newly created profile.
  3. Single-Click the MSEMS service.
  4. Find the Exchange Profile section. This is a little difficult in Outlook’s MAPI since in 2010 and above we no longer have the global profile section. To find the Exchange Profile Section find the property PR_EMSMDB_SECTION_UID (0x3D150102) in the properties for the service. The value will be the GUID of the profile section persisted in binary form which will be used in the subsequent steps. You will need to remember this value.
  5. Double-Click the MSEMS service.
  6. Find the Exchange profile section by using the UID gathered from Step 10 and single-click it to select the row.
  7. Go to Property > Additional Properties

  1. Click Add and add the following properties PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W (0x6641001F) and PR_DISPLAY_NAME_W.

  1. Click OK
  2. Configure each property using the guidance below.
Property: PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W
Value: SMTP Address of the user
Property: PR_DISPLAY_NAME_W
Value: The display name of the user
  1. Find the property PR_STORE_PROVIDERS in the Exchange profile section.  This is the EMSMDB profile section.  Note the value of it.

  1. Find the corresponding profile section whose UID matches the value of PR_STORE_PROVIDERS.
  2. Repeat Steps 13 – 17 for that profile section too.

  1. Select Session > Logon and display store, and select the profile if it is not already selected.
  2. You may be prompted for credentials, but it should work successfully.

More Information

The display name on the Exchange profile section is not required, but I included it here for simplicity.

In Step 14, it is okay if the property name is not resolved to PR_PROFILE_USER_SMTP_EMAIL_ADDRESS_W.

Sample code can be found here that shows you how to do this programmatically.


IMAPISession::OpenMsgStore() returns MAPI_E_VERSION (0x80040110)

$
0
0

As documented previously, Exchange 2016 will not allow connections from Exchange’s MAPI (aka MAPI \ CDO).  MAPI client applications may receive the error MAPI_E_VERSION (0x80040110).  If you are running On-Premises Exchange 2016 and have access to the RPC Client Access logs, you will see this error in the log around the time that the connection was attempted:

RpcDispatch: [RpcServerException] Client version 6.0.XXXX.0 is below the minimum required version 10.0.0.0. (StoreError=Version)

The recommended approach is to use Exchange Web Services or the REST APIs to access the Exchange mailbox.  As a temporary workaround you could try porting the MAPI client application to Outlook’s MAPI, but Outlook’s MAPI can’t log into Recovery Databases and have other nuances that may make this not viable.

MAPILogonEx causes crash if Version Info is not specified on the module

$
0
0

I wanted to create a simple Extended MAPI application that would call MAPIInitialize() followed by MAPILogonEx().  Seems simple right?  I do it all the time.  However, this time, for whatever reason, every time I called MAPILogonEx() my process crashed.  No matter what flags I chose, or how I called either MAPIInitialize() or MAPILogonEx(), it would crash.  I was perplexed. I’ve written ton of MAPI code and never got an error like this.  After debugging it I realized that Office¹ requires that the application include file version information.  If the path to the application is too long or the application doesn’t have file version information, Office¹ will force a crash of the application. I believe it does this for the Help.  Here are some ways you can recognize this problem.  First, you’ll see a stack similar to this in Visual Studio:

kb
 Index  Function
--------------------------------------------------------------------------------
 1      Mso98win32client.dll!6d08313b()
 2      [Frames below may be incorrect and/or missing, no symbols loaded for Mso98win32client.dll]
 3      Mso98win32client.dll!6d07c374()
 4      vcruntime140.dll!7400d627()
 5      vcruntime140.dll!7400e882()
 6      vcruntime140.dll!740036e8()
 7      vcruntime140.dll!74003654()
 8      vcruntime140.dll!74003215()
 9      vcruntime140.dll!74002f88()
 10     vcruntime140.dll!7400ec26()
 11     ntdll.dll!77d3b652()
 12     ntdll.dll!77d3b624()
 13     ntdll.dll!77d1420b()
 14     ntdll.dll!77d28e7f()
 15     KernelBase.dll!766802c5()
 16     KernelBase.dll!76695468()
 17     vcruntime140.dll!740049a5()
 18     Mso98win32client.dll!6d07c4fe()
 19     Mso98win32client.dll!6d02b65a()
 20     OLMAPI32.DLL!6f53a7b0()
 21     Mso20win32client.dll!6f2eee84()
 22     Mso20win32client.dll!6f2eec62()
 23     Mso20win32client.dll!6f2ece9c()
 24     Mso20win32client.dll!6f2f40f5()
 25     OLMAPI32.DLL!6f5393db()
 26     OLMAPI32.DLL!6f5393bd()
 27     OLMAPI32.DLL!6f54e8bb()
 28     OLMAPI32.DLL!6f54dd36()
 29     OLMAPI32.DLL!6f54cb9b()
 30     OLMAPI32.DLL!6f5446a5()
 31     OLMAPI32.DLL!6f543eff()
 32     MSMAPI32.DLL!51974e3d()
*33     YourAppHere.exe!MAPILogonEx(unsigned long a=0x00000000, wchar_t * b=0x00000000, wchar_t * c=0x00000000, unsigned long d=0x0000003b, IMAPISession * * e=0x0286f870)
 34     YourAppHere.exe!WorkerThread(void * state=0x008ff74c)
 35     msvcr120d.dll!5a2c3651()
 36     msvcr120d.dll!5a2c3861()
 37     kernel32.dll!772338f4()
 38     ntdll.dll!77d15de3()
 39     ntdll.dll!77d15dae()

and an error message that says Unhandled exception at 0x6D08313B (Mso98win32client.dll) in YourAppHere.exe: 0x0128300C (parameters: 0x00000001, 0x00000000).

Now, fixing this is easy if you know what to do.  In Visual Studio, just add the resource type “Version” and fill in the various fields for your application.  Next, Clean the solution, and Rebuild. I find that if I don’t Clean and Rebuild, it doesn’t fix the issue.  That’s it. After that it should work.  This was a big blocker for me, but I suppose that for people building real world applications this won’t be a problem since they’ll have this included in their applications anyway.  Only little test applications would be affected.

¹ I use this term rather than Outlook because this isn’t Outlook’s doing.  This is “shared Office code” that causes this, not Outlook.


MAPILogonEx() may appear to hang in Outlook 2016

$
0
0

I had a case recently where the customer was had written a service application using Extended MAPI.  The customer found that in his test environment the call to MAPILogonEx() was hanging and not returning.  After debugging it, we realized that the hang was caused by an unseen SSL security prompt.  The target Exchange server hosting Autodiscover was using a self-signed certificate.  Because the transport being used was RPC over HTTP (ROH) and the certificate was untrusted by the client, Outlook was prompting the “user” to accept the use of the certificate.  Since this was a service application and there was no one to accept the prompt, MAPILogonEx() would hang.  Ultimately, this is a by-design issue with ROH.  ROH doesn’t allow you to “trust” certain types of security prompts, although you really wouldn’t want to anyhow.  Since Outlook can’t proceed without someone trusting the certificate, it needs to prompt.  To workaround this, the developer has two options:

  1. Use only trusted certificates for your Exchange Server.  Even in the scenario of a self-signed certificate, you can manually trust the certificate or possibly create a GPO for all machines in the organization to trust it.
  2. Use the registry value outlined in this article:
    Outlook 2016 displays a prompt that lets you connect to an Exchange server if a certificate issue occurs https://support.microsoft.com/en-us/kb/3114926

If you use the latter, understand that the request will fail and that should cause MAPILogonEx() to fail. However, the failure not may be immediately obvious.  You may not see the result of the failure until a subsequent call to MAPI (e.g. IMAPISession::OpenMsgStore()).

Programmatically connecting to another mailbox when MAPI / HTTP is used

$
0
0

I’ve been meaning to create this post for a while, but haven’t got around to it. I had a case recently where a customer wanted to connect to a user’s Archive mailbox for which the service application had permissions.  However, the transport in use was MAPI over HTTP (MAPI/HTTP).  He was getting the error MAPI_E_CALL_FAILED (0x80004005) from the call to IMAPISession::OpenMsgStore().  His code worked when the transport was RPC over HTTP (ROH).

Introduction

When a MAPI client application attempts to connect to multiple mailboxes using a “hub and spoke” type approach, wherein the MAPI application connects to an initial mailbox and then connects to additional mailboxes for some sort of processing, if the transport in use is MAPI/HTTP, IMAPISession::OpenMsgStore() returns MAPI_E_CALL_FAILED (0x80004005).  This may be because the EntryID passed to OpenMsgStore() is not valid.  The EntryID needed to connect using MAPI/HTTP is a version 3 (v3) EntryID.  IExchangeManageStore::CreateStoreEntryID() can only create version 1 (v1) EntryIDs.  After all, this method was created for the early versions of Exchange Server.  Therefore, a new interface is needed in order to create v3 EntryIDs.  Enter IExchangeManageStoreEx.  This interface was previously documented in a former blog post.  However, the method CreateStoreEntryID2() takes additional data.

First,  you will need to define the new property PR_PROFILE_USER_SMTP_ADDRESS_W in your code base.

// 0x6641001F
#define PR_PROFILE_USER_SMTP_ADDRESS_W PROP_TAG(PT_UNICODE, 0x6641)

Next, you add that to the list of properties passed to the method CreateStoreEntryID2(). This property is what is used by Outlook to perform an Autodiscover to get the mailbox settings for the target mailbox.

LPSPropValue         lpspv = nullptr;
MAPIAllocateBuffer((sizeof(SPropValue) * 4), (LPVOID*)&lpspv);
ZeroMemory(lpspv, sizeof(SPropValue) * 4);

lpspv[0].ulPropTag = PR_PROFILE_MAILBOX;
lpspv[0].Value.lpszA = TargetMailboxDN;

lpspv[1].ulPropTag = PR_PROFILE_MDB_DN;
lpspv[1].Value.lpszA = TargetStoreDN;

lpspv[2].ulPropTag = PR_FORCE_USE_ENTRYID_SERVER;
lpspv[2].Value.b = true;

lpspv[3].ulPropTag = PR_PROFILE_USER_SMTP_ADDRESS_W;
lpspv[3].Value.lpszW = L"Susan@Contoso.com";

hres = m_pMsgPrivStore->QueryInterface(IID_IExchangeManageStoreEx,
                                                                     (LPVOID*)&pManageStoreEx);
if (FAILED(hRes) || pManageStoreEx == nullptr)
{
    // Handle the error
    goto Cleanup;
}

hRes = pManageStoreEx->CreateStoreEntryID2(3,
                        lpspv,
                        ulCreateStoreEIDFlags,
                        &cbEID,
                        &lpEntryId);
Cleanup:
MAPIFreeBuffer(lpsv);

From there you call IMAPISession::OpenMsgStore() as you did before passing the v3 EntryID you obtained from the call to IExchangeManageStoreEx::CreateStoreEntryID2().

More Information

How to indicate that a profile targets a consumer account

$
0
0

I had a case recently where the customer was using my post for creating a Outlook 2016 profile programmatically and found that the program would hang when performing certain MAPI operations.  This only happened when the profile was created programmatically (i.e. not through the Outlook UI or the Mail applet) and the target account was an Outlook.com account.  As you may be aware, Outlook.com addresses are being migrated to Exchange as the backend and Extended MAPI can be used to consume them.  The root cause of the issue was that Outlook uses the PR_PROFILE_EXCHANGE_CONSUMER_ACCOUNT property to determine if the target account is a “consumer account”.  If so, certain MAPI operations are avoided.  For example, creation of a Global Address Book (GAL).  Thus, if you are programmatically creating a MAPI profile that targets an Outlook.com address you need to pre-populate this property yourself.  This begs the question, “How do you know if the account is a consumer account?”  There are several ways that you can tell: First, you could look at the domain, if it’s Outlook.com or Hotmail.com, then chances are high that it’s a consumer account. If you want to be 100% sure, you could perform an Autodiscover on the target address and let Exchange tell you.  In the Autodiscover response you’ll consult the element ‘ConsumerMailbox’ in the Accounts section of the response.  True means that it is, otherwise False. Once you have that data, you’ll need to set the PR_PROFILE_EXCHANGE_CONSUMER_ACCOUNT property to what the Autodiscover response was.  If the target account is not a consumer account you can omit it completely.  You’ll need to set this property on the profile section identified as the “EMSMDB Section”.  You can query for the property PR_PROFILE_EMSMDB_SECTIONID and that’ll give you the MAPIUID of this profile section.  You must do this before you follow the instructions in my post.  Lastly, the profile must be a cached mode profile.  This property goes hand in hand with cached mode profiles.  Setting this property without indicating that the profile is a cached mode profile will result in undefined behavior.

Additional Information

You’ll need to define the property in your application to use it.  This property is not included in any of the MAPI headers.  I’ve included that below:

#define PR_PROFILE_EXCHANGE_CONSUMER_ACCOUNT PROP_TAG(0x00B, 0x665e)

At the time of this writing, in order to get the property from Autodiscover, the Exchange Server must think that an Outlook for Windows client is asking for it.  Therefore, you must set the User-Agent of the program making the HTTP request to the value that an Outlook for Windows client would use.  I’ll edit this post when this is addressed.

Access to the Recovery Database in Exchange Server 2016 from an application

$
0
0

I have had several customers interested in how to access the Recovery Database (RDB) programmatically in Exchange 2016.  Extended MAPI is the only way to access the Recovery Database programatically.  The Exchange MAPI subsystem (aka MAPI\CDO) is the only subsystem capable of accessing the Recovery Database.  This is because access to the Recovery database requires the use of the flag OPENSTORE_RECOVERY_DATABASE (0x100000).  This flag is not available in the Outlook MAPI subsystem.  If you try to use it from Outlook’s MAPI, the call to IMAPISession::OpenMsgStore() will fail with MAPI_E_UNKNOWN_FLAGS (0x80040106). Therefore, you are forced to use the Exchange MAPI subsystem.  As you know, Exchange Server 2016 has an explicit block in place that prevents from clients using the Exchange MAPI subsystem.

A programmatic alternative to MAPI  to access the RDB is through the use of Exchange Powershell’s New-MailboxRestoreRequest cmdlet.  You could then restore the data to a temporary mailbox in a normal mailbox database.  Once there, you could use Exchange Web Services or the Outlook Mail REST APIs to access that data. The user of your application never has to know about this temporary mailbox.  It could only be accessible by your application.  Your application could then find whatever it is that it’s looking for and then only restore that particular data to the end user’s mailbox.  Previous versions of Exchange Server support both EWS and this cmdlet so this architecture could work going back to Exchange 2010. That’s probably the furthest you’ll want to go back anyhow.

How to create an profile that uses MAPI/HTTP in Outlook 2013

$
0
0

I had a case recently where the customer wanted to know how to programmatically create a MAPI over HTTP profile using Outlook 2013. A few years ago I had developed a little sample to do just that, but I never posted it.  Therefore, today I’m fixing my omission.  You can view the sample code here.

Viewing all 62 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>