none
Sending Mail Using ExchangeServerBinding : The request failed with HTTP status 401: Unauthorized. RRS feed

  • Question

  • I am trying to send mail using ExchangeServerBinding

    I was struck up with an error, please assist me to accomplish this.

    Error:

    Stacktrace:

    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

       at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

       at com.outlook.EWSTest.ExchangeServiceBinding.CreateItem(CreateItemType CreateItem1) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\ewsmailserviceweb\cfd91776\ba3659b7\App_WebReferences.t3lp9tgj.0.cs:line 1492

       at _Default.SendEmailEWSTest()

    Message:

    The request failed with HTTP status 401: Unauthorized.

    Steps I have done:

    1. Addwebreference in the project. (create proxy)
    2. Adding namespaces.

    using com.outlook.EWSTest;

    using System.Net;

    using System.Net.Security;

    using System.Security.Cryptography.X509Certificates;

    1. I was mentioned below few methods, which I used for sending

    public static int SendEmailEWSTest()

        {

            ServicePointManager.ServerCertificateValidationCallback = ValidateX509Certificate;

            ExchangeServiceBinding esb = CreateBinding();

            CreateItemType createEmailRequest = CreateEmailRequest();

            MessageType message = new MessageType();

            message.Subject = "EWS Test Mail";

            message.Body = new BodyType();

            message.Body.BodyType1 = BodyTypeType.Text;

            message.Body.Value = "Auto Generated by System, dont reply.";

            message.Sender = new SingleRecipientType();

            message.Sender.Item = new EmailAddressType();

           

    message.Sender.Item.EmailAddress = "sender@domain.com";

            message.ToRecipients = new EmailAddressType[1];

            message.ToRecipients[0] = new EmailAddressType();

            message.ToRecipients[0].EmailAddress = "recipient@domain.com";

            message.Sensitivity = SensitivityChoicesType.Normal;

            createEmailRequest.Items.Items = new ItemType[1];

            createEmailRequest.Items.Items[0] = message;

            try

            {

                CreateItemResponseType createItemResponse = esb.CreateItem(createEmailRequest);

                ArrayOfResponseMessagesType responses = createItemResponse.ResponseMessages;

                foreach (ResponseMessageType response in responses.Items)

                {

                    Console.WriteLine("{0} : {1} ", response.ResponseCode, response.MessageText);

                }

                return 0;

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.Message);

                return 1;

            }

        }

    public static ExchangeServiceBinding CreateBinding()

        {

            ExchangeServiceBinding esb = new ExchangeServiceBinding();

            esb.UseDefaultCredentials = true;

            esb.PreAuthenticate = true;

            esb.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            esb.Credentials = new NetworkCredential("username", "password", “domain”);

            esb.Url = @"https://ExchangeServer/EWS/Exchange.asmx";

            exExchangeImpersonation.ConnectingSID = csConnectingSid; 

            esb.ExchangeImpersonation = exExchangeImpersonation;

            esb.RequestServerVersionValue = new RequestServerVersion();

            esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007;

            return esb;

        }

        public static CreateItemType CreateEmailRequest()

        {

            CreateItemType createEmailRequest = new CreateItemType();

            createEmailRequest.MessageDisposition = MessageDispositionType.SendAndSaveCopy;

            createEmailRequest.MessageDispositionSpecified = true;

            createEmailRequest.SavedItemFolderId = new TargetFolderIdType();

            DistinguishedFolderIdType sent = new DistinguishedFolderIdType();

            sent.Id = DistinguishedFolderIdNameType.sentitems;

            createEmailRequest.SavedItemFolderId.Item = sent;

            createEmailRequest.Items = new NonEmptyArrayOfAllItemsType();

            return createEmailRequest;

        }

    public static bool ValidateX509Certificate (Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)

        {

            if (sslPolicyErrors == SslPolicyErrors.None)

                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            return false;

        }

    for authentication purpose written generic details like.. URL, Username, Password....

    Wednesday, July 11, 2012 2:30 PM

