Aspose.Email Issue "2 CR Found" and recommended approach

Hi,

I randomly get the issue “2 CR Found” but I am unable to find description anywhere what causes this exception.
Could you please share what are the possible reasons for this exception?

We are using the Aspose Email to read all emails, move that email in other folder.
Connectivity approach is using clientId, secret, tenant, mailboxID, password .
PostRequest simply invokes oauth2 for authentication

String url = "https://login.microsoftonline.com/"+ tenantId + "/oauth2/token";

        HttpClient httpclient = HttpClients.createDefault();
        HttpPost httppost = new HttpPost(url);

        // Request parameters and other properties.
        httppost.setEntity(requestData);

        //Execute and get the response.
        HttpResponse httpResponse = null;
            httpResponse = httpclient.execute(httppost);
            HttpEntity entity = httpResponse.getEntity();

            if (entity != null) {
                try (InputStream instream = entity.getContent()) {
                    response = IOUtils.toString(instream);
                }
            }

Then initialize EWSClient in following manner:-

    bearerToken = new Gson().fromJson(response, BearerToken.class);
           OAuthNetworkCredential oAuthCredential = new OAuthNetworkCredential(bearerToken.access_token);
           iewsClient = EWSClient.getEWSClient(mailboxuri, oAuthCredential);

For every operation (readMail , moveMail) , new ewsClient is instantiated and disposed by setting it to null.
It is being used by multiple applications.
Multiple applications are creating ewsClient, performing operation on mailbox and then disposing.

What’s the recommended approach to handle such scenario?
I found following article, after which I changed static singleton client which was being shared by all applications into current non-static architecture.

Thanks

@curiousreedhub

I suggest you to please try using latest version of Aspose.Email 20.9.1 on your end. In case there is still an issue then please provide a working sample project and test account credentials verifying the issue on your end so that we may try to reproduce the same on our end.

Hi. I am using the latest version. But this is an intermittent issue. The approach I have explained above is that the correct one or should I make client singleton?
Please look at the latter part of my question.

Thanks

@curiousreedhub

This is something concerning too as on your end too its intermittent. In order to investigate and resolve the issue we need a working sample project and environment details that we may test on our end to help you further.

Sure I am working on sharing that. Any inputs on recommended approach?

@curiousreedhub

As requested earlier, we will need some working sample project that is reproducing issue on your end and we will try to reproduce the same on our end based oon that.

asposedemo.zip (107.4 KB)

Please find attached sample app. In our project, multiple application are using aspose client . We have tried to recreate this scenario using Scheduler.
Please do note that this issue only comes once in weeks or so.
We are currently using “ModernAuthentication” and not basic authentication using IMAP.
Please test using ModernAuthentication only.

Project Information:

Sample project for reading the unread mail and move to destFolder.
In AsposeMailheper class change the mailId and Password.
In Scheduler class change the FromFolder and ToFolder.

We do have aspose.email 1 year support as well.

Exception stacktrace:

