It can sometimes be tricky to get Exchange push notifications working. The development of a listener is only part of the solution. The other part is getting the notifications from the Exchange server to the listener, especially when the listener expects the notifications on a secure channel. Exchange is of no particular help here. The only error message that is generated when Exchange can’t send a notification message to a listener is something like this:
This message is not helpful at all. Ok – Exchange could not send a notification a specific subscription. But why?
That’s why I wrote a small utility that should be able to diagnose the three most common problems:
- The Exchange server cannot reach the notification listener because a firewall is blocking the access.
- The host specified in the callback address can not be resolved to an IP address
- If the callback address of the listener is secured using TLS/SSL, Exchange will not send notifications if the server certificate used by the listener is not trusted.
Copy the program on the Exchange server. Open a command prompt and start the program. It expects the address of the listener as the first parameter. The execution of the program can take up to one minute.
Download the program here:
The source code can be downloaded from CodePlex.
Exchange 2007 has requires SSL for its WebServices, and event for Exchange 2003 some administrators have enabled this requirement on the IIS. If you are dealing with a self-signed certificate on the server and want to use .NET, you will stumble across this error message:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
The remote certificate is invalid according to the validation procedure.
By default, .NET checks whether SSL certificates are signed by a certificate from the Trusted Root Certificate store. To override this behavior, use the System.Net.ServicePointManager.ServerCertificateValidationCallback property:
1: ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;
The callback looks like this:
1: private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
3: return true;
This will accept all certificates, regardless of why they are invalid. One option here is to display a warning similar to the Internet Explorer one.
Using C# 3.0, this can even be written with less code:
1: ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;