none
EWS API - limiting search to a specific email address RRS feed

  • Question

  • I want to limit the returned results from a contact folder to a specific user's email address. Anyone know how I would modify the code below to find the contact whose email is myuser@mydomain.com?

        static void GetContactID(ExchangeService svc)
    
        {
    
         //Create ItemView and specify IdOnly shape.
    
         ItemView view = new ItemView(10);
    
         view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
    
    
    
    
    
         //Find Contacts.
    
         FindItemsResults<Item> findResults = svc.FindItems("AAMkADIyMzczODE5LWVkYTQtNGZmNC05ODdmLTM2MzE0NWEwYjI3NgAuAAAAAAB9THkbQ8DSEZAzAIBfuwAUAQCk7vLITbfIQJ77mDILjum0AAAaaqFWAAA=", view);
    
         //AAMkADIyMzczODE5LWVkYTQtNGZmNC05ODdmLTM2MzE0NWEwYjI3NgAuAAAAAAB9THkbQ8DSEZAzAIBfuwAUAQCk7vLITbfIQJ77mDILjum0AAAaaqFWAAA=
    
         
    
         //Get Additional Property.
    
         //svc.LoadPropertiesForItems(findResults, new PropertySet(ContactSchema.HomePhone));
    
         svc.LoadPropertiesForItems(findResults, new PropertySet(ContactSchema.EmailAddress1));
    
    
    
         //Loop through results, printing out Id and email.
    
         foreach (Item item in findResults.Items)
    
         {
    
    
    
          Contact contact = item as Contact;
    
    
    
          Console.WriteLine("------------------");
    
          Console.WriteLine("ID: " + item.Id.UniqueId);
    
          Console.WriteLine("Email: " + contact.EmailAddresses[EmailAddressKey.EmailAddress1]);
    
          Console.WriteLine("------------------");
    
          Console.WriteLine("");      
    
    
    
         }
    
        }
    
    

     


    Monday, August 22, 2011 5:00 PM