com.aspose.email.system.exceptions.WebException: 2 CR found
com.aspose.email.internal.o.ze.b(Unknown Source)
com.aspose.email.internal.o.ze.c(Unknown Source)
com.aspose.email.internal.o.ze.a(Unknown Source)
com.aspose.email.internal.o.ze.b(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.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
java.base/java.lang.Thread.run(Thread.java:834)

 java.lang.RuntimeException: class com.aspose.email.system.exceptions.WebException: 2 CR found
com.aspose.email.internal.o.ze.b(Unknown Source)
com.aspose.email.internal.o.ze.c(Unknown Source)
com.aspose.email.internal.o.ze.a(Unknown Source)
com.aspose.email.internal.o.ze.b(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.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
java.base/java.lang.Thread.run(Thread.java:834)

Kindly help in identifying and resolving the issue. It’s at very critical stage for us.

Thank you

@curiousreedhub

I have created an issue with ID EMAILJAVA-34759 in our issue tracking system to further investigate this intermittent issue. We will share the feedback with you as soon as the issue will be addressed.

Hi.

Thanks. Can you have please share any timeline/ETA on it?
Also, if you could suggest probable root causes for “2 CR Found” exception we could look at our end as well.

We have multiple clients connecting with mailbox in parallel.

Please provide your input.

Thanks

@curiousreedhub

We can use single EwsClient instance for one user credentials. We have tested scheduler with our test account.
We suggest you to enable new EwsClient core implementation using option:

EWSClient.useSAAJAPI(true);

Should we use single client instance for one user credential for IMAP as well as SMTP?
In that case can we make it static per credential as in our functionality multiple independent applications have to connect with the same email and do following operations:

  1. Read email folder and list emails
  2. Do processing and move email
  3. Send Email

Also, could you please elaborate on SAAJ? I could only find below brief in documentations:
Sets value indicating whether SAAJ is used.

Thanks for your support

@curiousreedhub

We will get back to you with feedback on this as soon as it will be shared.

Hi any feedback on multiple applications connecting with same mailbox scenario and how SAAJ will help in supporting multiple connectivity?
How could this be achieved?

Thank you

@curiousreedhub

By default, EWSClient uses our own SOAP client implementation(including HTTP client impl).
With SAAJAPI mode we are using Java EE SOAP Client.
(SOAP Clients and Services Using SAAJ and JAXM)
Use SAAJ API for EWSClient:

EWSClient.useSAAJAPI(true);

We can use Basic or OAUTH2 credentials for the connection.
In the next code snippet Basic authentication header will be assigned:

EWSClient.useSAAJAPI(true);
IEWSClient client = EWSClient.getEWSClient("https://outlook.office365.com/ews/exchange.asmx", "testuser", "pw", "domain");
client.listMessages();

In the next code snippet OAUTH2 authentication header will be assigned:

EWSClient.useSAAJAPI(true);
// token provider
/*ITokenProvider provider = new ITokenProvider() {

    @Override
    public void dispose() {
    }

    @Override
    public OAuthToken getAccessToken(boolean ignoreExistingToken) {
        return null;
    }

    @Override
    public OAuthToken getAccessToken() {
        return null;
    }
};

NetworkCredential credentials = new OAuthNetworkCredential(provider);*/

// accessToken
NetworkCredential credentials = new OAuthNetworkCredential("accessToken");

IEWSClient client = EWSClient.getEWSClient("https://outlook.office365.com/ews/exchange.asmx", credentials);
client.listMessages();

Note, we do not control NTLM authentication process in our API when SAAJ mode is enabled.
If we need to use NTLM we need to set Java Authenticator.

The NTLM authentication code snippet for Java 8:

static Authenticator getAuthenticator() {

    // This block is written for suppressing a bug in sun implementation.
    // In Sun Impl client doesn't authenticate user for each connection,
    // uses cached credentials instead.
    sun.net.www.protocol.http.AuthCacheValue.setAuthCache(new sun.net.www.protocol.http.AuthCache() {
        public void remove(String pkey, sun.net.www.protocol.http.AuthCacheValue entry) {
        }
        public void put(String pkey, sun.net.www.protocol.http.AuthCacheValue value) {
        }
        public sun.net.www.protocol.http.AuthCacheValue get(String pkey, String skey) {
            return null;
        }
    });

    return new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return getEmbeddedCredentials(getRequestingURL());
        }

        PasswordAuthentication getEmbeddedCredentials(URL url) {
            if (url == null) {
                return null;
            }
            String userInfo = url.getUserInfo();
            int colon = userInfo == null ? -1 : userInfo.indexOf(":");
            if (colon == -1) {
                return null;
            } else {
                String userName = userInfo.substring(0, colon);
                String pass;
                try {
                    pass = URLDecoder.decode(userInfo.substring(colon + 1), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    pass = "";
                }
                System.out.println("Authenticate " + userInfo);
                return new PasswordAuthentication("\\" + userName, pass.toCharArray());
            }
        }
    };
}

static URL getURL(String url, String user, String pw, String domain) throws Exception {
    String host = new URL(url).getHost();
    URL endpoint = new URL(url.replace(host, user + ":" + URLEncoder.encode(pw, "UTF-8") + "@" + host));

    return endpoint;
}

EWSClient.useSAAJAPI(true);
Authenticator.setDefault(getAuthenticator());

System.setProperty("http.auth.preference", "NTLM");
IEWSClient client1 = EWSClient.getEWSClient(getURL("https://domain.com/ews/Exchange.asmx", "user1", "pw", "domain"));
IEWSClient client2 = EWSClient.getEWSClient(getURL("https://domain.com/ews/Exchange.asmx", "user2", "pw", "domain"));

Since Java 9, we can set Authenticator for connection:

static Map<String, Authenticator> authInfo = new HashMap<String, Authenticator>();
static URL getURL(String url, final String user, final String pw, final String domain) throws MalformedURLException {
    URL endpoint = new URL(new URL(url), "", new URLStreamHandler() {
        protected URLConnection openConnection(URL url) throws IOException {
            URL target = new URL(url.toString());
            HttpURLConnection connection = (HttpURLConnection) target.openConnection();
            // Cache for User@Url
            Authenticator auth = authInfo.get(user + "@" + url);
            if (auth == null) {
                auth = new Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        System.out.println("Authenticate " + user);
                        return new PasswordAuthentication(domain + "\\" + user, pw.toCharArray());
                    }
                };
                authInfo.put(user + "@" + url, auth);
            }
            connection.setAuthenticator(auth);

            return connection;
        }
    });

    return endpoint;
}

