It;’s here! It’s finally here! The May 2013 update of MAPICDO is live here:
http://www.microsoft.com/en-us/download/details.aspx?id=39045
At that same link, you’ll also find the long awaited configuration guidance. It’s not immediately obvious it’s there. Just hit the Download link and it will be offered to you. As a reminder, this configuration guidance will help you in configuring an RPC/HTTP (aka ROH) profile using this MAPI/CDO download package. These instructions do NOT apply equally to Outlook’s implementation of MAPI. Attempting to use these guidelines to build a profile for Outlook’s MAPI, or attempting to “port” a profile between the two implementations WILL lead to failure.
Installation details:
Fixes:
Enjoy!
Recently, I’ve had a few different customers coming to me asking about Outlook’s interaction with the Credential Manager. If you’ve not looked at the Credential Manager before, you can read a bit about it here. Interaction with the Credential Manager is fairly straightforward. There’s one function, CredWrite, which is used to store credentials, and another, CredRead, which is used to retrieve them. The customers who contacted me both had the same goal: use CredWrite to cache a set of credentials for Outlook to use so the user isn’t prompted for a password.
While this seems a simple request, it turns out that once you start considering all the various scenarios for which Outlook has to cache credentials (O365, Exchange on-Premise, machine in the domain versus out of the domain, multiple profiles, multiple credentials for a single profile), it gets complicated real fast. Even if you figure out how to cache credentials for Outlook to use for one scenario, a slight change to that scenario means the credentials have to be cached differently. So while the set of functions to be used in managing credentials is simple, the logic that goes into making these calls is very complex. We ran this by development just to make sure, but the results were as we expected: We cannot support any third party manipulation of the credentials used by Outlook. If a user wants to cache credentials, they need to enter them at the credential prompt.
Anybody remember that Message Header Analyzer App for Office I wrote about last month? Well, the folks who do support for Exchange and Office 365 caught wind of it and liked it. In fact, they liked it so much they asked me to port the code into their Remove Connectivity Analyzer. Here’s the blog entry they just put up yesterday announcing this:
http://blogs.technet.com/b/exchange/archive/2013/05/01/introducing-message-analyzer-an-smtp-header-analysis-tool-in-microsoft-remote-connectivity-analzyer.aspx
So even if you don’t have Exchange 2013, you can still use the Message Header Analyzer by going to https://testconnectivity.microsoft.com/?tabid=mha. Feature requests and bug reports can either be directed through the feedback link on that site or by contacting me.
The March 2013 Second Release (build 15.0.0.1039) is live: http://mfcmapi.codeplex.com.
This is an emergency build to correct a problem a few people were having running MFCMAPI on Windows XP.
Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code:
Enjoy.
The March 2013 Release (build 15.0.0.1038) is live: http://mfcmapi.codeplex.com.
A few smaller changes this round: I’ve upgraded the project to support Visual Studio 2012. I also fixed a bug in the new PST parsing, and inserted a new dialog into the “Open from GAL” path to give the user the opportunity to adjust the server DN (this should help in testing Exchange 2013 scenarios).
So – I’ve been playing a lot with Apps for Office lately. I even wrote and published an app:
http://office.microsoft.com/en-us/store/message-header-analyzer-WA104005406.aspx
My management encouraged me to put together a presentation on everything I learned while developing this app. I did, and they asked me to record a video of me delivering this presentation. So – now you all get to hear me drone on about App development. Here’s the entry on the Partner Technical Services blog containing my presentation:
http://blogs.technet.com/b/ptsblog/archive/2013/03/20/microsoft-office-lessons-learned-developing-apps-for-the-office-store.aspx
And here’s the direct YouTube link:
and the direct link to the slide deck:
https://skydrive.live.com/view.aspx/Documents/AppsForOffice.pptx?cid=8d22925062e717b6&id=documents&authkey=!AOsqoQIn-Xb4nBk&&wdSlideId=274
In case you don’t want to dig through the slide deck for the links I reference, here they all are:
Finally, my JQuery EWS parsing trick:
(function ($) { $.fn.filterNode = function (name) { return this.find('*').filter(function () { return this.nodeName === name; }); }; })(jQuery); function callback(asyncResult) { var response = $.parseXML(asyncResult.value); var responseDOM = $(response); var Prop = responseDOM.filterNode("t:InternetMessageHeaders")[0];
(function ($) {
$.fn.filterNode = function (name) {
return this.find('*').filter(function () {
return this.nodeName === name;
});
};
})(jQuery);
function callback(asyncResult) {
var response = $.parseXML(asyncResult.value);
var responseDOM = $(response);
var Prop = responseDOM.filterNode("t:InternetMessageHeaders")[0];
As several of you have noted, we recently released an update for the MAPICDO package. This is the update you have all been waiting for, as it is now possible to build an RPC/HTTP enabled profile to connect to Exchange 2013. What several of you have also noticed is that this update did NOT come with any guidance for HOW to build such a profile. Such guidance does exist, but hasn’t been published yet. I had delayed commenting on this new package until the guidance was ready, but it’s taking longer than I thought it would.
I’m working with the team responsible for publishing the guidance to get it out the door. We’ve almost got it ready, so I expect to see it up on the download site (or the Exchange blog) any day now. Once that guidance is published, Dave will most likely publish an updated version of his How to Build a Profile For MFCMAPI guidance. I’ll link to both as soon as they’re public.
http://msdn.microsoft.com/en-us/library/ee159108(v=exchg.80).aspxIf you’ve got an application that processes e-mails paying attention to the PR_RECEIVED_BY_* and PR_RCVD_REPRESENTING_* properties, you may notice these properties showing up on e-mails in the Sent Items folders of your users. That is, messages submitted by a user who doesn’t explicitly mark themselves as a recipient will still appear (in these properties) as if they received the message. This may interfere with your logic, especially if you have a need to distinguish mails a user sent from mails a user received.
Before we get into an explanation of why this is happening, some workarounds:
Together, you should be able to use these properties to heuristically decide if a message was, from the user’s perspective, sent or received. And do note that any algorithm you put together here will by necessity be a heuristic. There is no single property that tracks whether a message in a user’s mailbox was sent by the user, received by the user, neither, or both.
Now – when/why does Exchange 2013 stamp these properties? When first: It appears Exchange 2013 will stamp these properties when Outlook (any version) submits a mail from a profile with only one Exchange mailbox in it. These properties will then be present on the copy of the message which ends up in Sent Items (or wherever the sent copy is to be saved). If the profile contains multiple Exchange accounts (aka Multi-Ex, possible in Outlook 2010 and higher), then Exchange 2013 does not appear to stamp these properties on the message that ends up in Sent Items.
Why: Exchange 2013 has a completely new store, written in managed code (the old, native, store.exe no longer exists). As part of this work, we found that it was possible for the transport to attempt to deliver a message multiple times. Part of the work involved in making sure this didn’t happen was to ensure these properties were set on messages as we processed them for transport. The difference in behavior with Multi-Ex is attributable to the fact that Outlook builds the messages it intends to submit differently in Multi-Ex.
It was suggested to me that this change in behavior means our documentation is now incorrect. I do not agree with this assessment. For instance, here’s a snippet from the MSDN documentation of PR_RECEIVED_BY_NAME:
Contains the display name of the messaging user who receives the message...These properties are an example of the address properties for the messaging user who receives the message. They must be set by the incoming transport provider.
And the [MS-OXOMSG] protocol doc:
The PidTagReceivedByName property ([MS-OXPROPS] section 2.961) contains the e-mail message receiver's display name, as specified by the DisplayName field of the RecipientRow structure ([MS-OXCDATA] section 2.8.3.2).
Note that the documentation does not indicate anything about what should or should not be present on sent items. It only documents these properties in relation to received messages. What happens with sent messages is undefined behavior, so any behavior is acceptable, as is changing behavior. I’m sending this article over to the protocol team, however, so they can note this behavior with respect to Exchange 2013.
Some of you may have already noticed this by now, but the logic used to load MAPI providers has changed in Outlook 2013. Previously, we would use LoadLibrary to load a MAPI provider. This API has logic in it to search the user’s PATH for the provider, which is great if you placed the provider somewhere on the user’s PATH. In Outlook 2013, though, we call LoadLibraryEx, passing the LOAD_LIBRARY_SEARCH_DEFAULT_DIRS flag. The effect of this flag is that Outlook no longer searches the path.
Fortunately, you can still put your provider wherever you want by putting the full path in MAPISVC.INF. You may need to rethink how you load your own dependencies, but now that you know what’s going on that problem shouldn’t be insurmountable. BTW – Process Monitor is invaluable in investigating this sort of issue.
The January 2013 Release (build 15.0.0.1037) is live: http://mfcmapi.codeplex.com.
We’ve been working a few issues lately related to the size of a OST versus the size of a mailbox. I’ve added some features to MrMAPI to aid in these sorts of issues. First is the –Size switch, which calculates the size of all the items in a folder and it’s subfolders. You can combine it with the –Folder switch to get the size of any folder. For instance, using the @2 notation to refer to the Contacts folder, I can get the size in my own mailbox as follows:
C:\>mrmapi -size -f "@2" Folder size (including subfolders) Bytes: 388867 KB: 379 MB: 0
C:\>mrmapi -size -f "@2"
Folder size (including subfolders)
Bytes: 388867
KB: 379
MB: 0
The second feature uses the documentation of the PST file format to read the header of a PST/OST file and report free space. Note that this does require that the file not be loaded in Outlook when you run it. Simply closing Outlook is sufficient. Here’s an example run against an OST here:
C:\>mrmapi -pst -i c:\Users\sgriffin\AppData\Local\Microsoft\Outlook\outlook.ost Analyzing c:\Users\sgriffin\AppData\Local\Microsoft\Outlook\outlook.ost Unicode PST File Size = 2.71 GB (2911577088 bytes) Free Space = 1.05 GB (1132028480 bytes) Percent free = 38.88%
C:\>mrmapi -pst -i c:\Users\sgriffin\AppData\Local\Microsoft\Outlook\outlook.ost
Analyzing c:\Users\sgriffin\AppData\Local\Microsoft\Outlook\outlook.ost
Unicode PST
File Size = 2.71 GB (2911577088 bytes)
Free Space = 1.05 GB (1132028480 bytes)
Percent free = 38.88%
I’ve just checked in a fix for the Wrapped PST sample that should allow it to work with Outlook 2013. Let me know if you find any problems with the sample. I haven’t tested the other samples yet as they don’t appear to get as much attention as the wrapped PST.
Here’s a nice article on choosing between mail apps and add-ins for Outlook development:
http://blogs.msdn.com/b/officedevdocs/archive/2012/12/10/when-should-i-choose-to-create-a-mail-app-versus-an-add-in-for-outlook.aspx
Bottom line: if you can do what you need to do from a mail app, it’s the way to go, especially since apps developed for Outlook will work in OWA..
In my previous post, we discussed how to locate Outlook’s POP3 UIDL history. Now that we have the blob, let’s look at how to parse it:
A resource tag encodes a UID with some metadata. The format of a resource tag string is represented as follows:
Mcyyyymmddhhmmssuuuuuuuuuuuuuuuuuu...
where
The encoded uid of the message has been escaped so only alphanumeric characters and the character '$' are present. Non-alphanumeric characters in the original UID are represented as '$'+ 2 digit hex encoding. For instance, the character '-' is encoded in the UID as $2d
For example, this blob:
030017002B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 2B623230313230393036313331313337313433444242434224326445413636243264313145312432644135463224326430303232363443313534424100 2B623230313230393036313331313339323445383833333324326445413334243264313145312432644133414324326430303231354144374631353600 2B623230313230393036313331313336333446324533383124326445423236243264313145312432644244353924326430303231354144383043324300 2B623230313230393036313331313339333733443545363924326445413236243264313145312432644231363024326430303231354144393946303000 ...
030017002B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400
2B623230313230393036313331313337313433444242434224326445413636243264313145312432644135463224326430303232363443313534424100
2B623230313230393036313331313339323445383833333324326445413334243264313145312432644133414324326430303231354144374631353600
2B623230313230393036313331313336333446324533383124326445423236243264313145312432644244353924326430303231354144383043324300
2B623230313230393036313331313339333733443545363924326445413236243264313145312432644231363024326430303231354144393946303000
...
0300 Version: PBLOB_VERSION_NUM 1700 Count: Count of restags (0x17 = 23) 2B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 Tag 1 2B623230313230393036313331313337313433444242434224326445413636243264313145312432644135463224326430303232363443313534424100 Tag 2 2B623230313230393036313331313339323445383833333324326445413334243264313145312432644133414324326430303231354144374631353600 Tag 3 2B623230313230393036313331313336333446324533383124326445423236243264313145312432644244353924326430303231354144383043324300 Tag 4 2B623230313230393036313331313339333733443545363924326445413236243264313145312432644231363024326430303231354144393946303000 Tag 5 ...
0300 Version: PBLOB_VERSION_NUM
1700 Count: Count of restags (0x17 = 23)
2B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 Tag 1
2B623230313230393036313331313337313433444242434224326445413636243264313145312432644135463224326430303232363443313534424100 Tag 2
2B623230313230393036313331313339323445383833333324326445413334243264313145312432644133414324326430303231354144374631353600 Tag 3
2B623230313230393036313331313336333446324533383124326445423236243264313145312432644244353924326430303231354144383043324300 Tag 4
2B623230313230393036313331313339333733443545363924326445413236243264313145312432644231363024326430303231354144393946303000 Tag 5
2B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 = "+b201209061311380BC535DB$2dEA63$2d11E1$2dA75C$2d00215AD7BB74" + = Successful get b = Content is body 2012 = Year 09 = Month 06 = Day 13 = Hour 11 = Minute 38 = Second 0BC535DB$2dEA63$2d11E1$2dA75C$2d00215AD7BB74 = UID
2B623230313230393036313331313338304243353335444224326445413633243264313145312432644137354324326430303231354144374242373400 =
"+b201209061311380BC535DB$2dEA63$2d11E1$2dA75C$2d00215AD7BB74"
+ = Successful get
b = Content is body
2012 = Year
09 = Month
06 = Day
13 = Hour
11 = Minute
38 = Second
0BC535DB$2dEA63$2d11E1$2dA75C$2d00215AD7BB74 = UID
0BC535DB + $2d + EA63 + $2d + 11E1 + $2d + A75C + $2d + 00215AD7BB74 = 0BC535DB + '-' + EA63 + '-' + 11E1 + '-' + A75C + '-' + 00215AD7BB74 = 0BC535DB-EA63-11E1-A75C-00215AD7BB74
0BC535DB + $2d + EA63 + $2d + 11E1 + $2d + A75C + $2d + 00215AD7BB74 =
0BC535DB + '-' + EA63 + '-' + 11E1 + '-' + A75C + '-' + 00215AD7BB74 =
0BC535DB-EA63-11E1-A75C-00215AD7BB74
So the first UID encoded in this blob is "0BC535DB-EA63-11E1-A75C-00215AD7BB74", and the body was successfully retrieved on 9/6/2012 at 13:11:38.
When Outlook’s POP3 provider syncs with a POP3 mailbox and the user chooses to leave a copy of the messages on the server, it has to remember which messages it has already downloaded so it doesn’t accidently download the same message twice. It does this by tracking the UIDL of each message it has downloaded in a binary property on a hidden message. This post describes how Outlook locates this binary property. My next post will detail how to parse this property.
SRestriction rgRes[3]; SPropValue rgProps[3]; rgRes[0].rt = RES_AND; rgRes[0].res.resAnd.cRes = 2; rgRes[0].res.resAnd.lpRes = &rgRes[1]; rgRes[1].rt = RES_PROPERTY; rgRes[1].res.resProperty.relop = RELOP_EQ; rgRes[1].res.resProperty.ulPropTag = PR_CONVERSATION_KEY; rgRes[1].res.resProperty.lpProp = &rgProps[0]; rgRes[2].rt = RES_PROPERTY; rgRes[2].res.resProperty.relop = RELOP_EQ; rgRes[2].res.resProperty.ulPropTag = PR_MESSAGE_CLASS; rgRes[2].res.resProperty.lpProp = &rgProps[1]; rgProps[0].ulPropTag = PR_CONVERSATION_KEY; rgProps[0].Value.bin = pVals[iSearchKey].Value.bin; // PR_SEARCH_KEY from the profile rgProps[1].ulPropTag = PR_MESSAGE_CLASS; rgProps[1].Value.LPSZ = (LPTSTR)"IPM.MessageManager";
SRestriction rgRes[3];
SPropValue rgProps[3];
rgRes[0].rt = RES_AND;
rgRes[0].res.resAnd.cRes = 2;
rgRes[0].res.resAnd.lpRes = &rgRes[1];
rgRes[1].rt = RES_PROPERTY;
rgRes[1].res.resProperty.relop = RELOP_EQ;
rgRes[1].res.resProperty.ulPropTag = PR_CONVERSATION_KEY;
rgRes[1].res.resProperty.lpProp = &rgProps[0];
rgRes[2].rt = RES_PROPERTY;
rgRes[2].res.resProperty.relop = RELOP_EQ;
rgRes[2].res.resProperty.ulPropTag = PR_MESSAGE_CLASS;
rgRes[2].res.resProperty.lpProp = &rgProps[1];
rgProps[0].ulPropTag = PR_CONVERSATION_KEY;
rgProps[0].Value.bin = pVals[iSearchKey].Value.bin; // PR_SEARCH_KEY from the profile
rgProps[1].ulPropTag = PR_MESSAGE_CLASS;
rgProps[1].Value.LPSZ = (LPTSTR)"IPM.MessageManager";
rgRes[1].res.resProperty.ulPropTag = rgProps[0].ulPropTag = PR_SEARCH_KEY;
"Outlook Message Manager (%s) (KEY: %s)", PR_PROFILE_NAME, HexFromBin(PR_SEARCH_KEY)
For Outlook 2010 and higher, you can substitute the following for steps 3-6:
CHAR g_szGeneralKey[] = "General Key"; const SBinary g_binGeneralKey = {sizeof(g_szGeneralKey), (LPBYTE)g_szGeneralKey};
CHAR g_szGeneralKey[] = "General Key";
const SBinary g_binGeneralKey = {sizeof(g_szGeneralKey), (LPBYTE)g_szGeneralKey};
Now, use these values for PR_SEARCH_KEY and PR_PROFILE_NAME and run through steps 3-6. If this fails to find a message, fall back to the original steps 3-6.
There may be more than one attachment on the message. Try the following, in order (note again the use of printf style notation)::
PRO_ACCT_MINI_UID is a property you can retrieve via the Account Management API. Here’s the definition:
#define PROP_ACCT_MINI_UID PROP_TAG(PT_DWORD, 0x0003)
The POP3 UIDL data blob is stored in PR_ATTACH_DATA_BIN.
We’ll discuss how to parse this blob in my next post. Stay tuned.
I’ve just been given permission to announce we’re targeting the release of the updated MAPICDO which will support Exchange 2013 to coincide with the release of Exchange 2010 SP3.
Exchange 2010 SP3 was announced a while back on the Ehlo blog. As you can see from that announcement, SP3 provides much needed changes to allow for coexistence between Exchange 2010 and Exchange 2013. The updated MAPICDO is part of this work.
I don’t have dates for SP3, but you can track the Ehlo blog for that.