Skip to main content

paperless-esig

badge

paperless-esig is a third-party parser for Paperless-ngx. It adds support for EU electronically signed documents.

Supported formats

Format Extensions
ASiC-E containers .edoc, .asice, .bdoc, .adoc
CAdES signatures .p7m
PAdES-signed PDFs .pdf

Paperless-ngx does not consume these files by default. The parser is required for them.

Why Paperless-ngx cannot handle these files

ASiC-E containers are ZIP archives. libmagic reports them as application/zip, and Paperless-ngx rejects the MIME type. CAdES files are reported as application/octet-stream and are also rejected. PAdES-signed PDFs are consumed, but the built-in parser does not expose their signature metadata.

Signature formats in detail

XAdES

Used inside ETSI ASiC-E containers (.edoc, .asice, .bdoc, .adoc). The parser extracts the signing time, signer certificate, certificate chain, RFC 3161 timestamp, and OCSP values. It verifies the document digest, the SignedProperties digest, and the signature value offline.

CAdES

CMS SignedData (ETSI EN 319 122) in .p7m files. The embedded PDF becomes the rendition. The CMS signing time, signer, and verification results are exposed as metadata. Detached .p7s signatures are detected but rejected during parsing with a clear error, because they carry no document.

PAdES

PDFs signed with the ETSI.CAdES.detached or adbe.pkcs7.detached subfilter. The signed PDF is the rendition. The document date prefers the CMS signing time and falls back to the signature's /M field. The covered byte range, signer, and verification results are exposed as metadata.

Encoding notes

Both DER and BER (indefinite-length) CMS encodings are accepted. Some signers, such as the adbe.pkcs7.detached flavour, emit BER. Verification is offline only. It proves that the document digest and the signature value are consistent with the signer certificate. It does not validate trust chains, revocation status, or timestamps.

What the parser does

  • Stores the original file unchanged. This is required for legal compliance.
  • Extracts the signed PDF as the display and archive rendition. Browsers cannot render ZIP containers. A PAdES PDF is already a rendition and keeps its signature.
  • Extracts the text of the PDF for search.
  • Sets the document date from the signature signing time, with fallbacks to the PAdES /M field and the PDF creation date.
  • Displays signature metadata in the metadata tab: signer name, organisation, country, signing time, certificate chain and issuer, RFC 3161 timestamp authority, and OCSP presence.
  • Verifies the document digest and the signature value offline.
  • Handles nested containers (an EDOC inside an EDOC, as produced by the Latvian e-archive) and multi-document containers (multiple PDFs and office documents merged into a single rendition).
  • Assigns the signer as the document's correspondent. This happens after consumption, only when no correspondent was determined by content matching or workflow rules. The signer (organisation preferred over common name) is looked up case-insensitively and created if it does not exist, and the document is re-indexed so the correspondent is searchable immediately. This is enabled by default. Disable it with PAPERLESS_ESIG_ASSIGN_SIGNER_AS_CORRESPONDENT=false. Known limitations: the assignment is not recorded in the audit log, and the UI may show the new correspondent as "Private" until the page is reloaded.

Install

The parser runs inside Paperless-ngx. Use one of two methods.

Method 1: Docker

  1. Clone this repository and build the image:

    docker build -t paperless-ngx-esig .
    
  2. In docker-compose.yml, replace the webserver image with your build:

    services:
      webserver:
        image: paperless-ngx-esig
        # ...everything else stays the same
    
  3. Restart the stack:

    docker compose up -d
    

Method 2: Bare metal

Install the package into the same virtual environment that runs Paperless-ngx:

uv pip install paperless-esig

Verify the install

  1. Start Paperless-ngx and check the logs. Look for a line like this:

    [paperless.parsers.registry]   [third-party] Paperless-ngx ESig Parser v0.3.0 — https://github.com/Exerra/paperless-esig
    

    If the logs say No third-party parsers discovered. instead, see Troubleshooting.

  2. Upload an .edoc, .asice, .bdoc, .adoc, or .p7m file, or a PAdES-signed PDF. The document is consumed, displays the inner PDF, and shows signature metadata in the metadata tab.

