InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

Simple push notification client

As I wrote in my earlier post, I recently published a component on CodePlex that simplifies using push notifications in your applications. Since I’ve not published a full fledged sample application, I will start with a series of blog posts. I will tag all related articles on this topic with “push notifications”, and you can get a list of all articles with this link: http://www.infinitec.de/?tag=/push+notifications.

I’ll start with a very simple application: A console application that creates one subscription get notifications about new mails arriving in the mailbox of the current user.

   1: using System;
   2: using System.Net;
   3: using InfiniTec.Exchange.Notifications;
   4:  
   5: namespace ExchangeNotificationTestClient
   6: {
   7:     internal class Program
   8:     {
   9:         private static void Main()
  10:         {
  11:             // Ignore any certificate errors
  12:             ServicePointManager.ServerCertificateValidationCallback += 
  13:                 (sender, certificate, chain, sslPolicyErrors) => true;
  14:  
  15:             // Setup the adapter which will be used to call into the Exchange WebService
  16:             var adapter = new ExchangeWebServicesAdapter(
  17:                 new Uri("https://casserver/ews/exchange.asmx"), 
  18:                 new NetworkCredential("administrator", "password", "contoso"));
  19:  
  20:             // Create a new subscription collection to manage all the subscriptions
  21:             var subscriptionCollection = new SubscriptionCollection(adapter);
  22:  
  23:             // Setup a listener that listens on port 80 on the local computer
  24:             using (var listener = new PushNotificationListener())
  25:             {
  26:                 // Register for a NewMail notification on the inbox of the administrator
  27:                 subscriptionCollection.Add(
  28:                     new[] {new FolderReference(WellKnownFolderId.Inbox)}, 
  29:                     EventTypes.NewMail);
  30:                 Console.Out.WriteLine("Starting Notification Service...");
  31:                 listener.Start();
  32:  
  33:                 Console.Out.WriteLine("Creating subscription");
  34:  
  35:                 foreach (var subscription in subscriptionCollection)
  36:                 {
  37:                     // Write a line to the console for each new mail received
  38:                     subscription.NewMail += (sender, e) => 
  39:                         Console.Out.WriteLine(string.Format("{0}: New Mail arrived in your inbox", e.Timestamp));
  40:                     subscription.Start(listener);
  41:                 }
  42:  
  43:                 Console.Out.WriteLine("Waiting for notifications... Hit [Enter] to quit...");
  44:  
  45:                 Console.ReadLine();
  46:             }
  47:         }
  48:     }
  49: }

There are four important classes used in this example:

  1. The ExchangeServiceAdapter (created in line 16) is used to actually perform the Web Services calls to the Exchange Server (CAS Role). It’s a rather simple implementation, as it does not support AutoDiscover. You have to specify the Exchange server manually. It does, however, support Exchange Impersonation. And if you want to subscribe to events on public folders, you’ll have to enable this feature by setting the ExchangeServiceAdapter.IsPublicFolderAccessEnabled to true. Your Exchange Server must have Service Pack 1 installed to use this feature.
  2. The PushNotificationListener (created in line 24): This class does all the necessary WCF plumbing to setup a host, receives the notifications and channels them to the right subscription.
  3. The SubscriptionCollection: (created in line 21) It’s not really necessary, but it makes is more easy to handle multiple subscriptions.
  4. The Subscription (created in line 27). You can either create a subscription by calling SubscriptionCollection.Add(), or create a subscription directly via “new Subscription()”.

Both, the PushNotificationListener and the Subscription need to be started to do some actual work. And that’s all you need to do to get a simple notification client up and running. However, there are some security settings to consider, because WCF doesn’t let you run around and open endpoints on your users machines. Additionally, the Windows Firewall needs to be configured correctly to let the notifications through. I’ll discuss this in a separate post.


Posted by Henning Krause on Tuesday, December 30, 2008 10:55 PM, last modified on Saturday, November 27, 2010 6:04 AM
Permalink | Post RSSRSS comment feed

InfiniTec.Exchange 0.99.4 released

This release brings a bunch of bugfixes and some new features: The Subscription and SubscriptionCollection classes implement the WebDAV push event feature: Now you can subscribe to changes made to folders and elements. Here's a diagram of the system:


Class diagram of the Subscription management (click to enlarge)

Access to the SubscriptionCollection is exposed via the Connection Class, although you are free to create your own instance. By default, it binds to a local port between 1024 and 5000, but you can specify a fixed port also. An example is not yed available.

