Hello, @woutedaeu !
Thanks for the code snippet — that was enough to reproduce your exact call path on Java. I re-ran the whole measurement against the Java build rather than assuming it matches .NET, and here is what came out.
Short answer: your snippet, as written, does not issue any outbound request. I could not make getText() on MSG/EML touch the network in any message shape I was able to construct. So on the evidence, the traffic you are seeing is coming from somewhere else — and I have a concrete suspect below.
What I measured
GroupDocs.Parser for Java 26.5 (Aspose.Email 24.9, Aspose.Words 23.6). Every message body pointed its <img src>, <link href> and INCLUDEPICTURE at a local HTTP server, and I counted the requests that actually arrived. Loading was done exactly as in your code — from a stream, with new LoadOptions(FileFormat.Email).
| Document |
getText() |
getFormattedText() |
getStructure() |
getImages() |
| MSG, plain-text + HTML body |
no requests |
CSS + image |
CSS + image |
no requests |
| MSG, HTML body only |
no requests |
CSS + image |
CSS + image |
no requests |
| MSG with no plain-body property at all |
no requests |
— |
— |
— |
| MSG, RTF body with INCLUDEPICTURE |
no requests |
— |
— |
— |
| EML, hand-written, text/html only |
no requests |
CSS + image |
CSS + image |
no requests |
| S/MIME-signed MSG (cert carrying CRL + OCSP + caIssuers URLs) |
no requests |
— |
— |
— |
| plain HTML file |
CSS + image |
CSS + image |
CSS + image |
CSS + image |
So the per-method table from my earlier post holds for Java as well: on email, GetFormattedText/getFormattedText and GetStructure/getStructure fetch external resources; getText does not.
Why getText() stays offline on email — and the one caveat
Internally the email parser does this:
if (msg.getBody() != null) return msg.getBody(); // plain-text body, no network
switch (msg.getBodyType()) {
case Html: return WordProcessingUtils.getText(...); // Aspose.Words
case Rtf: return WordProcessingUtils.getText(...); // Aspose.Words
}
Those two fallback branches are network-active — I called them directly and Aspose.Words downloaded the stylesheet, the image, and the RTF INCLUDEPICTURE target even in plain-text mode. But I could not reach them from a real file: Aspose.Email synthesises a plain-text body from the HTML or RTF part itself, offline, so getBody() came back non-null even for a .msg that physically has no plain-body stream (I checked the compound-file streams byte-wise). In practice those branches are dead code. I am flagging them because they are the only way getText() on email could ever go out, not because I saw them fire.
One honest caveat: these runs were unlicensed (evaluation mode), which watermarks the body. That does not affect the request counts — they were measured on the wire — but I cannot fully rule out a rare licensed case where getBody() returns null.
Things I ruled out
- Signature handling. The Java parser loads messages with
removeSignature(true), so I tested a signed .msg whose certificate carried CRL, OCSP and caIssuers URLs pointing at my server. Nothing was fetched — no revocation or chain-building traffic.
- Format misrouting. With
new LoadOptions(FileFormat.Email) only the email detector runs; anything else fails with UnsupportedDocumentFormatException rather than silently falling through to the HTML parser. PST/OST would be accepted, but they do not support the text feature, so your features.isText() guard skips them.
- Anything else in the library. The only outbound HTTP in Parser’s own Java code is the metered-licensing client (HTTPS to the GroupDocs API, usage counts only). Everything else is an explicit
Parser(URL) / Parser(EmailConnection) / Parser(Connection) you would have written yourself.
The likely culprit: HTML content elsewhere in your pipeline
Note the last row of the table. On Java, getText() on an HTML document downloads external stylesheets and images — same as .NET. This is the one place where the method you already use is network-active.
That matters if anywhere else in your application:
- attachments pulled out of messages (
getContainer()) are fed back into Parser, and some of them are .html / .mht;
- files arrive with an unknown or guessed type and are parsed without a fixed
FileFormat, so detection lands on HTML or MHTML;
- HTML bodies are saved out and re-parsed as documents.
Any of those would produce exactly what you describe — requests to a different domain per message, from a worker thread, with nothing suspicious in your own stack trace.
Good news on the handler
You noticed the ResourceHandler was never invoked. On the email paths that is correct and it is a gap on our side — the handler is not passed through to the layout engine there. But on the HTML and MHTML paths it does work in Java, via ParserSettings(ExternalResourceHandler). So if the source turns out to be HTML content, you have a real interception point, not just an egress block:
ParserSettings settings = new ParserSettings(new ExternalResourceHandler() {
@Override public void onLoading(ExternalResourceLoadingArgs args) {
// args.getUri() — log it, then hand back empty data to suppress the fetch
args.setData(new byte[0]);
}
});
try (Parser parser = new Parser(fileToParse, loadOptions, settings)) { ... }
Even if you end up blocking egress anyway, running this once with logging only is the fastest way to find out which call site is responsible — every URL the library is about to request will pass through onLoading on those paths.
What would settle it
- Capture the outbound URLs and check whether they appear verbatim in the messages you process.
- Grep for every other place your code constructs a
Parser — especially attachment handling and any path without an explicit FileFormat.
- Drop in the handler above on those paths and log
args.getUri().
If the URLs do come from the message bodies but never appear in onLoading, send me that call site and I will dig further. And thanks again — this thread has already produced one fix worth making on our side.
Kind regards!