Exception: EWS 401 Unauthorized Issue on calling client (Java)

We are using Aspose.Email for Java 19.6. We attempt to connect to EWS, but soon as it’s initiated, we get a 401 Unauthorized error.

The problem is that when we try both EWSEditor and Microsoft’s ews-java-api, we are able to successfully connect, which implies this may be an issue in Aspose itself.

We have tried various permutations of username: domain\username, just username, the fully-qualified domain name in the domain parameter, the shortname in the domain parameter, no domain parameter, but all of them fail.

It fails on this line:

client = EWSClient.getEWSClient(mailboxUri, username, password);

and this is the stack trace that gets generated. PutToExchange is the name of our program–we are attempting to put messages in a user’s inbox via impersonation.

Any insight you could please provide would be very appreciated. Thanks so much!

Exception in thread “main” java.lang.IllegalStateException: class com.aspose.email.system.exceptions.WebException: The remote server returned an error: (401) Unauthorized.
com.aspose.email.internal.o.zab.b(Unknown Source)
com.aspose.email.internal.o.zab.a(Unknown Source)
com.aspose.email.internal.o.zbh.a(Unknown Source)
com.aspose.email.internal.o.zbi.invoke(Unknown Source)
com.aspose.email.system.zd.a(Unknown Source)
com.aspose.email.internal.ex.zc.a(Unknown Source)
com.aspose.email.internal.ah.zg.run(SourceFile:66)
java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
java.util.concurrent.FutureTask.run(Unknown Source)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
at com.aspose.email.zra.a(SourceFile:289)
at com.aspose.email.zra.a(SourceFile:357)
at com.aspose.email.EWSClient.getEWSClient(SourceFile:332)
at com.aspose.email.EWSClient.getEWSClient(SourceFile:280)
at PutToExchange.main(PutToExchange.java:58)
Caused by: class com.aspose.email.system.exceptions.WebException: The remote server returned an error: (401) Unauthorized.
com.aspose.email.internal.o.zab.b(Unknown Source)
com.aspose.email.internal.o.zab.a(Unknown Source)
com.aspose.email.internal.o.zbh.a(Unknown Source)
com.aspose.email.internal.o.zbi.invoke(Unknown Source)
com.aspose.email.system.zd.a(Unknown Source)
com.aspose.email.internal.ex.zc.a(Unknown Source)
com.aspose.email.internal.ah.zg.run(SourceFile:66)
java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
java.util.concurrent.FutureTask.run(Unknown Source)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
at com.aspose.email.internal.o.zab.b(Unknown Source)
at com.aspose.email.internal.o.zab.a(Unknown Source)
at com.aspose.email.internal.o.zbh.a(Unknown Source)
at com.aspose.email.internal.o.zbi.invoke(Unknown Source)
at com.aspose.email.system.zd.a(Unknown Source)
at com.aspose.email.internal.ex.zc.a(Unknown Source)
at com.aspose.email.internal.ah.zg.run(SourceFile:66)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

@ctidd1,

Can you please share source file along with sample code so that we may further investigate to help you out.

PutToExchange.zip (1.0 KB)

Hi @Adnan.Ahmad,

Sure; please find attached the source file that contains the code I’m running. Please let me know if you need anything else. Thank you so much.

@ctidd1,

I have observed the exception message shared by you and request you to please share the test account credentials with which you are getting Unauthorized user exception. We will be able to investigate the issue further on our end on provision of requested information.

Hi @mudassir.fayyaz,

Thanks for looking into this; unfortunately, since this is happening in a client environment, I’m not able to divulge exact credentials, but can generally describe the permutations we’ve tried:

Username: something like abc\username or just username
Password: alphanumeric with special characters
Domain: blank, or abc or abc.company.com
Mailbox URI: https://exchange.company.com/ews/exchange.asmx
Mailbox email address: someone@abc.com (to impersonate with)

Please let me know if you need any other information.

Thanks,
Cameron

@ctidd1,

Unfortunately, without provision of requested information we may not be able to investigate the issue. The error 401 generally happen when either user name or password are wrong.

Given the format of how it has been used and tested with various programs , and using ewseditor(Windows) to connect and it does work with MAPI also, the format should be all you need. Giving exact usernames/passwords should never be given. just the formats.

@computermanj,

Unfortunately, without provision of requested information we may not be able to identify the root cause of the issue. Although, I have already shared the reason for 401 error previously with you.

@mudassir.fayyaz , We know it is not a 401 because of username /password as we are able to use mapi to connect with same information. I can not give exact account info against corporate polices and also you would not be able to connect outside of the internal environment. Is there anything in the stacktrace that can help narrow down the issue? @Adnan.Ahmad ( any ideas)

@computermanj,

As my colleague already requested we need information so that we may further investigate to help you out.

I regret to inform that it is not possible.

Hi @mudassir.fayyaz and @Adnan.Ahmad,

Thank you for your assistance so far.

Is there any possibility that you could please provide a debug build with an enhanced tracing capability? Currently, the tracing (the “EWS Client diagnostic log”) only seems to output the generated SOAP XML for requests and responses. If the tracing could be enhanced to provide the HTTP(S) headers/credentials and URI for all requests and responses, as well, it could help us find the deltas between our approach with Aspose and the other APIs.

Particularly, all this trace information should be written before the request is actually sent so that even if a 401 Unauthorized is encountered, we can still see what is going on.

Thanks so much,
Cameron

@ctidd1,

We are looking into this and will share feedback with you soon.

Hi @Adnan.Ahmad and @mudassir.fayyaz,

Thank you for looking into this. We have done further troubleshooting and analysis on our end and found that Aspose’s EWS client is using TLS version 1.0, whereas the other clients we’ve tried are utilizing TLS version 1.2. We believe TLS 1.0 and 1.1 are disabled on the Exchange server, and this is why we are seeing 401 Unauthorized.

I see in Aspose.Email for Java 19.7, TLS 1.2 support was added for the EmailClient ( EMAILJAVA-34562). Could it also please be added to the EWSClient and AutodiscoverService?

Thanks,
Cameron

@ctidd1,

Based on your request, an issue with ID EMAILJAVA-34575 has been created to investigate the possibility of implementing requested support. This thread has been linked with the issue so that you may be notified once the support will be available.

Hi @mudassir.fayyaz and @Adnan.Ahmad,

Thank you for opening the ticket.

I have a question regarding NTLM support: does Aspose support NTLMv2, or does it only use NTLMv1?

Thanks,
Cameron

@ctidd1,

We are investigating this issue and will share feedback with you soon.

What is the status of this issue? We are experiencing the same problem.

@ctidd1,

We have fixed the issue in hotfix Aspose.Email for .NET 19.8.4 hotfix that is shared here.

New API

Use SAAJ API for EWSClient. TLS 1.2 is supported.

EWSClient.useSAAJAPI(boolean);

Code samples

// SAAJ API is used (TLS 1.2 is supported)
EWSClient.useSAAJAPI(true);

// EWS client code sample
IEWSClient client = EWSClient.getEWSClient("https://exchange.domain.com/ews/Exchange.asmx/", "user", "password");
ExchangeMailboxInfo mailboxInfo = client.getMailboxInfo();

// Autodiscover Service code sample
AutodiscoverService service = new AutodiscoverService();
service.setCredentials(new NetworkCredential("user", "password"));
GetUserSettingsResponse response = service.getUserSettings("userSmtpAddress", UserSettingName.ExternalEwsUrl, UserSettingName.UserDisplayName);
1 Like