Another cool new feature is the incorporation of my little Expression classes. These classes allow you to easily build expressions for filter items in a ItemCollection or Searcher class. A typical example would be to filter all appointments in a folder between a specified date range. You can do this now very easily:

    1     Expression expression = Expression.And(Expression.Equals(WellknownProperties.Appointment.Starttime, DateTime.Now),

    2                                        Expression.Equals(WellknownProperties.Appointment.EndTime, DateTime.Now.AddDays(3)));

    3 

    4 using (Connection connection = newConnection(server, ConnectionProtocol.Default, newCredential(username, password, AuthenticationType.Ntlm)))

    5 {

    6     Mailbox mbx = newMailbox("exchange/administrator", connection);

    7     mbx.Refresh();

    8 

    9     mbx.Calendar.Items.ConstraintExpression += expression;

   10     mbx.Calendar.Items.Refresh();

   11 

   12     foreach (CalendarItem item in mbx.Calendar.Items)

   13     {

   14         ProcessItem(item);

   15     }

   16 }

One special thing about this: You can concatenate two expressions by using the plus operator. This will result in both expressions being ANDed.

No more worrying about casting properties to the right type and such. You don't even have to worry about time zones - all handled automagically.

Here is a small overview over the expression classes:


Class diagram for the expression classes (click to enlarge)

Changelog

  • Fixed a bug in the FolderCollection class
  • Fixed a bug in the TaskItem.PreSave() method which caused the Content class of the item not to be set.
  • Fixed a bug in the TaskItem.PreSave() method which prevented a successful modification of the TaskStatus (Would not work if PercentComplete was not set)
  • The Searcher<ItemType> now get the correct set of properties for the specific item types.
  • Changed the type of TaskItem.PercentComplete from float to double
  • Exchange 'float' datatype is now handled as 'System.Double' instead of 'System.Float'
  • New method ApplyInheritedSecurity(FolderSecurity): Clears all security descriptor entries and applies the security settings from the specified descriptor. (Experimental!)
  • SchemaClass attribute is now public
  • The ItemCollection and ItemCollection<ItemType> classes now expose a IList<string> PropertiesToLoad property
  • Renamed ChildItems and ChildFolders of the Folder and Folder<ItemType> classes to Items and Folders.
  • Moved the IsRead property from MessageItem to Item
  • Made the IsRead property writable
  • Fixed a bug in the Property class which prevented setting propertyvalues to 0 or false
  • Replaced the HttpStatus class with a PropertyStatus enumeration. HttpStatus was used with the Property.Status property.
  • Added support for InfiniTec.Expressions on the Searcher, Item- and FolderCollections. Constraints can now be either specified using the Constraints property or the ConstraintExpression property.
  • SubscriptionCollection and Subscription implement WebDAV events

Downloads

ReleaseBuild.zip (497,091 Bytes)
Optimized build with a strong name and AuthentiCode signature
SourceAndDemoApplication.zip (496,678 Bytes)
The source files and the demo application
Documentation.zip (2,087,722 Bytes)
The documentation as CHM file

Technorati:

Posted by Henning Krause on Monday, April 9, 2007 12:00 AM, last modified on Monday, April 9, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

Exchange library updated

Another maintenance update with a bunch of bugfixes...