EWSClient.useSAAJAPI(true);
System.setProperty("http.auth.preference", "NTLM");
IEWSClient client1 = EWSClient.getEWSClient(getURL("https://domain.com/ews/Exchange.asmx", "user1", "pw", "domain"));
IEWSClient client2 = EWSClient.getEWSClient(getURL("https://domain.com/ews/Exchange.asmx", "user2", "pw", "domain"));

Note:
The JAXB APIs are considered to be Java EE APIs, and therefore are no longer contained on the default class path in Java SE 9.
Maven JAXB dependencies:

<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> </dependency> <dependency> <groupId>com.sun.xml.messaging.saaj</groupId> <artifactId>saaj-impl</artifactId> </dependency>

Hi,

Email polling is working fine now. But following 2 issues are occurring:

  1. Send email functionality -> While sending emails, client hangs forever after 1 day. Emails sending job is triggering email in every 30 seconds.

  2. Read email functionality -> Getting below exception once in few hours while reading email from folder
    Error occurred in reading mail from folder: [INBOX <emailid> with](mailto:INBOX <email Id> with) exception message as: java.lang.RuntimeException: SOAP Fault a:ErrorNoRespondingCASInDestinationSite Exchange Web Services are not currently available for this request because none of the Client Access Servers in the destination site could process the request.

I have appended the information in our issue tracking system and we will get back to you with feedback as soon as it will be shared.

@curiousreedhub

We need to check if a CookieManager is set

if (CookieHandler.getDefault() == null)
    CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

We can set “X-AnchorMailbox” to avoid SOAP Exception with “Client Access Servers”

client = EWSClient.getEWSClient(mailboxuri, credentials);
client.addHeader("X-AnchorMailbox", userPrimaryMailID);

Hi, We had implemented the “X-AnchorMailbox” change but the above exception still keeps coming intermittently.
Exception- java.lang.RuntimeException: SOAP Fault a:ErrorNoRespondingCASInDestinationSite Exchange Web Services are not currently available for this request because none of the Client Access Servers in the destination site could process the request.

The configuration is Mailboxes are being accessed using service account using OAUTH post call to fetch Bearer token

@curiousreedhub

I have included the provided feedback in concerned ticket and we will share feedback with you as soon as it will be addressed.

Also to add to it, we faced major blocker issue in production on 18th January in which all the send email, read email functionalities threw this exception continuously for 12 hours and no operation was successful.