Limitations

  • Documents are stored with the MIME type that libmagic reports. ASiC-E containers are stored as application/zip and CAdES files as application/octet-stream. The original file extension (.edoc, .asice, .p7m, and so on) is preserved in the stored filename.
  • Plain ZIP files pass API and mail upload validation but are rejected during consumption with an "Unsupported mime type" error. The parser cannot inspect a file at validation time. ZIP files placed in the consume directory are attempted instead of silently skipped. The same applies to application/octet-stream files: CAdES signatures are the only octet-stream files that are consumed.
  • Detached .p7s signatures are detected but rejected during parsing. They carry no document, so there is nothing to display or search.
  • Office documents (DOCX, ODT, and similar) inside a container are converted to PDF by Gotenberg, and their text is extracted by Tika, when those services are configured with PAPERLESS_TIKA_ENDPOINT. Without them, the DOCX text is still extracted locally and the affected pages are omitted from the rendition.

Requirements

  • Paperless-ngx 2.x. The parser uses the paperless_ngx.parsers entrypoint registry.
  • The container must contain a PDF. Containers without a PDF cannot be ingested.

Troubleshooting

  • No third-party parsers discovered. in the logs. The package is not installed in the environment that Paperless-ngx runs in. For Docker, check that your compose file points at the image you built (docker images).
  • uv: command not found. Install uv first. Alternatively, python3 -m pip install . works.
  • Plain ZIP files are rejected with "Unsupported mime type". This is expected. See Limitations.

License

GPL-3.0-or-later. Derived from the Paperless-ngx project, which is GPL-3.0.

For developers

Building the Docker image

The build defaults to the latest release from PyPI:

docker build -t paperless-ngx-esig .

Build a specific release:

docker build --build-arg ESIG_VERSION=0.3.0 -t paperless-ngx-esig .

Build from your local checkout, for development or unreleased changes:

docker build --build-arg ESIG_SOURCE=local -t paperless-ngx-esig .

Build against a specific Paperless-ngx base version:

docker build --build-arg PAPERLESS_VERSION=2.14.7 -t paperless-ngx-esig .

make docker and make docker-local are shortcuts for the first and third commands.

Development

Prerequisites

  • uv
  • Python 3.11 or newer (uv installs it for you)
  • Docker, only for the Docker image targets
  • A checkout of Paperless-ngx, for the test suite

Set up

git clone https://github.com/Exerra/paperless-esig.git
cd paperless-esig
uv sync
git clone --depth 1 https://github.com/paperless-ngx/paperless-ngx.git ../paperless-ngx

uv sync creates a virtual environment and installs the package plus dev dependencies (django, pytest, ruff, and others). The tests import Paperless-ngx's own code, so the checkout must be on PYTHONPATH.

Run the tests

PYTHONPATH=../paperless-ngx/src uv run pytest

make test does the same. It uses PAPERLESS_NGX_SRC, which defaults to ../paperless-ngx/src relative to this repo. Override it with make test PAPERLESS_NGX_SRC=/path/to/paperless-ngx/src.

The tests build synthetic signed containers. They do not contain real personal data. They need only the Paperless-ngx source importable. No database or running instance is required.

If the tests fail with ModuleNotFoundError: No module named 'documents', the Paperless-ngx checkout is missing or not on PYTHONPATH.

Lint

uv run ruff check src tests

Build a wheel

uv build

Artifacts land in dist/ as paperless_esig-<version>-py3-none-any.whl and paperless_esig-<version>.tar.gz.

Makefile targets

Command What it does
make venv Create venv and install dev dependencies (uv sync)
make test Run the test suite
make lint Run ruff
make build Build wheel and sdist into dist/
make docker Build the image from the latest PyPI release
make docker-local Build the image from your local checkout
make clean Remove build artifacts and caches

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

paperless_esig-0.3.0.tar.gz (58.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

paperless_esig-0.3.0-py3-none-any.whl (36.2 kB view details)

Uploaded Python 3

File details

Details for the file paperless_esig-0.3.0.tar.gz.

File metadata

  • Download URL: paperless_esig-0.3.0.tar.gz
  • Upload date:
  • Size: 58.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for paperless_esig-0.3.0.tar.gz
Algorithm Hash digest
SHA256 bbb02462dde1bf20099f429aa0efc26f05e541bac1d6c8bc244fa711e8ee9ec1
MD5 159cf4a6b1a0140493ddd9c9120908da
BLAKE2b-256 f903520528ef53fef2f1ada42558deb94efecc23b2ed5433dfdc328bd237e370

See more details on using hashes here.

File details

Details for the file paperless_esig-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: paperless_esig-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 36.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for paperless_esig-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 17d0f99838c2ad57717850992ce4f52bc477c9a92501cd2274ea1fe8a76776b3
MD5 12bfa0de5bf8eb129d2e8cfafbab03b5
BLAKE2b-256 aa5becd0ce85d118f5e8c2f392863359ab94c6537c7ee4501291715c9a6af5fa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page