演练:使用 WCF Exchange Server 邮件传输

更新:2007 年 11 月

您可以创建基于 Windows Communication Foundation (WCF) Exchange Server 邮件传输的应用程序,以便通过将运行 Microsoft Exchange Server 的计算机用作中介在指定的输入/输出信道中发送和接收邮件。基于 WCF Exchange Server 邮件传输的应用程序在台式机和设备上均受支持。

本演练介绍 WCF Exchange Server 邮件传输的功能,并阐释了下列任务:

  • 设置计算机。

  • 为设备(客户端)生成应用程序。

  • 为台式机(服务器)生成应用程序。

有关这些过程中所显示的完整代码清单,请参见本演练结尾处的“示例”一节。

说明:

请勿在成品代码中使用此示例。

先决条件

此示例需要使用 .NET Compact Framework 3.5 版。

设置计算机

在此过程中,应确保正确设置开发环境,以运行给出的示例。

设置计算机以运行给出的示例

  1. 安装 Windows Mobile 5.0 版或 Windows Mobile 6 软件开发工具包 (SDK)。

    Windows Mobile 6 Professional SDK 包括 ActiveSync 始终最新 (AUTD) 功能,设备上的邮件传输使用此功能将“收件箱”保持为最新状态。有关更多信息,请参见 Windows Mobile Web site(Windows Mobile 网站)。

  2. 确保可通过网络访问运行 Microsoft Exchange Server 2007 的电子邮件服务器。

    如果没有 Exchange Server 2007,可以使用在虚拟 PC 上运行的试用版本。有关更多信息,请参见 Exchange Server Web site(Exchange Server 网站)。

  3. 通过在计算机上运行 Outlook Web Access (OWA) 并连接至一个电子邮件帐户,验证计算机是否可以连接到新的 Exchange 电子邮件服务器。

  4. 确保 Exchange 电子邮件服务器上启用了 Exchange Web 服务。

    一种验证方法是使用下列 URL 之一访问电子邮件服务器上的 exchange.asmx 页:http://服务器地址/ews/exchange.asmx 或 https://服务器地址/ews/exchange.asmx。

  5. 如果使用了仿真程序,请为其提供网络功能。

    说明:

    当 ActiveSync 提供网络连接时,将不会运行 ActiveSync AUTD 功能。您可以使用 Device Emulator 2.0(包括在 Windows Mobile 6 Professional SDK 中,也可以单独下载)并通过配置仿真程序属性将 NE2000 PCMCIA 卡绑定到宿主网络适配器上。

  6. 在启动并运行仿真程序后,请配置 ActiveSync 以便与 Exchange 电子邮件服务器进行通信。有关更多信息,请参见位于 Microsoft TechNet 网站上的 Deploying Windows Mobile 6 Powered Devices with Microsoft Exchange Server 2007(将基于 Windows Mobile 6 的设备与 Microsoft Exchange Server 2007 部署在一起)中的“Step 5: Configure and Manage Mobile Device Access on the Exchange Server”(步骤 5:在 Exchange Server 上配置和管理移动设备访问)。

为设备创建应用程序

在此过程中,将为表示客户端的设备生成应用程序,然后使用邮件传输创建邮件并将其发送到服务器。

为设备创建应用程序

  1. 在 Visual Studio 中创建一个新的智能设备项目。

  2. 将下列引用添加到该项目中:

    • Microsoft.ServiceModel.Mail.dll

    • Microsoft.ServiceModel.Mail.WindowsMobile.dll

    • System.ServiceModel.dll

    • System.Runtime.Serialization.dll

  3. 添加 CFMessagingSerializer 类(如何:序列化 WCF 应用程序中的消息中进行了描述)。

    在台式机上,可以使用自定义序列化程序或属性来创建序列化数据。但是,我们建议对设备和台式机使用同一个序列化程序。

  4. 生成邮件。

    Dim str As String = "Hello"
    
    String str = "Hello";
    
  5. 创建邮件并对它加以序列化。

    ' 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);
    
  6. 创建表示信道名称、设备电子邮件地址以及服务器电子邮件地址的变量。

    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";
    
  7. 生成输出信道。

    ' 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();
    
  8. 添加发送邮件的代码。

    ' Send the message.
    outChannel.Send(m)
    
    // Send the message.
    outChannel.Send(m);
    
  9. 生成侦听器并添加侦听响应的代码。

    侦听器会阻止代码执行。因此,在成品代码中,我们建议在单独的线程中运行侦听器。在此示例中,请将侦听器代码添加到发送方代码之后。

    ' 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();
    
  10. 收到来自服务器的响应后,对响应进行反序列化并向用户显示结果。

    ' 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");
    
  11. 进行清理。

    outChannel.Close()
    channelFactory.Close()
    
    listener.Close()
    inputChannel.Close()
    binding.Close()
    
    outChannel.Close();
    channelFactory.Close();
    
    listener.Close();
    inputChannel.Close();
    binding.Close();
    
  12. 生成客户端应用程序,然后将其部署到配置为与 Exchange 电子邮件服务器进行同步的仿真程序或设备中。

为台式机创建应用程序

在此过程中,将为台式计算机(在此示例中表示服务器)生成应用程序。服务器将处理来自客户端的邮件,并在追加邮件后将其发送回客户端。

为台式机创建应用程序

  1. 创建一个新的 Windows 控制台应用程序。

  2. 将下列引用添加到该项目中:

    • Microsoft.ServiceModel.Mail.dll

    • Microsoft.ServiceModel.Channels.Mail.ExchangeWebService.dll

    • System.ServiceModel.dll

    • System.Runtime.Serialization.dll

  3. 添加 CFMessagingSerializer 类(如何:序列化 WCF 应用程序中的消息中进行了描述)。

  4. 创建一些变量,其中某些变量必须对应于设备项目中的值。

    ' 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";
    
  5. 创建侦听器。

    如果使用了 Windows 凭据,请将 null 值作为第二个参数传递给 ExchangeWebServiceMailBinding 对象。与在设备上的情况相同,输入信道也会阻止代码执行。因此,我们建议在成品代码中为每个侦听器创建一个新线程。

    ' 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);
    
  6. 添加处理邮件的代码。

    ' Process the message.
    str += ", World!"
    
    // Process the message.
    str += ", World!";
    
  7. 添加通过输出信道发送响应的代码。

    ' 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);
    
  8. 进行清理。

    ' Clean up.
    outChannel.Close()
    channelFactory.Close()
    
    listener.Close()
    inputChannel.Close()
    binding.Close()
    
    // Clean up.
    outChannel.Close();
    channelFactory.Close();
    
    listener.Close();
    inputChannel.Close();
    binding.Close();
    
  9. 生成项目并启动服务器应用程序。

  10. 启动仿真程序或设备上的客户端应用程序。

示例

说明

下面的完整示例演示如何使用 WCF Exchange Server 邮件传输发送和接收邮件。

针对设备(客户端)的完整代码清单

        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();
}

针对台式机(服务器)的完整代码清单

        ' 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();
}

编译代码

在设备上运行的示例需要引用下列命名空间:

在台式机上运行的示例需要引用下列命名空间:

安全性

此示例中未启用邮件传输安全性。有关更多信息,请参见 WCF Exchange Server 邮件传输

请参见

任务

如何:在 WCF Exchange Server 邮件传输中使用消息安全性

其他资源

Windows Communication Foundation (WCF) 开发与 .NET Compact Framework