Walkthrough: Using the WCF Exchange Server Mail Transport
You can create applications that are based on the Windows Communication Foundation (WCF) Exchange Server mail transport to send and receive messages on specified input/output channels, by using a computer that is running Microsoft Exchange Server as the mediator. Applications that are based on the WCF Exchange Server mail transport are supported both on the desktop and on devices.
This walkthrough introduces the features of the WCF Exchange Server mail transport. It illustrates the following tasks:
Setting up your computer.
Building the application for the device (client).
Building the application for the desktop (server).
For a complete listing of the code shown in these procedures, see the Example section at the end of this walkthrough.
Note
Do not use this example in production code.
Prerequisites
This example requires the .NET Compact Framework version 3.5.
Setting up Your Computer
In this procedure, you make sure that your development environment is set up correctly to run the example.
To set up your computer to run the example
Install the Windows Mobile version 5.0 or Windows Mobile 6 Software Development Kit (SDK).
The Windows Mobile 6 Professional SDK includes the ActiveSync always-up-to-date (AUTD) feature, which is used by the mail transport on the device to keep the Inbox up-to-date. For more information, see the Windows Mobile Web site.
Make sure that an e-mail server that is running Microsoft Exchange Server 2007 is available on the network.
If you do not have Exchange Server 2007 available, you can use a trial version that runs on Virtual PC. For more information, see the Exchange Server Web site.
Verify that your computer can connect to the new Exchange e-mail server by running Outlook Web Access (OWA) from your computer and connecting to an e-mail account.
Make sure that Exchange Web Services is enabled on the Exchange e-mail server.
One way to verify this is to access the exchange.asmx page on the e-mail server by using one of the following URLs: http://server-address/ews/exchange.asmx or https://server-address/ews/exchange.asmx.
If you are using the emulator, provide your emulator with network capabilities.
Note
The ActiveSync AUTD feature does not run when ActiveSync is providing the network connection. You can use Device Emulator 2.0, which is included with the Windows Mobile 6 Professional SDK or as a separate download, to bind your NE2000 PCMCIA card to a host network adapter by configuring emulator properties.
When you have the emulator up and running, configure ActiveSync to communicate with your Exchange e-mail server. For more information, see "Step 5: Configure and Manage Mobile Device Access on the Exchange Server" in Deploying Windows Mobile 6 Powered Devices with Microsoft Exchange Server 2007 on the Microsoft TechNet Web site.
Creating the Application for the Device
In this procedure, you build an application for the device that represents the client, and then create and send a message to the server by using the mail transport.
To create the application for the device
Create a new Smart Device project in Visual Studio.
Add the following references to the project:
Microsoft.ServiceModel.Mail.dll
Microsoft.ServiceModel.Mail.WindowsMobile.dll
System.ServiceModel.dll
System.Runtime.Serialization.dll
Add the CFMessagingSerializer class, which is described in How to: Serialize Messages in WCF Applications.
On the desktop, you can use either a custom serializer or attributes to create serialized data. However, we recommend that you use the same serializer for both the device and the desktop.
Build the message.
Dim str As String = "Hello"
String str = "Hello";
Create the message and serialize it.
' Create the message. Dim serializer As New CFMessagingSerializer(GetType(String)) Dim m As Message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer)
// Create the message. CFMessagingSerializer serializer = new CFMessagingSerializer(typeof(string)); Message m = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer);
Create variables to represent the channel name, the device e-mail address, and the server e-mail address.
Dim channelName As String = "StoreandFowardMessageHelloWorld" Dim serverAddress As String = "ServerMailAddress@fabrikam.com" Dim clientAddress As String = "DeviceMailAddress@fabrikam.com"
string channelName = "StoreandFowardMessageHelloWorld"; string serverAddress = "ServerMailAddress@fabrikam.com"; string clientAddress = "DeviceMailAddress@fabrikam.com";
Build the output channel.
' Build the output channel. Dim binding As New WindowsMobileMailBinding() Dim parameters As New BindingParameterCollection() Dim channelFactory As IChannelFactory(Of IOutputChannel) channelFactory = binding.BuildChannelFactory(Of IOutputChannel)(parameters) channelFactory.Open() Dim outChannel As IOutputChannel = channelFactory.CreateChannel(New EndpointAddress(MailUriHelper.Create(channelName, serverAddress))) outChannel.Open()
// Build the output channel. WindowsMobileMailBinding binding = new WindowsMobileMailBinding(); BindingParameterCollection parameters = new BindingParameterCollection(); IChannelFactory<IOutputChannel> channelFactory = binding.BuildChannelFactory<IOutputChannel>(parameters); channelFactory.Open(); IOutputChannel outChannel = channelFactory.CreateChannel(new EndpointAddress(MailUriHelper.Create(channelName,serverAddress))); outChannel.Open();
Add code to send the message.
' Send the message. outChannel.Send(m)
// Send the message. outChannel.Send(m);
Build a listener and add code to listen for the response.
The listener blocks code execution. Therefore, we recommend that you run the listener in a separate thread in your production code. For this example, add the listener code after the sender code.
' Listen for the response. Dim listener As IChannelListener(Of IInputChannel) listener = binding.BuildChannelListener(Of IInputChannel)(MailUriHelper.CreateUri(channelName, clientAddress)) listener.Open() Dim inputChannel As IInputChannel = listener.AcceptChannel() inputChannel.Open() Dim reply As Message = inputChannel.Receive()
// Listen for the response. IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(MailUriHelper.CreateUri(channelName,clientAddress),parameters); listener.Open(); IInputChannel inputChannel = listener.AcceptChannel(); inputChannel.Open(); Message reply = inputChannel.Receive();
When a response is received from the server, deserialize the response and present the result to the user.
' When you receive a response, deserialize the message. str = reply.GetBody(Of String)(serializer) MessageBox.Show(str, "Received message")
// When you receive a response, deserialize the message. str = reply.GetBody<string>(serializer); MessageBox.Show(str, "Received message");
Clean up.
outChannel.Close() channelFactory.Close() listener.Close() inputChannel.Close() binding.Close()
outChannel.Close(); channelFactory.Close(); listener.Close(); inputChannel.Close(); binding.Close();
Build the client application and deploy it to the emulator or device that you configured to synchronize with your Exchange e-mail server.
Creating the Application for the Desktop
In this procedure, you build an application for a desktop computer, which represents the server in this example. The server processes a message from the client, appends it, and sends it back to the client.
To create the application for the desktop
Create a new Windows Console Application.
Add the following references to the project:
Microsoft.ServiceModel.Mail.dll
Microsoft.ServiceModel.Channels.Mail.ExchangeWebService.dll
System.ServiceModel.dll
System.Runtime.Serialization.dll
Add the CFMessagingSerializer class, which is described in How to: Serialize Messages in WCF Applications.
Create some variables, some of which must correspond to values from the device project.
' Set some global variables. Dim channelName As String = "StoreandFowardMessageHelloWorld" Dim serverAddress As String = "ServerMailAddress@fabrikam.com" Dim serverPWD As String = "MyPassword" Dim clientAddress As String = "DeviceMailAddress@fabrikam.com" Dim exchangeServerLocation As String = "http://fabrikam"
// Set some global variables. string channelName = "StoreandFowardMessageHelloWorld"; string serverAddress = "ServerMailAddress@fabrikam.com"; string serverPWD = "MyPassword"; string clientAddress = "DeviceMailAddress@fabrikam.com"; string exchangeServerLocation = "http://fabrikam";
Create the listener.
If you are using Windows credentials, pass a null value as the second argument to the ExchangeWebServiceMailBinding object. As on the device, the input channel blocks code execution. Therefore, we recommend that you create a new thread for each listener in your production code.
' Create the listener. If you are using Windows credentials, ' pass a null value as the second argument to the ExchangeWebServiceMailBinding. Dim binding As MailBindingBase binding = New ExchangeWebServiceMailBinding(New Uri(exchangeServerLocation), New System.Net.NetworkCredential(serverAddress, serverPWD)) Dim parameters As New BindingParameterCollection() Dim listener As IChannelListener(Of IInputChannel) listener = binding.BuildChannelListener(Of IInputChannel)(MailUriHelper.CreateUri(channelName, serverAddress)) listener.Open() Dim inputChannel As IInputChannel = listener.AcceptChannel() inputChannel.Open() Dim reply As Message = inputChannel.Receive() Dim serializer As New CFMessagingSerializer(GetType(String)) Dim str As String = "" str = reply.GetBody(Of String)(serializer)
// Create the listener. If you are using Windows credentials, // pass a null value as the second argument to the ExchangeWebServiceMailBinding. MailBindingBase binding = new ExchangeWebServiceMailBinding(new Uri(exchangeServerLocation), new System.Net.NetworkCredential(serverAddress, serverPWD)); BindingParameterCollection parameters = new BindingParameterCollection(); IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel> (MailUriHelper.CreateUri(channelName, serverAddress), parameters); listener.Open(); IInputChannel inputChannel = listener.AcceptChannel(); inputChannel.Open(); Message reply = inputChannel.Receive(); CFMessagingSerializer serializer = new CFMessagingSerializer(typeof(string)); string str = ""; str = reply.GetBody<string>(serializer);
Add code to process the message.
' Process the message. str += ", World!"
// Process the message. str += ", World!";
Add code to send the response through an output channel.
' Send the response through an output channel. Dim m As Message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer) Dim channelFactory As IChannelFactory(Of IOutputChannel) channelFactory = binding.BuildChannelFactory(Of IOutputChannel)(parameters) channelFactory.Open() Dim outChannel As IOutputChannel = channelFactory.CreateChannel(New EndpointAddress(MailUriHelper.CreateUri(channelName, clientAddress))) outChannel.Open() outChannel.Send(m)
// Send the response through an output channel. Message m = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer); IChannelFactory<IOutputChannel> channelFactory = binding.BuildChannelFactory<IOutputChannel>(parameters); channelFactory.Open(); IOutputChannel outChannel = channelFactory.CreateChannel(new EndpointAddress( MailUriHelper.CreateUri(channelName, clientAddress))); outChannel.Open(); outChannel.Send(m);
Clean up.
' Clean up. outChannel.Close() channelFactory.Close() listener.Close() inputChannel.Close() binding.Close()
// Clean up. outChannel.Close(); channelFactory.Close(); listener.Close(); inputChannel.Close(); binding.Close();
Build the project and start the server application.
Start the client application on the emulator or the device.
Example
Description
The following complete examples demonstrate how to send and receive messages by using the WCF Exchange Server mail transport.
Complete Code Listing for the Device (Client)
Dim str As String = "Hello"
' Create the message.
Dim serializer As New CFMessagingSerializer(GetType(String))
Dim m As Message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer)
Dim channelName As String = "StoreandFowardMessageHelloWorld"
Dim serverAddress As String = "ServerMailAddress@fabrikam.com"
Dim clientAddress As String = "DeviceMailAddress@fabrikam.com"
' Build the output channel.
Dim binding As New WindowsMobileMailBinding()
Dim parameters As New BindingParameterCollection()
Dim channelFactory As IChannelFactory(Of IOutputChannel)
channelFactory = binding.BuildChannelFactory(Of IOutputChannel)(parameters)
channelFactory.Open()
Dim outChannel As IOutputChannel = channelFactory.CreateChannel(New EndpointAddress(MailUriHelper.Create(channelName, serverAddress)))
outChannel.Open()
' Send the message.
outChannel.Send(m)
' Listen for the response.
Dim listener As IChannelListener(Of IInputChannel)
listener = binding.BuildChannelListener(Of IInputChannel)(MailUriHelper.CreateUri(channelName, clientAddress))
listener.Open()
Dim inputChannel As IInputChannel = listener.AcceptChannel()
inputChannel.Open()
Dim reply As Message = inputChannel.Receive()
' When you receive a response, deserialize the message.
str = reply.GetBody(Of String)(serializer)
MessageBox.Show(str, "Received message")
outChannel.Close()
channelFactory.Close()
listener.Close()
inputChannel.Close()
binding.Close()
End Sub
End Class
static void Main()
{
String str = "Hello";
// Create the message.
CFMessagingSerializer serializer = new CFMessagingSerializer(typeof(string));
Message m = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer);
string channelName = "StoreandFowardMessageHelloWorld";
string serverAddress = "ServerMailAddress@fabrikam.com";
string clientAddress = "DeviceMailAddress@fabrikam.com";
// Build the output channel.
WindowsMobileMailBinding binding = new WindowsMobileMailBinding();
BindingParameterCollection parameters = new BindingParameterCollection();
IChannelFactory<IOutputChannel> channelFactory = binding.BuildChannelFactory<IOutputChannel>(parameters);
channelFactory.Open();
IOutputChannel outChannel = channelFactory.CreateChannel(new EndpointAddress(MailUriHelper.Create(channelName,serverAddress)));
outChannel.Open();
// Send the message.
outChannel.Send(m);
// Listen for the response.
IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(MailUriHelper.CreateUri(channelName,clientAddress),parameters);
listener.Open();
IInputChannel inputChannel = listener.AcceptChannel();
inputChannel.Open();
Message reply = inputChannel.Receive();
// When you receive a response, deserialize the message.
str = reply.GetBody<string>(serializer);
MessageBox.Show(str, "Received message");
outChannel.Close();
channelFactory.Close();
listener.Close();
inputChannel.Close();
binding.Close();
}
Complete Code Listing for the Desktop (Server)
' Set some global variables.
Dim channelName As String = "StoreandFowardMessageHelloWorld"
Dim serverAddress As String = "ServerMailAddress@fabrikam.com"
Dim serverPWD As String = "MyPassword"
Dim clientAddress As String = "DeviceMailAddress@fabrikam.com"
Dim exchangeServerLocation As String = "http://fabrikam"
' Create the listener. If you are using Windows credentials,
' pass a null value as the second argument to the ExchangeWebServiceMailBinding.
Dim binding As MailBindingBase
binding = New ExchangeWebServiceMailBinding(New Uri(exchangeServerLocation), New System.Net.NetworkCredential(serverAddress, serverPWD))
Dim parameters As New BindingParameterCollection()
Dim listener As IChannelListener(Of IInputChannel)
listener = binding.BuildChannelListener(Of IInputChannel)(MailUriHelper.CreateUri(channelName, serverAddress))
listener.Open()
Dim inputChannel As IInputChannel = listener.AcceptChannel()
inputChannel.Open()
Dim reply As Message = inputChannel.Receive()
Dim serializer As New CFMessagingSerializer(GetType(String))
Dim str As String = ""
str = reply.GetBody(Of String)(serializer)
' Process the message.
str += ", World!"
' Send the response through an output channel.
Dim m As Message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer)
Dim channelFactory As IChannelFactory(Of IOutputChannel)
channelFactory = binding.BuildChannelFactory(Of IOutputChannel)(parameters)
channelFactory.Open()
Dim outChannel As IOutputChannel = channelFactory.CreateChannel(New EndpointAddress(MailUriHelper.CreateUri(channelName, clientAddress)))
outChannel.Open()
outChannel.Send(m)
' Clean up.
outChannel.Close()
channelFactory.Close()
listener.Close()
inputChannel.Close()
binding.Close()
End Sub
End Class
static void Main()
{
// Set some global variables.
string channelName = "StoreandFowardMessageHelloWorld";
string serverAddress = "ServerMailAddress@fabrikam.com";
string serverPWD = "MyPassword";
string clientAddress = "DeviceMailAddress@fabrikam.com";
string exchangeServerLocation = "http://fabrikam";
// Create the listener. If you are using Windows credentials,
// pass a null value as the second argument to the ExchangeWebServiceMailBinding.
MailBindingBase binding = new ExchangeWebServiceMailBinding(new Uri(exchangeServerLocation),
new System.Net.NetworkCredential(serverAddress, serverPWD));
BindingParameterCollection parameters = new BindingParameterCollection();
IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>
(MailUriHelper.CreateUri(channelName, serverAddress), parameters);
listener.Open();
IInputChannel inputChannel = listener.AcceptChannel();
inputChannel.Open();
Message reply = inputChannel.Receive();
CFMessagingSerializer serializer = new CFMessagingSerializer(typeof(string));
string str = "";
str = reply.GetBody<string>(serializer);
// Process the message.
str += ", World!";
// Send the response through an output channel.
Message m = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:test", str, serializer);
IChannelFactory<IOutputChannel> channelFactory = binding.BuildChannelFactory<IOutputChannel>(parameters);
channelFactory.Open();
IOutputChannel outChannel = channelFactory.CreateChannel(new EndpointAddress(
MailUriHelper.CreateUri(channelName, clientAddress)));
outChannel.Open();
outChannel.Send(m);
// Clean up.
outChannel.Close();
channelFactory.Close();
listener.Close();
inputChannel.Close();
binding.Close();
}
Compiling the Code
The example that runs on the device requires references to the following namespaces:
The example that runs on the desktop requires references to the following namespaces:
Security
Mail transport security is not enabled in this example. For more information, see WCF Exchange Server Mail Transport.
See Also
Tasks
How to: Use Message Security with the WCF Exchange Server Mail Transport
Other Resources
Windows Communication Foundation (WCF) Development and the .NET Compact Framework