1

目前我在尝试使用EWS时遇到问题,最初的要求是连接到特定用户的邮件,然后搜索特定文件夹,搜索邮件然后将附件下载到特定文件夹到本地机器,以便稍后它可以由集成服务处理,我不想使用 EWS 托管 API,因为我不想在迁移到生产服务器时安装任何东西,现在我的想法是开发一个 WCF通过 .asmx uri 连接到 EWS 服务并且能够满足我的要求的服务,现在我可以连接到公司的 EWS,但我有一些疑问:

根据微软的说法:http: //msdn.microsoft.com/en-us/library/exchange/bb408524 (v=exchg.150).aspx他们说你必须为你的项目添加一个 Web 服务引用,尽管它只提到了 VS 2005 和 VS 2008(我正在使用 VS 2012),它应该自动创建 ExchangeServiceBinding 类,它为您提供模拟帐户所需的一切,我的第一个问题是:为什么我没有看到这个类添加到我的项目?我应该期望这是因为我使用的是 VS 2012 吗?

好的,无论如何我可以使用getPasswordExpirationTime之类的方法,但是当我使用FindFolder方法时,我收到错误:“该帐户无权模拟请求的用户。”,这是我的方法:

using (ExchangeServicePortTypeClient exchangeServicePortTypeClient = new ExchangeServicePortTypeClient())
                {
                    exchangeServicePortTypeClient.ChannelFactory.Endpoint.Address = new EndpointAddress("https://email.kraft.com/EWS/Exchange.asmx");


                    FindFolderResponseType findFolderResponseType = null;

                    exchangeServicePortTypeClient.FindFolder(
                        new ExchangeImpersonationType
                        {
                            ConnectingSID = new ConnectingSIDType
                            {
                                Item = @"gilberto.gutierrez@mdlz.com",
                                ItemElementName = ItemChoiceType1.PrimarySmtpAddress
                            }
                        },
                        null,
                        new RequestServerVersion { Version = ExchangeVersionType.Exchange2010_SP2 },
                        null,
                        new FindFolderType
                        {
                            FolderShape = new FolderResponseShapeType
                            {
                                BaseShape =
                                  DefaultShapeNamesType.Default
                            }
                        }, out findFolderResponseType);

                }                   

我试图通过这个设置凭据:

exchangeServicePortTypeClient.ClientCredentials.Windows.ClientCredential.UserName
exchangeServicePortTypeClient.ClientCredentials.Windows.ClientCredential.Password      
exchangeServicePortTypeClient.ClientCredentials.Windows.ClientCredential.Domain             
exchangeServicePortTypeClient.ChannelFactory.Credentials.Windows.ClientCredential.UserName
exchangeServicePortTypeClient.ChannelFactory.Credentials.Windows.ClientCredential.Password
exchangeServicePortTypeClient.ChannelFactory.Credentials.Windows.ClientCredential.Domain

