PDF Generation Template Editor
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
Version 1.3.0 introduces the CEmailConverter API for EML/MIME messages and Outlook MSG files. It supports file paths, File objects, byte arrays and input streams, and can generate an HTML package or a PDF containing the email body and an optional attachment list.
Use the matching version of the JAR and native library. Before running the PDF examples below, initialize the SDK with a valid license as described in Apply the License Key. HTML parsing and HTML-package export do not require a license, but the native library must still be loaded; for an HTML-only application, System.load() can load the matching native library by its absolute path.
CEmailFormat provides EMAIL_FORMAT_AUTO, EMAIL_FORMAT_EML and EMAIL_FORMAT_MSG. AUTO identifies MSG from its Compound File Binary signature and otherwise parses the input as EML; it does not rely on the filename extension. Pass binary MSG data directly rather than converting it to a Java string.
import CPDFGeneration.CEmailConverter;
import CPDFGeneration.CEmailDiagnostic;
import CPDFGeneration.CEmailResult;
try (CEmailResult result = CEmailConverter.ConvertToPdf("message.eml", "message.pdf")) {
if (!result.isSuccess()) {
for (int i = 0; i < result.GetDiagnosticCount(); i++) {
CEmailDiagnostic diagnostic = result.GetDiagnostic(i);
System.err.println(diagnostic.code + ": " + diagnostic.detail);
}
throw new IllegalStateException("Email conversion failed: " + result.GetStatus(),
result.GetLastCallbackException());
}
System.out.println("Converted format: " + result.GetFormat());
}The same example accepts an MSG input by replacing message.eml with a MSG path. The output PDF must not already exist: path output preserves existing files and removes a partial file created by the operation if it fails. Always close the returned CEmailResult, including on failure. Both EMAIL_SUCCESS and EMAIL_SUCCESS_WITH_WARNINGS are successful; isSuccess() accepts either.
The PDF contains the selected email body and, when enabled, an attachment list. It does not embed attachment files or render attachment contents as additional pages. Attachment download links are omitted from the PDF; use HTML-package export or attachment data access when you need the files.
Parse once with ConvertToHtml(), then export an offline HTML package or write a PDF from the retained content. This example also queries the selected primary body's provenance and applies custom page margins.
import CPDFGeneration.CConverterProperties;
import CPDFGeneration.CEmailBodySource;
import CPDFGeneration.CEmailConverter;
import CPDFGeneration.CEmailResult;
import CPDFGeneration.CEmailStatus;
CConverterProperties properties = new CConverterProperties();
try {
properties.setPageMargins(48, 40, 48, 40);
try (CEmailResult result = CEmailConverter.ConvertToHtml("message.msg")) {
if (!result.isSuccess()) {
throw new IllegalStateException("Email parsing failed: " + result.GetStatus());
}
CEmailBodySource body = result.GetSelectedBodySource();
if (body.status.isSuccess()) {
System.out.println(body.mediaType + " / " + body.origin);
}
CEmailStatus exported = result.ExportHtml("mail-package");
if (!exported.isSuccess()) {
throw new IllegalStateException("HTML export failed: " + exported);
}
CEmailStatus written = result.WritePdf("message.pdf", properties);
if (!written.isSuccess()) {
throw new IllegalStateException("PDF write failed: " + written,
result.GetLastCallbackException());
}
}
} finally {
properties.release();
}Use a new output directory for the HTML package. ExportHtml() writes index.html, body resources and enabled attachments without overwriting existing output files. Failure removes files created by that export, while preserving caller data. GetHtml() returns only the UTF-8 HTML string, which may contain relative resource paths; use ExportHtml() to obtain a complete offline package.
Check the status returned by each export/write operation. GetStatus() describes the latest operation and can replace the original conversion status. Each new native output operation recalculates status and diagnostics from the initial HTML conversion state. Previously obtained Java snapshots remain valid.
PDF, license or output failures can retain successfully generated HTML, resources and attachments, allowing a later export or PDF retry. An input parsing failure does not guarantee that HTML exists. GetSelectedBodySource().status describes the provenance query only and does not change the result's operation status. It identifies the selected primary body, not every displayed multipart segment; its source IDs are opaque within that result. The returned CEmailBodySource contains bodyId, sourceId, mediaType and origin; the media type is text/plain or text/html, and the origin is original, recovered, fallback or generated.
When PDF properties are null, email conversion uses A4 with top/bottom margins of 32 CSS px and left/right margins of 40 CSS px. A supplied properties object preserves its configured page size, margins (including zero), font provider and header/footer settings. The operation does not modify the caller's properties or base URI. HTML-preview padding is not added to PDF page margins. See Page Margins and Headers and Footers for print configuration.
Pass null options for defaults, or create a CEmailOptions object. Options are copied when conversion begins; do not modify them concurrently while the copy is being made.
| Field | Default | Description |
|---|---|---|
flags | 7 | Include headers, show the attachment list and enable attachment export. |
maxInputBytes | 100 MiB | Maximum input size in bytes. |
maxDecodedBytes | 256 MiB | Decoded-content byte budget. |
maxHtmlBytes | 64 MiB | Generated HTML byte budget. |
cancellationCallback | null | Optional CEmailCancelCallback returning true to request cancellation. |
Combine CEmailFlags values with bitwise OR:
| Flag | Effect |
|---|---|
EMAIL_INCLUDE_HEADERS | Display the email header summary. Enabled by default. |
EMAIL_INCLUDE_ATTACHMENT_LIST | Display an attachment list. Enabled by default. |
EMAIL_EXPORT_ATTACHMENTS | Export available attachment files with the HTML package. Enabled by default. |
EMAIL_INLINE_RESOURCES | Inline body resources in the generated HTML. |
EMAIL_RECOVER_EML | Enable bounded recovery of malformed EML; inspect diagnostics for fallback or skipped content. |
EMAIL_INCLUDE_BCC | Display Bcc, which is hidden by default. |
import CPDFGeneration.CEmailConverter;
import CPDFGeneration.CEmailFlags;
import CPDFGeneration.CEmailFormat;
import CPDFGeneration.CEmailOptions;
import CPDFGeneration.CEmailResult;
import java.util.concurrent.atomic.AtomicBoolean;
CEmailOptions options = new CEmailOptions();
options.flags |= CEmailFlags.EMAIL_INLINE_RESOURCES;
options.maxInputBytes = 20L * 1024 * 1024;
AtomicBoolean cancelled = new AtomicBoolean(false);
options.cancellationCallback = cancelled::get;
try (CEmailResult result = CEmailConverter.ConvertToHtml(
"message.eml", CEmailFormat.EMAIL_FORMAT_AUTO, options)) {
if (!result.isSuccess()) {
throw new IllegalStateException("Email parsing failed: " + result.GetStatus(),
result.GetLastCallbackException());
}
System.out.println("HTML characters: " + result.GetHtml().length());
}Byte budgets are nonnegative; zero is a real zero limit, not unlimited. Negative budgets throw IllegalArgumentException when passed to a converter. Unknown flag bits produce EMAIL_ERROR_INVALID_PARAMETER. Internal parser/structural limits also apply, even when the configured byte budgets have not been exceeded.
Cancellation is cooperative, checked between phases and during callback I/O. It does not interrupt a parser or layout operation already in progress and does not provide a hard timeout. The callback runs synchronously on the calling Java thread and must return promptly. Another thread can request cancellation by setting the example's cancelled flag to true.
The result retains the callback for subsequent ExportHtml() and WritePdf() calls until the result is closed. Changing the original options object does not replace that retained callback. A callback exception is treated as cancellation and is available through GetLastCallbackException(). Do not reenter SDK operations, close the active result, release its properties or synchronously wait for another PDF task from the callback.
For an input stream, supply the number of email bytes to read from its current position. Do not use InputStream.available() as the message length. For a file, use Files.size() and ensure that the input does not change while it is read.
import CPDFGeneration.CEmailConverter;
import CPDFGeneration.CEmailResult;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
Path input = Paths.get("message.eml");
Path output = Paths.get("message-stream.pdf");
long length = Files.size(input);
try (InputStream source = Files.newInputStream(input);
OutputStream destination = Files.newOutputStream(output,
StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
CEmailResult result = CEmailConverter.ConvertToPdf(source, length, destination)) {
if (!result.isSuccess()) {
throw new IllegalStateException("Stream conversion failed: " + result.GetStatus(),
result.GetLastCallbackException());
}
}Short reads are retried. Premature EOF produces EMAIL_ERROR_READ with the original EOFException retained by the result. SDK operations do not close or flush caller streams; the try-with-resources block above closes them on the caller's behalf. On failure or cancellation, discard partial output, including a file created by the caller for the output stream.
To work entirely in memory:
import CPDFGeneration.CEmailConverter;
import CPDFGeneration.CEmailResult;
import java.io.ByteArrayOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
byte[] email = Files.readAllBytes(Paths.get("message.msg"));
ByteArrayOutputStream output = new ByteArrayOutputStream();
try (CEmailResult result = CEmailConverter.ConvertToPdf(email, output)) {
if (!result.isSuccess()) {
throw new IllegalStateException("Memory conversion failed: " + result.GetStatus(),
result.GetLastCallbackException());
}
byte[] pdf = output.toByteArray();
System.out.println("PDF bytes: " + pdf.length);
}Memory input and output consume Java heap space. For large messages, prefer file or stream input and avoid copying attachment payloads unless they are needed.
The following overload groups provide both convenience methods and full methods with explicit format/options. PDF methods also accept CConverterProperties:
| Operation | Input | Output | Additional full-method parameters |
|---|---|---|---|
ConvertToHtml | String path or File | CEmailResult | CEmailFormat, CEmailOptions |
ConvertToHtml | byte[] | CEmailResult | CEmailFormat, CEmailOptions |
ConvertToHtml | InputStream, long length | CEmailResult | CEmailFormat, CEmailOptions |
ConvertToPdf | String path | String PDF path | CEmailFormat, CEmailOptions, CConverterProperties |
ConvertToPdf | File | File PDF output | CEmailFormat, CEmailOptions, CConverterProperties |
ConvertToPdf | byte[] | OutputStream | CEmailFormat, CEmailOptions, CConverterProperties |
ConvertToPdf | InputStream, long length | OutputStream | CEmailFormat, CEmailOptions, CConverterProperties |
Convenience methods use AUTO format and default options. Convenience PDF methods also use default email page properties. All converter methods return an owned CEmailResult that must be closed.
| Result method | Purpose |
|---|---|
GetStatus() / isSuccess() | Status of the latest conversion or native output operation. |
GetFormat() | Input format reported by the parser. |
GetPdfError() | Underlying CHtmlConverter.CErrorCode for PDF/license failures. |
GetHtml() | HTML string, or an empty string if HTML was not generated. |
GetResourceCount() / GetResource(index) | Body-resource count and metadata/payload snapshots. |
GetAttachmentCount() / GetAttachment(index) | Attachment count and metadata/payload snapshots. |
GetDiagnosticCount() / GetDiagnostic(index) | Error/warning diagnostics, including code, source ID, detail and fallback action. |
GetSelectedBodySource() | Selected primary body's query status, IDs, media type and origin. |
GetLastCallbackException() | Captured Java stream/cancellation exception, or null. |
ExportHtml(String / File) | Export an offline HTML package. |
WritePdf(String / File / OutputStream [, properties]) | Generate or retry PDF from retained HTML. |
GetResource() returns CEmailResource; GetAttachment() returns CEmailAttachment; GetDiagnostic() returns CEmailDiagnostic. Resources and attachments provide metadata such as media type, relative path and size. Attachments also expose id, originalName, displayName, hasData, hidden, referencedByBody and nestedMessage. A metadata-only attachment has hasData == false and getData() == null, unlike a valid zero-byte attachment.
Collection indices are zero-based; an invalid index throws IndexOutOfBoundsException. Metadata and payload snapshots are Java-owned copies that remain valid after the result is closed. Each getData() call returns another independent byte-array copy, so large payloads require additional heap space.
CEmailStatus | Value | Meaning |
|---|---|---|
EMAIL_SUCCESS | 0 | Success without warnings. |
EMAIL_SUCCESS_WITH_WARNINGS | 1 | Success with warnings or fallback content. |
EMAIL_ERROR_INVALID_PARAMETER | -1 | Invalid argument, format or option. |
EMAIL_ERROR_READ | -2 | Input read failure. |
EMAIL_ERROR_PARSE | -3 | Email parsing failure. |
EMAIL_ERROR_HTML | -4 | HTML generation failure. |
EMAIL_ERROR_WRITE | -5 | Output write failure. |
EMAIL_ERROR_PDF | -6 | PDF rendering failure. |
EMAIL_ERROR_LICENSE | -7 | PDF license check failed. |
EMAIL_ERROR_LIMIT | -8 | A byte budget or internal structural limit was exceeded. |
EMAIL_ERROR_CANCELLED | -9 | Cancellation requested. |
EMAIL_ERROR_OUT_OF_MEMORY | -10 | Native allocation failure. |
EMAIL_ERROR_INTERNAL | -11 | Internal error or unknown native status. |
Typical conversion failures are reported as statuses. Java-side argument validation, such as negative budgets or a path containing NUL, can throw IllegalArgumentException; Java/JNI allocation failures can throw OutOfMemoryError. Stream and cancellation exceptions are retained by GetLastCallbackException(), and that value is replaced by the next native output operation. A Java validation failure leaves the previous operation state intact.
CEmailResult. close() and release() are idempotent; native queries/output after closing throw IllegalStateException. isClosed() remains available.release(); released properties cannot be reused with the email API.Run the packaged example from the samples directory:
cd EmailConvertTest
bash RunTest.shThe example reads the fixed EML/MSG inputs directly from samples/TestFiles/email, and writes an HTML package, a PDF with headers/footers, a nested-message PDF and a stream-generated PDF to a new samples/out/email-example-* directory. On Linux, its script locates and preloads libjsig.so from the Java installation on PATH to preserve JVM signal-handler behavior. Cached online-license background refresh remains enabled by default.
PrintOptionsTest demonstrates page margins and header/footer configuration. FamilyHeaderFooterTest demonstrates cover-page handling and page numbering with TestFiles/family_html/family_all_pages.html.