0
votes

We exported information from a customer's Address book using outlook. Now he wants that information maintained and updated using Exchange.

We decided to use the Exchange Webservices API for this purpose.

I can retrieve the Contacts, and within those Contacts is the PhysicalAddresses enumeration that contains Work, Home and Other addresses.

Those addresses are instances of the PhysicalAddressEntry class.

This class contains Street address, Postal code, City, State and Region/Country. (See: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.physicaladdressentry_members(v=exchg.80).aspx )

It does not however contain the PostOfficeBox fields which Outlook address items have:

  • BusinessAddressPostOfficeBox
  • HomeAddressPostOfficeBox
  • MailingAddressPostOfficeBox
  • OtherAddressPostOfficeBox

(See: https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/contactitem-object-outlook )

The Exchange Webservices API does have a PersonaPostalAddress Class which is more detailed than the PhysicalAddressEntry Class ( See: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.personapostaladdress_properties(v=exchg.80).aspx ). That one does have a PostOfficeBox member.

I have not succeeded in obtaining PersonaPostalAddress entries out of my Contacts (See: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.contact_properties(v=exchg.80).aspx )

Is there a way to read and possibly write the PostOfficeBox field that belongs to a certain address ?

There is a 'user defined' property that we are already reading as an extended property, those are in the PublicStrings namespace. (See: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.defaultextendedpropertyset(v=exchg.80).aspx )

I tried creating an extended property called "OtherAddressPostOfficeBox" as PublicStrings, Address and Common, but I haven't succeeded in getting it returned.

Forgive the openedge / progress code but here is what I tried:

DEFINE VARIABLE continent-regio           AS CLASS   Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition NO-UNDO.
DEFINE VARIABLE OtherAddressPostOfficeBox AS CLASS   Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition NO-UNDO.
DEFINE VARIABLE properties                AS CLASS   "Microsoft.Exchange.WebServices.Data.PropertyDefinitionBase[]" NO-UNDO.
ASSIGN continent-regio = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet:PublicStrings,"Continent/Regio",Microsoft.Exchange.WebServices.Data.MapiPropertyType:String).
ASSIGN OtherAddressPostOfficeBox = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet:Common,"OtherAddressPostOfficeBox",Microsoft.Exchange.WebServices.Data.MapiPropertyType:String).

ASSIGN properties = NEW "Microsoft.Exchange.WebServices.Data.PropertyDefinitionBase[]"(3).
properties:SetValue(continent-regio,0).
properties:SetValue(Microsoft.Exchange.WebServices.Data.ContactSchema:PostalAddressIndex,1).
properties:SetValue(OtherAddressPostOfficeBox,2).

contactlijst:PropertySet = NEW Microsoft.Exchange.WebServices.Data.PropertySet(
    Microsoft.Exchange.WebServices.Data.BasePropertySet:FirstClassProperties,
    properties).

DELETE OBJECT properties.

ASSIGN contacten = service:FindItems(Microsoft.Exchange.WebServices.Data.WellKnownFolderName:Contacts, contactlijst).

DO iX = 0 TO contacten:Items:COUNT - 1:
    IF STRING(contacten:Items:Item[iX]:GetType()) EQ "Microsoft.Exchange.WebServices.Data.Contact" THEN DO: /* Mailinglijsten overslaan */
        ASSIGN contactpersoon = CAST(contacten:Items:Item[iX], Microsoft.Exchange.WebServices.Data.Contact).

        DO iY = 0 TO contactpersoon:ExtendedProperties:COUNT - 1:
            CASE contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:NAME:
                WHEN continent-regio:NAME THEN ASSIGN tt-cp.continent-regio = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
                WHEN OtherAddressPostOfficeBox:NAME THEN MESSAGE contactpersoon:ExtendedProperties:ITEM[iY]:VALUE
                    VIEW-AS ALERT-BOX INFO BUTTONS OK.
            END CASE.
        END.

        DELETE OBJECT contactpersoon.
    END.
END.

We can read the custom Continent/Regio field this way, but not the PostOfficeBox fields.

I probably need the numeric ID's of these fields to use one of the other constructors of the ExtendedPropertyDefinition class (See: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.extendedpropertydefinition_members(v=exchg.80).aspx ) but I can't seem to find them.

I tried this, after finding that 0x3A64 (14948) might be the ID for OtherAddressPostOfficeBox but that didn't work either.

ASSIGN OtherAddressPostOfficeBox = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet:Address,14948,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String).

Did I use the correct Property Identifier ? Would it work this way or do I need to do something entirely different ?

Edit: I'm running a brute force attack on these Address fields on an Exchange Contact Item for which I filled in every available field with the name of the field. For most of them Exchange responds with an internal server error, however, from 32768 onwards, the fields start to appear periodically.