没有运气:(。

顺便说一句,这是我的 wcf 配置文件。

<?xml version="1.0" encoding="utf-8"?>

<configuration>

    <!--Diagnostics section, we will only catch error and warning in production-->

    <system.diagnostics>
        <sources>
            <source propagateActivity="true" name="System.ServiceModel" switchValue="Error, Warning">
                <listeners>
                    <add type="System.Diagnostics.DefaultTraceListener" name="Default">
                        <filter type="" />
                    </add>
                    <add type="System.Diagnostics.DefaultTraceListener" name="SellOut.ExchangeWcfService">
                        <filter type="" />
                    </add>
                    <add name="ServiceModelTraceListener">
                        <filter type="" />
                    </add>
                </listeners>
            </source>
            <source name="System.ServiceModel.MessageLogging" switchValue="Error, Warning">
                <listeners>
                    <add type="System.Diagnostics.DefaultTraceListener" name="Default">
                        <filter type="" />
                    </add>
                    <add type="System.Diagnostics.DefaultTraceListener" name="SellOut.ExchangeWcfService">
                        <filter type="" />
                    </add>
                    <add name="ServiceModelMessageLoggingListener">
                        <filter type="" />
                    </add>
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add initializeData="C:\Users\LFH2623\Documents\SellOut\SellOut\SellOut.Hosts.ExchangeWcfService\SellOut.ExchangeWcfService_web_tracelog.svclog"
              type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
              name="ServiceModelTraceListener" traceOutputOptions="LogicalOperationStack, DateTime, Callstack">
                <filter type="" />
            </add>
            <add initializeData="C:\Users\LFH2623\Documents\SellOut\SellOut\SellOut.Hosts.ExchangeWcfService\SellOut.ExchangeWcfService_web_messages.svclog"
                type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                name="ServiceModelMessageLoggingListener" traceOutputOptions="LogicalOperationStack, DateTime, Callstack">
                <filter type="" />
            </add>
        </sharedListeners>
        <trace autoflush="true" />
    </system.diagnostics>

    <!--Framework Section-->

    <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    </appSettings>  

    <!--Web section-->

    <system.web>        
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" maxRequestLength="2147483646" />
    </system.web>

    <!--Web server section-->

    <system.webServer>
        <directoryBrowse enabled="false"/>
        <defaultDocument enabled="true"/>               
        <modules runAllManagedModulesForAllRequests="true"/>
    </system.webServer>

    <!--WS section-->

    <system.serviceModel>

        <diagnostics>
            <messageLogging logMalformedMessages="true"
                            maxMessagesToLog="10000"
                            logMessagesAtTransportLevel="true"
                            logMessagesAtServiceLevel="True"
                            logEntireMessage="true"/>
            <endToEndTracing activityTracing="false" />
        </diagnostics>

        <!--For the ExchangeWebService we will aply the following service and endpoint behaviors-->

        <behaviors>

            <serviceBehaviors>
                <behavior name="ExchangeWebService">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
                    <serviceDebug includeExceptionDetailInFaults="false" httpHelpPageEnabled="true" />
                    <dataContractSerializer maxItemsInObjectGraph="2147483646" />
                    <serviceTimeouts transactionTimeout="01:00:00" />
                    <serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="100" maxConcurrentInstances="100"/>
                    <serviceDiscovery>
                        <announcementEndpoints>
                            <endpoint kind="udpAnnouncementEndpoint"></endpoint>
                        </announcementEndpoints>
                    </serviceDiscovery>
                </behavior>             
            </serviceBehaviors>

            <!-- Define the corresponding scope for the clients to find the service through resolve message -->

            <endpointBehaviors>
                <behavior name="ExchangeWebService">
                    <endpointDiscovery enabled="true">
                        <scopes>
                            <add scope="http://SellOut.ExchangeWcfService/"/>
                        </scopes>
                    </endpointDiscovery>
                </behavior>
            </endpointBehaviors>

        </behaviors>

        <!-- In case you want to scale this service -->

        <standardEndpoints>

            <!-- We allow the service to be discoverable through the network in an adhoc architecture through UDP -->

            <udpDiscoveryEndpoint>
                <standardEndpoint name="adhocDiscoveryEndpointConfiguration"
                                  discoveryMode="Adhoc"
                                  discoveryVersion="WSDiscovery11"
                                  maxResponseDelay="00:00:10">
                </standardEndpoint>
            </udpDiscoveryEndpoint>

            <!-- We allow the service to be discoverable through the network in a managed architecture -->

            <discoveryEndpoint>
                <standardEndpoint name="managedDiscoveryEndpoint" discoveryMode="Managed" maxResponseDelay="00:01:00"/>
            </discoveryEndpoint>

            <!-- We announce the service with hello & bye -->

            <announcementEndpoint>
                <standardEndpoint name="udpAnnouncementEndpointConfiguration"
                                  discoveryVersion="WSDiscovery11" />
            </announcementEndpoint>

        </standardEndpoints>

        <!--All the Kraft's clients are .net, so we will use the proprietary binary message encoding to reduce the message's size -->

        <bindings>
            <customBinding>
                <binding name="wsHttpBindingBynaryEncoding"
                         closeTimeout="00:10:00"
                         openTimeout="00:10:00"
                         receiveTimeout="00:10:00"
                         sendTimeout="00:10:00">
                    <binaryMessageEncoding>
                        <readerQuotas maxDepth="32"
                                      maxStringContentLength="5242880"
                                      maxArrayLength="2147483646"
                                      maxBytesPerRead="4096"
                                      maxNameTableCharCount="5242880" />
                    </binaryMessageEncoding>
                    <httpTransport
                                    transferMode="Buffered"
                                    maxBufferPoolSize="2147483646"
                                    maxReceivedMessageSize="2147483646">
                    </httpTransport>
                </binding>
            </customBinding>

            <basicHttpBinding>
                <binding name="KraftEWS" messageEncoding="Text" transferMode="Buffered">
                    <security mode="Transport">
                        <transport clientCredentialType="Windows" proxyCredentialType="Windows"></transport>                        
                    </security>             
                </binding>
            </basicHttpBinding>

        </bindings>

        <!-- We reference the Kraft EWS -->

        <client>
            <endpoint binding="basicHttpBinding" bindingConfiguration="KraftEWS"
                      contract="KraftEWS.ExchangeServicePortType"                                     
                      name="ExchangeServiceBinding_ExchangeServicePortType">                
            </endpoint>
        </client>

        <!--Services section-->

        <services>
            <service name="SellOut.Services.Exchange.ExchangeWebService" behaviorConfiguration="ExchangeWebService">
                <endpoint name="rules"
                          address="rules"
                          binding="customBinding"
                          bindingConfiguration="wsHttpBindingBynaryEncoding"
                          behaviorConfiguration="ExchangeWebService"
                          contract="SellOut.Contracts.Exchange.IExchangeRulesContract"/>
                <endpoint name="udpDiscovery"
                          kind="udpDiscoveryEndpoint"
                          endpointConfiguration="adhocDiscoveryEndpointConfiguration" />
                <endpoint name="mex"
                          address="mex"
                          binding="mexHttpBinding"
                          contract="IMetadataExchange" />               
            </service>
        </services>

        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

    </system.serviceModel>

</configuration>

另一件事要提的是,在这个配置中:

<basicHttpBinding>
                    <binding name="KraftEWS" messageEncoding="Text" transferMode="Buffered">
                        <security mode="Transport">
                            <transport clientCredentialType="Windows" proxyCredentialType="Windows"></transport>                        
                        </security>             
                    </binding>
                </basicHttpBinding>

如果我删除部分客户端凭据类型“Windows”,则在尝试运行服务时异常是:

HTTP 请求未经客户端身份验证方案“匿名”授权。从服务器收到的身份验证标头是“协商,NTLM”。

你们能帮帮我吗?

谢谢指教。

4

1 回答 1

0

我强烈建议您为此使用 EWS 托管 API。当您声明不想在生产服务器上安装任何东西时,我不明白您的意思,因为您必须在生产服务器上安装 WCF 服务,以及由添加 Web 服务参考创建的对象模型项目。但是,看起来你已经通过了这部分,所以让我们继续吧......

太好了,很高兴知道您可以调用 getPassowrdExpirationTime。谢谢你给我提供这些信息。

您收到消息“该帐户无权模拟请求的用户”的原因是因为运行您的 WCF 服务的帐户没有模拟邮箱的权限。您需要先设置 Exchange 模拟,然后您的服务帐户才能访问用户的帐户。一旦您的服务具有 Exchange 可以在 AD 中查找的凭据(它已经这样做了),并且它有权模拟您的用户(在您的 TODO 列表中),您的代码应该可以工作,因为身份验证是基于服务帐户的身份完成的。

代码示例之后的问题的所有部分都不在范围内。您不需要对 web.config 进行任何更改(至少我不这么认为)。我假设您正在针对本地服务器进行测试,因为身份验证方案是协商和 NTLM。

带着敬意,

您链接到的文章

于 2013-10-28T22:42:30.330 回答