All replies

  • I'd suggest you use the ResolveName operation instead of using a findItems operation unless you are only trying to find contacts where the email address is only in the EmailAddress1 property (eg could be also EmailAddress2,EmailAddress3. Eg something like this would search all three properties and bind to any contacts founds

          NameResolutionCollection ncCol = service.ResolveName("test@wobble.com",ResolveNameSearchLocation.ContactsOnly,true);
          foreach (NameResolution nc in ncCol) {
            Contact cnCnt = Contact.Bind(service, nc.Mailbox.Id);
            Console.WriteLine(cnCnt.DisplayName);
          }
    

     

    Otherwise you can just use a search filter eg

     

          ItemView iv = new ItemView(1);
          SearchFilter sf = new SearchFilter.IsEqualTo(ContactSchema.EmailAddress1, "test@wobble.com");
          FindItemsResults<Item> firesults = service.FindItems(WellKnownFolderName.Contacts, sf, iv);
    


    Cheers
    Glen

    Tuesday, August 23, 2011 3:39 AM
  • Strange. If I use the first code block below I get the 7 contacts in that contacts folder, but if I use the second code block I get nothing. I know this email address is in the EmailAddress1 field, so not sure why it's not finding it.

            static void GetContactID(ExchangeService svc)
            {
              ItemView view = new ItemView(10);
              view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
    
              FindItemsResults<Item> findResults = svc.FindItems("AAMkADIyMzczODE5LWVkYTQtNGZmNC05ODdmLTM2MzE0NWEwYjI3NgAuAAAAAAB9THkbQ8DSEZAzAIBfuwAUAQCk7vLITbfIQJ77mDILjum0AAAaaqFWAAA=", view);
              
              //Get Additional Property.
              svc.LoadPropertiesForItems(findResults, new PropertySet(ContactSchema.EmailAddress1));
    
              foreach (Item item in findResults.Items)
              {
    
                Contact contact = item as Contact;
    
                Console.WriteLine("------------------");
                Console.WriteLine("ID: " + item.Id.UniqueId);
                Console.WriteLine("Email: " + contact.EmailAddresses[EmailAddressKey.EmailAddress1]);
                //Console.WriteLine("HomePhone = " + contact.PhoneNumbers[PhoneNumberKey.HomePhone]);
                Console.WriteLine("------------------");
                Console.WriteLine("");            
    
              }
            }
    

     

            static void GetContactID(ExchangeService svc)
            {
    
              ItemView view = new ItemView(10);
              view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
    
              SearchFilter sf = new SearchFilter.IsEqualTo(ContactSchema.EmailAddress1, "test@wobble.com>");
    
              FindItemsResults<Item> findResults = svc.FindItems("AAMkADIyMzczODE5LWVkYTQtNGZmNC05ODdmLTM2MzE0NWEwYjI3NgAuAAAAAAB9THkbQ8DSEZAzAIBfuwAUAQCk7vLITbfIQJ77mDILjum0AAAaaqFWAAA=", sf, view);
              
    
              foreach (Item item in findResults.Items)
              {
    
                Contact contact = item as Contact;
    
                Console.WriteLine("------------------");
                Console.WriteLine("ID: " + item.Id.UniqueId);
                Console.WriteLine("Email: " + contact.EmailAddresses[EmailAddressKey.EmailAddress1]);
                //Console.WriteLine("HomePhone = " + contact.PhoneNumbers[PhoneNumberKey.HomePhone]);
                Console.WriteLine("------------------");
                Console.WriteLine("");            
    
              }
            } 
    

     

    Tuesday, August 23, 2011 3:11 PM
  • Well, I just changed the filter to my business phone and it worked. Something strange about filtering with the email address. I noticed when I output the results using my business phone it shows the email like this: Lastname, Firstname <SMTP:Firstname.Lastname@mydomain.com>

    I tried filtering on that as well, but that didn't work either. 

    SearchFilter sf = new SearchFilter.IsEqualTo(ContactSchema.BusinessPhone, "444-555-6666");

    Tuesday, August 23, 2011 3:30 PM
  • All things being even (which they rarely are) you shouldn't really have a prefix on these email addresses but it could depend on the way they are added and its not nessasarly invalid what i would suggest in that case if you want to use a searchfilter is just use the ContainSubstring eg

     SearchFilter sf = new SearchFilter.ContainsSubstring(ContactSchema.EmailAddress1, "test@wobble.com");

    If you do that you might want to implement some more string logic to verify any results returned.

    The other option is to use the Extended property but my guess is you'll probaby get the same result eg

           ExtendedPropertyDefinition emailAddress1 = new ExtendedPropertyDefinition(32899, MapiPropertyType.String);

           SearchFilter sf = new SearchFilter.IsEqualTo(emailAddress1, "test@wobble.com");

    Cheers
    Glen

    Wednesday, August 24, 2011 3:21 AM
  • Interesting. The ContainsSubstring didn't work either. One thing I noticed was in a different contacts folder where the contact was created by webdav I opened the contact and copied the email address. It showed Firstname.Lastname@mydomain.com

    When I went to the contacts folder created with EWS and copied the email address it shows "firstname.lastname@mydomain.com <firstname.lastname@mydomain.com>"

    I even tried SearchFilter sf = new SearchFilter.ContainsSubstring(ContactSchema.EmailAddress1, "firstname"); and it still doesn't find anything.

    I know it's there. Weird.

     

     

     

    Wednesday, August 24, 2011 3:40 PM
  • I just noticed under E-Mail fields the email address type is EX rather than SMTP. Any idea how I would modify the filter to account for this?

     

     

    Wednesday, August 24, 2011 5:59 PM
  • What i would suggest is that you use a Mapi editor like MFCMapi and have a look at the properties on the contact Item your trying to search for this will allow you to see all the properties/values that you can essentially query on. If a Contact is using a Native address it probably means that it was added from the GAL or is a one offentry either way unless the SMTP address is stored in another property you wont be able to find this contact based on the SMTP address. What you can do is use resolveName to search Global Address list and access the information about the contact this way depends what your trying to achieve ?

    Cheers
    Glen

    Thursday, August 25, 2011 4:00 AM
  • Thanks for all your help Glen. Much appreciated.

    I guess there are two other ways I could do this. One is to use createitem for the contacts and make the email address type SMTP. Not sure if that's even possible?

    The second would be to use two values to retrieve a contact like businessphone and file as. How would you go about adding multiple values to a search filter? Could I add the File As field to the filter below?

    SearchFilter sf = new SearchFilter.IsEqualTo(ContactSchema.BusinessPhone, "123-456-7899");

    Thursday, August 25, 2011 7:01 PM
  • Use a search filter collection eg (this finds an email between a certain size but you should get the point)

          SearchFilter sf1 = new SearchFilter.IsGreaterThan(ItemSchema.Size, (1 * 1024));
          SearchFilter sf2 = new SearchFilter.IsLessThan(ItemSchema.Size, (10 * 1024));
          SearchFilter sfcol = new SearchFilter.SearchFilterCollection(LogicalOperator.And) { sf1, sf2 };
    


    If your are creating a contact using EWS the address format should always be SMTP that only time Native address generally gets used is when contacts are added using Outlook and address resolves in the GAL

    Cheers
    Glen 

    Friday, August 26, 2011 7:22 AM
  • Thanks! That did the trick.

    With Exchange 2007, we were using Intapp to sync contacts from our user database. They had wizards that made it pretty simple to do things with webdav. Unfortunately, their interface for Exchange 2010 is basically a textbox to paste the SOAP request. What I'm having to do is write the code using the EWS API and capture the SOAP request so I can use that in Intapp. Currently, I output the xml from the API using a trace listener that write to an xml file. That doesn't seem to be generating what I would expect to see. If you look at the code and the tracing results I don't think this will work. Since you appear to be rather knowledgeable in this area, just wondering if you had any ideas on getting the correct capture for the SOAP request?

            static void GetContactID(ExchangeService svc)
            {
              ItemView view = new ItemView(1);
              view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
    
              SearchFilter sf1 = new SearchFilter.IsEqualTo(ContactSchema.BusinessPhone, "123-456-7899");
              SearchFilter sf2 = new SearchFilter.IsEqualTo(ContactSchema.FileAs, "Lastname, Firstname");
              SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And) { sf1, sf2 };
    
    
              FindItemsResults<Item> findResult = svc.FindItems("AAMkADIyMzczODE5LWVkYTQtNGZmNC05ODdmLTM2MzE0NWEwYjI3NgAuAAAAAAB9THkbQ8DSEZAzAIBfuwAUAQCk7vLITbfIQJ77mDILjum0AAAaaqFWAAA=", sf, view);
              
    
                svc.LoadPropertiesForItems(findResult, new PropertySet(ContactSchema.EmailAddress1));
    
              foreach (Item item in findResult.Items)
              {
    
                Contact contact = item as Contact;
    
              }
            }
    


    XML output from trace listener:

    <Trace Tag="EwsRequest" Tid="1" Time="2011-08-26 13:37:53Z" Version="14.02.0051.000">
     <?xml version="1.0" encoding="utf-8"?>
     <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Header>
       <t:RequestServerVersion Version="Exchange2010_SP1" />
      </soap:Header>
      <soap:Body>
       <m:GetItem>
        <m:ItemShape>
         <t:BaseShape>IdOnly</t:BaseShape>
         <t:AdditionalProperties>
          <t:IndexedFieldURI FieldURI="contacts:EmailAddress" FieldIndex="EmailAddress1" />
         </t:AdditionalProperties>
        </m:ItemShape>
        <m:ItemIds>
         <t:ItemId Id="AAMkADIyMzczODE5LWVkYTQtNGZmNC05ODdmLTM2MzE0NWEwYjI3NgBGAAAAAAB9THkbQ8DSEZAzAIBfuwAUBwCk7vLITbfIQJ77mDILjum0AAAaaqFWAACk7vLITbfIQJ77mDILjum0AAAaatA8AAA=" ChangeKey="EQAAABYAAACk7vLITbfIQJ77mDILjum0AAAaawqZ" />
        </m:ItemIds>
       </m:GetItem>
      </soap:Body>
     </soap:Envelope>
    </Trace>
    

     

     

    Friday, August 26, 2011 6:27 PM
  • >What I'm having to do is write the code using the EWS API and capture the SOAP request so I can use that in Intapp. Currently, I output the xml from the API using a trace listener that write to an xml file. That doesn't seem to be generating what I would expect to see

    Can you elobrate more on this ? That method should work okay as long as you drop the Trace tags and as long as you authenticate okay things like ItemId's and FolderI'd are unique so you can't really have static SOAP like you may have had in Webdav but you can build the soap strings manually once you retrieve the Id's.

    I guess the other question is what value does Intapp really give you in terms of Sync it maybe better to just deal with the code directly.

    Cheers
    Glen

     

    Tuesday, August 30, 2011 4:08 AM