Changelog

  • Fixed bugs in the ItemCollection.Add, ItemCollection<T>.Add and FolderCollection.Add method
  • Fixed NullReferenceException bugs in the ItemBase constructors
  • New Interface IKeyedCollection 
  • Contact EmailAddresses and PhysicalAddresses are now of type IKeyedCollection
  • The Item Class and all its descendents now have an Url property (delegated from BaseItem
  • Fixed a bug in the ContactItem class regarding the population of the PhysicalAddress list
  • Fixes a bug in the search method, which occured when the number of items in the search query where an exact multiple of the pagesize
  • New class SearchResult, which is used in the Methods.Search method. It contains the result items of the search, as well as the total number of items of the search.

Downloads

InfiniTec.Exchange_Release.zip (453,287 Bytes)
Binaries (Release build with debug symbols) with a strong-name
InfiniTec.Exchange.zip (1,725,519 Bytes)
Source, Documentation and Example application

Technorati:

Posted by Henning Krause on Thursday, February 15, 2007 12:00 AM, last modified on Thursday, February 15, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

Enumerating attachments in a users inbox folder

One reader recently asked how he could use my InfiniTec.Exchange library to scan the mails in the inbox folder of a users mailbox for attachments. Here is an example:

    1 classProgram

    2 {

    3     staticvoid Main(string[] args)

    4     {

    5         ServicePointManager.ServerCertificateValidationCallback = delegate { returntrue; };

    6 

    7         using (Connection connection = newConnection("server", ConnectionProtocol.Secure, newCredential("username", "password", AuthenticationType.Ntlm)))

    8         {

    9             Mailbox mbx;

   10 

   11             Console.Out.WriteLine("Refreshing mailbox....");

   12             mbx = newMailbox("exchange/useralias", connection);

   13             mbx.Refresh();

   14 

   15             ItemCollection<MessageItem> children = mbx.Inbox.ChildItems;

   16 

   17             children.Constraints +=

   18                 string.Format("AND Cast(\"{0}\" as \"boolean\") = true", WellknownProperties.Item.HasAttachments);

   19 

   20             Console.Out.WriteLine("Enumerating child items with attachments in inbox...");

   21 

   22             children.Refresh();

   23 

   24             Console.Out.WriteLine("Found {0} items", children.Count);

   25 

   26             foreach (MessageItem item in children)

   27             {

   28                 Console.Out.WriteLine("Processing " + item.Subject);

   29                 item.Attachments.Refresh();

   30 

   31                 foreach (Attachment attachment in item.Attachments)

   32                 {

   33                     Console.Out.WriteLine("\t{0} ({1}, {2}, {3} bytes)", attachment.Name, attachment.MimeType, attachment.ContentDisposition, attachment.Size);

   34                 }

   35             }

   36 

   37             Console.Out.WriteLine("Finished");

   38             Console.ReadLine();

   39         }

   40     }

   41 }

This is a console application, so you'll just have to replace the main class of a newly created console application with this code. Then, add a reference to my library (At least version 0.99.2).

The most tricky part here clearly is the modification of the constraints in line 17; The default constraint is initialized with this value:

    1 _Searcher.Constraints = string.Format(CultureInfo.InvariantCulture, "(\"{0}\" = false) ", WellknownProperties.Dav.IsFolder);

This restricts the result set to child elements which are not folders. To restrict the result set further, you can just append additional constraints with an "AND". The full constraint being used here is this:

    1 ("DAV:isfolder" = false) AND Cast("http://schemas.microsoft.com/mapi/proptag/xe1b000b" as "boolean") = true

You'll probably wonder why I used the MAPI property 0xe1b00b instead of the urn:schemas:httpmail:hasattachment property. In the past, I've found the latter property not very reliable - it was false, even though a message had an attachment. And since I'm using a non-standard property here, I have to cast it to boolean to make the request work. If you don't do this, you'll end up with a Bad Request error from exchange.


Technorati:

Posted by Henning Krause on Sunday, February 11, 2007 12:00 AM, last modified on Monday, November 29, 2010 8:50 PM
Permalink | Post RSSRSS comment feed

Exchange library updated again

This is a maintenance update with a number of bugfixes and a few new features to ease access to child items and folders: The Folder classes now expose two properties, ChildItems and ChildFolders, which provide access to the child elements of the folder. Both, the ItemCollection and the FolderCollection, have a Refresh operation, which must be called before the child elements can be accessed. Furthermore, both classes have a Constraints property, which restricts the items enumerated by the Refresh operation. Here is a class diagram of the new classes:


Class diagram of the ItemCollection and FolderCollection classes (click to enlarge)

I will post an example tomorrow on how to use these new methods to enumerate the attachments of all items in the inbox folder of a users mailbox.

Changelog for this version

  • Many minor changes to comply with static code-analysis
  • Fixed an bug with the Mailbox class
  • Fixed several bugs in the Initialize() method of the typed item classes
  • New class FolderCollection, which provides access to subfolders of an item.
  • New class ItemCollection<ItemType>, which provide access to child elements of a folder
  • The Folder<ItemType> now have a property ChildItems
  • The Folder classes now has a property ChildFolders;
  • The Folder class now has a property ChildItems.
  • The Attachment.Name property is now more accurate
  • All Item and Folder classes now expose a method ResetSecurityDescriptor and ResetSecurityDescriptorAsync, which does exactly that.
  • The Contact, CalendarItem now sets the content class correctly on new items
  • The Find Method on the Searcher and Searcher<ItemType> has been renamed to FindAll
  • The FindAsync Method on the Searcher and Searcher<ItemType> has been renamed to FindAllAsync
  • New method FindPage on the Searcher and Searcher<ItemType> 
  • New method FindPageAsync on the Searcher and Searcher<ItemType> 
  • The constructor of FolderSecurity is now internal
  • Constructor in ContactEmailAddress now saves the displayname correctly
  • Upgraded the threading library to version 2.5.2. This fixes a bug with all the synchronous methods blocking in a deadlock.

Downloads

InfiniTec.Exchange.zip (1,858,836 Bytes)
Binaries, Source, Documentation and Example application of version 0.99.2

Technorati:

Posted by Henning Krause on Saturday, February 10, 2007 12:00 AM, last modified on Saturday, February 10, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

Minor update on the Exchange library

This is a minor update on the InfiniTec.Exchange library due to the issues found within the multi threading library today. The Example application has also been updated accordingly.

Change log

  • Fixed a multi-threading bug in the ActiveDirectoryResolver class.
  • Upgraded the threading library to version 2.5.1. It's no longer necessary to call Control.Invoke() methods when reporting progress to the UI.

Downloads

InfiniTec.Exchange.zip (1,660,202 Bytes)
Source, binaries, documentation and example application for 0.99.1

Technorati:

Posted by Henning Krause on Sunday, January 28, 2007 12:00 AM, last modified on Sunday, January 28, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

Exchange library updated again

Again, an update on my exchange library.

This update fixes a bunch of issues (many thanks to Mr. Heinen for his input), and some new features, as listed in the change log below.

Messing with distribution lists

This release adds experimental support for distribution lists in exchange folder. But instead of relying on the OWA commands to decode them (as described here), I decoded the binary member properties. Turned out, that the entry ids contained in that folder can be translated into a permannt url.

This release allows only read-only access to the member list.

The Members property of the DistributionList class returns a list of IAddressEntry instances. This interface currently exposes only one property, the name of the element. The element is one of the following:

  • User - A reference to an Active Directory user.
  • Contact - A reference to an Active Directory contact
  • Group - A reference to an Active Directory group
  • DistributionList - A nested distribution list
  • EmailAddress - A so called One-Off member. This is just name with an email address.

Calendar permissions

When giving other people access to a calendar folder on a mailbox, it's not enough, to set those permissions on the calendar folder itself. The trustee must be given access to the local free busy data as well (This folder resides in the NON_IPM_SUBTREE/FreeBusy Data folder). The Mailbox class now returns a special folder instance for the mailbox.Calendar folder which handles this. More information on this topic can be found here.

Changelog for version 0.99

  • Connection class now implements IDisposable (explicit implementation) and has a Close() method. Call either of these methods to close the underlying active directory connection.
  • Optimized the resolution of mailbox urls.
  • Added DistributionList class, which provides read-only access to the members of a distribution list stored on an Exchange folder.
  • Added new CalendarFolder class, which is returned from the Mailbox class. This class propagates security changes made to the folder to the local free/busy folder, as described in KB (237924). See http://support.microsoft.com/kb/237924/en-us.
  • Fixed several NullReferenceExceptions
  • Fixed some issues with TaskItem and CalendarItem
  • Added some validation logic to TaskItem and CalendarItem
  • Added some auto-calculations to the TaskItem an CalendarItem (e.g. End = Start + Duration and so on, modifying IsAllDayEvent accordingly)
  • Added the GetContent and SetContent functionality to the Item class
  • Fixed a bug with the PUT method (and the SetContent functionality as well)
  • Fixed a bug with setting the Free/Busy property on CalendarItems
  • Fixed a bug in the save method which occured when the Save operation was called when no properties were changed.
  • The SetContent and Attachment.Add methods now require a content type to be specified
  • New Class WellknownContentTypes, which has some definitions of common content types.
  • Renamed the FreeBusyType OOF to OutOfOffice
  • Removed the SearchScope property from the SearcherBase class, as it was redundant. Use the Scope property instead.

Downloads

InfiniTec.Exchange_0.99.zip (2,023,427 Bytes)
All-in-wonder package, including source, binaries, documentation and example application.

Technorati:

Posted by Henning Krause on Saturday, January 27, 2007 12:00 AM, last modified on Saturday, January 27, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

Exchange library updated again

Here is another update on the InfiniTec.Exchange library. Among a few bug fixes, there are several new classes which simplify access to the Exchange store. Here is a class diagram of those classes:


Class diagram of Active Directory integration (click to enlarge)

To get the address of a users mailbox, you can now use the User class, which exposes a property named Mailbox. Be sure to call the Refresh or RefreshAsync method before accessing it.

To get a user object, you can either traverse the address lists defined in the Exchange organization by using the AddressListManager class.

Another way is to use the UserResolver which uses "ambiguous name resolution" and "search by initials" to find users: Specifying a Filter of jd will return John Doe. Specifiy john will do return all users with the name joe. This is essentially, what Outlook does when you execute the "Resolve Name" function. But in this case, the users contact folder is not searched.

Permissions needed

The problem with resolving the mailbox url or enumerating the address lists is that these operations require access to the Exchange configuration in the Active Directory. This data is stored under CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=primary_domain. By default, normal users do not have access to this data.

Downloads

InfiniTec.Exchange.Release_0.98.zip (386,492 Bytes)
Release Build of version 0.98
InfiniTec.Exchange_Source_0.98.zip (301,731 Bytes)
Source code of version 0.98
InfiniTec.Exchange_Documentation_0.98.zip (768,932 Bytes)
Documentation
ExampleApplication_0.98.zip (279,372 Bytes)
Example application

Technorati:

Posted by Henning Krause on Sunday, January 7, 2007 12:00 AM, last modified on Sunday, January 7, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

Exchange Library 0.97

It's time for a new update to my Exchange access library. Again, several breaking changes, as the number of classes grow. So, here is the new class diagram:


(click to enlarge)

And there are a few more classes worth writing about: The Searcher<ItemType> is a Searcher class which returns MessageItems, CalendarItems and so on. Next, the Folder<ItemType> implements the folder functionality for the same classes. And finally, the Mailbox class provides access to the wellknown folders like Calendar, Inbox, Outbox and so on - language independent. So, here is the diagram for these classes:


If you have comments or if you found an error, please drop me a note.

Changelog for this version

  • The Item class now has most of the methods from the SimpleItem class: Delete, Copy, Move
  • The host of the url passed to the an Item or Folder class now checks the IP addresses of the specified hostname instead of the literal hostname. If an IP address is specified as a server, no DNS resolution is attempted.
  • New Searcher<ItemType> class. Allows to directly search for tasks, appointments, calendaritems..
  • New Folder<ItemType> class. 
  • New Mailbox class which provides language-independent access to the wellknown folders like inbox, outbox, tasks...
  • Renamed Item to SimpleItem
  • Renamed TypedItemBase to Item
  • Renamed Task to TaskItem
  • Renamed Contact to ContactItem
  • Renamed Message to MessageItem
  • Item is no longer abstract
  • Item and its descendents now all have a parameterless constructor
  • Fixed a bug in the ContactItem class which prevented a successful save operation
  • Fixed several bugs in the security logic.

Downloads

InfiniTec.Exchange_0.97_Binaries.zip (253,065 Bytes)
Binaries for version 0.97, strong-named
ExampleApplication.zip (501,698 Bytes)
Example application for version 0.97
InfiniTec.Exchange_0.97_Source.zip (855,323 Bytes)
Source files for version 0.97
Documentation_0.97.zip (667,023 Bytes)
Documentation for version 0.97.

Technorati:

Posted by Henning Krause on Tuesday, January 2, 2007 12:00 AM, last modified on Tuesday, January 2, 2007 12:00 PM
Permalink | Post RSSRSS comment feed

New version of the Exchange class library

This is a bug-fix release.

Changelog:

  • Fixed a bug in the Security logic. It is now possible to set permissions on groups (security and distribution) without destroying the security descriptor
  • Fixed a bug with MultiValued properties
  • Fixed a bug with the Duedate property of tasks
  • Fixed a bug which prevented the manipulation of properties which names started with 0x
  • Removed the set part of the Task.IsComplete property. This has been replaced by a SetComplete(DateTime) method.
  • Added an IconIndex enumeration and changed the data type of the TypedItemBase.IconIndex from int? to IconIndex?
  • Fixed a bug in the Attachment class

Downloads

InfiniTec.Exchange_0.96_Source.zip (223,936 Bytes)
InfiniTec.Exchange 0.96 Source code
InfiniTec.Exchange_0.96_Release.zip (239,684 Bytes)
InfiniTec.Exchange 0.96 binaries, signed with the InfiniTec private key. Release-Build with debug symbols
InfiniTec.Exchange_Documentation.zip (818,848 Bytes)
Documentation as CHM file
InfiniTec.Exchange_ExampleApplication.zip (453,545 Bytes)
Example application

Technorati:

Posted by Henning Krause on Sunday, October 29, 2006 12:00 AM, last modified on Sunday, October 29, 2006 11:00 AM
Permalink | Post RSSRSS comment feed