All replies

  • mdprasad,

    Are you sending the request to the correct service endpoint? Better yet, instead of using an auto-generated proxy, you should download and use the EWS Managed API. It is much easier to use, fewer lines of code required to do what you want, and there is a lot of client-side business logic built in it, including Autodiscover which will find the correct service endpoint.

    Download it here: http://www.microsoft.com/en-us/download/details.aspx?id=30141
    Documentation here: http://msdn.microsoft.com/en-us/library/dd633709(EXCHG.80).aspx

    With regards,


    Michael | Microsoft Exchange SDK

    The Exchange Development Forum Guide has useful information for using the Exchange Development Forum.

    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.


    Wednesday, July 11, 2012 5:43 PM
    Moderator
  • Michael! Thanks for assisting.

    I was successful with Exchange Server API(EwsManagedApi32.msi), but our requirement is to adding webreference to our current project.

    And develop code using ExchangeServiceBinding.

    Using autodiscover we found the service endpoint url, and that is fine to working in two different methods.

    1. Exchange service class using manual

    ExchangeService service = new ExchangeService();

    service.Credentials = new WebCredentials("username@domain.com", "*********");

    service.Url = new Uri("https://************/EWS/Exchange.asmx");

    1. Exchange service class using autodiscover.

    ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);

    service.Credentials = new WebCredentials("username@domain.com ", "*********");

    service.AutodiscoverUrl("username@domain.com ", RedirectionUrlValidationCallback);

    static bool RedirectionUrlValidationCallback(String redirectionUrl)

    {

    return (redirectionUrl == "https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml");

    }

    The same endpoint url using in ExchangeServiceBinding, I got exception: The request failed with HTTP status 401: Unauthorized.

    This is brief discription about this issue,  and I have few queries on my development.

    If you can look into this and help me out that would be a great help.

    1. Which credentials do we use “esb.Credentials = new NetworkCredential("username", "password", “domain”);
      1. Windows userid, password, domain
      2. Outlook username and password.
      3. Or any other.

    1. Service endpoint url is generated by autodiscover process in exchangeservice.
      1. Is the same url can we use or any other url needed.

    1. Impersonation is needed or not.

    1. I am using following callback method for certificate validation
      1. Certificate validation is needed or not (in msdn documentation it was mention : “After you set up the ExchangeServiceBinding proxy class, you must handle X509 certificates for SSL over HTTP”).
      2. Wheather these methods are enough for certificate validation

    ServicePointManager.ServerCertificateValidationCallback = ValidateX509Certificate;

    public static bool ValidateX509Certificate (Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)

        {

             // If the certificate is a valid, signed certificate, return true.

            if (sslPolicyErrors == SslPolicyErrors.None)

                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            return false;

          .

    .

    .

    .

        }

    Thanks in advance.

    Thursday, July 12, 2012 9:26 AM
  • Hello mdprasad,

    Your redirection call back will not work properly. It will only return true for one option in the Autodiscover retry attempts. That callback should only check to make sure that the redirection is targeting an endpoint with TLS. Use something like:

        private static bool RedirectionUrlValidationCallback(string redirectionUrl)
        {
          // The default for the validation callback is to reject the URL.
          bool result = false;
    
          Uri redirectionUri = new Uri(redirectionUrl);
    
          // Validate the contents of the redirection URL. In this simple validation
          // callback, the redirection URL is considered valid if it is using HTTPS
          // to encrypt the authentication credentials. 
          if (redirectionUri.Scheme == "https")
          {
            result = true;
          }
    
          return result;
        }

    Here is a better example for validating certifcate: http://msdn.microsoft.com/en-us/library/dd633677(v=exchg.80)

    I'm very curious as to why you have a requirement that you use an auto-generated object model (as in use the Add Web Reference option in Visual Studio) versus using the EWS Managed API. We have deemphasized the auto-generated object model in favor of the EWS Managed API for many reasons. The EWS Managed API is a restributable dll that you can ship with your product. Can you help me understand why your solution architect has placed a requirement on using the auto-generated proxy object model? 

    With regards,

     


    Michael | Microsoft Exchange SDK

    The Exchange Development Forum Guide has useful information for using the Exchange Development Forum.

    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Thursday, July 12, 2012 3:19 PM
    Moderator