I can as of now confirm that ID 0x804A / 32842 corresponds with BusinessAddressPostOfficeBox, so expect an answer to be added shortly once the others have popped up. Do feel free to comment if you happen to know how to pull a PersonaPostalAddress directly from the server.

We have Microsoft Exchange Server 2010 SP3 (14.3.123.4002)

1

1 Answers

0
votes

It wasn't as simple as I thought, as only the BusinessAddressPostOfficeBox is a field that can be retrieved out of the Address DefaultExtendedPropertySet.

However, having this one field I managed to find the following list on the internet that explains how to get the others: http://j-integra.intrinsyc.com/support/kb/article.aspx?id=53135

Eventually our code now looks like this:

ASSIGN BusinessAddressPostOfficeBox = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet:Address,32842,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       HomeAddressPostOfficeBox     = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14942,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       MailingAddressCity           = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14887,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       MailingAddressCountry        = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14886,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       MailingAddressPostalCode     = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14890,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       MailingAddressPostOfficeBox  = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14891,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       MailingAddressState          = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14888,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       MailingAddressStreet         = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14889,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)
       OtherAddressPostOfficeBox    = NEW Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(14948,Microsoft.Exchange.WebServices.Data.MapiPropertyType:String)

ASSIGN properties = NEW "Microsoft.Exchange.WebServices.Data.PropertyDefinitionBase[]"(10).
properties:SetValue(continent-regio,0).
properties:SetValue(BusinessAddressPostOfficeBox,1).
properties:SetValue(HomeAddressPostOfficeBox,2).
properties:SetValue(MailingAddressCity,3).
properties:SetValue(MailingAddressCountry,4).
properties:SetValue(MailingAddressPostalCode,5).
properties:SetValue(MailingAddressPostOfficeBox,6).
properties:SetValue(MailingAddressState,7).
properties:SetValue(MailingAddressStreet,8).
properties:SetValue(OtherAddressPostOfficeBox,9).

contactlijst:PropertySet = NEW Microsoft.Exchange.WebServices.Data.PropertySet(
    Microsoft.Exchange.WebServices.Data.BasePropertySet:FirstClassProperties,
    properties).

ASSIGN contacten = service:FindItems(Microsoft.Exchange.WebServices.Data.WellKnownFolderName:Contacts, contactlijst).

DO iX = 0 TO contacten:Items:COUNT - 1:
    IF STRING(contacten:Items:Item[iX]:GetType()) EQ "Microsoft.Exchange.WebServices.Data.Contact" THEN DO: /* Mailinglijsten overslaan */
        ASSIGN contactpersoon = CAST(contacten:Items:Item[iX], Microsoft.Exchange.WebServices.Data.Contact).

        CREATE tt-cp.
        ASSIGN tt-cp.naam               = contactpersoon:CompleteName:FullName
               tt-cp.firma              = contactpersoon:CompanyName
               tt-cp.initialen          = contactpersoon:Initials
               tt-cp.functie            = contactpersoon:JobTitle
               tt-cp.afdeling           = contactpersoon:Department
/* ... */
        DO iY = 0 TO contactpersoon:ExtendedProperties:COUNT - 1:
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(continent-regio) THEN 
                ASSIGN tt-cp.continent-regio = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(BusinessAddressPostOfficeBox) THEN 
                ASSIGN tt-cp.werkadres-postbus = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(HomeAddressPostOfficeBox) THEN 
                ASSIGN tt-cp.thuisadres-postbus = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(MailingAddressCity) THEN 
                ASSIGN tt-cp.postadres-stad = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(MailingAddressCountry) THEN 
                ASSIGN tt-cp.postadres-land = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(MailingAddressPostalCode) THEN 
                ASSIGN tt-cp.postadres-postcode = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(MailingAddressPostOfficeBox) THEN 
                ASSIGN tt-cp.postadres-postbus = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(MailingAddressState) THEN 
                ASSIGN tt-cp.postadres-staat = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(MailingAddressStreet) THEN 
                ASSIGN tt-cp.postadres-straat = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(OtherAddressPostOfficeBox) THEN 
                ASSIGN tt-cp.anderadres-postbus = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
            IF contactpersoon:ExtendedProperties:ITEM[iY]:PropertyDefinition:Equals(Webpage) THEN 
                ASSIGN tt-cp.webstek = contactpersoon:ExtendedProperties:ITEM[iY]:VALUE.
        END.

So basically you just look up what the tagged id is for the field you are looking for and create an extended property for it, then it will be returned.

When going over the returned resultset, you can test the propertydefinition using Equals to see which one was returned.