Skip to content

Email DLP Setup

Arbitex Email DLP inspects outbound and inbound email using the same 5-tier DLP pipeline that protects your AI gateway. Email flows through a Haraka MTA relay that forwards each message to the platform scan endpoint. Findings trigger quarantine, rejection, or tagging based on per-org policy — with no changes required to your existing mail infrastructure beyond an MX or relay hop.

For the underlying detection pipeline, see DLP Pipeline Architecture.


┌─────────────────────────────────────────┐
│ Arbitex Platform │
Outbound email │ │
──────────────► ┌────┴──────┐ POST /v1/internal/dlp/scan │
(SMTP :25 / │ Haraka │ ──────────────────────────────► │
STARTTLS :587) │ MTA │ channel="email" │
│ Relay │ │
└────┬──────┘ ┌──────────────────────────┐ │
│ │ 5-Tier DLP Pipeline │ │
Inbound email │ │ │ │
──────────────► │ │ Tier 0: TF-IDF filter │ │
│ │ Tier 1: Regex+checksum │ │
│ │ Tier 2: GLiNER NER │ │
│ │ Tier 3: DeBERTa NLI │ │
│ │ Tier 4: CredInt │ │
│ └────────────┬─────────────┘ │
│ │ │
│ ┌────────────▼─────────────┐ │
│ │ Policy Decision │ │
│ │ │ │
│ │ quarantine → hold .eml │ │
│ │ reject → bounce │ │
│ │ tag → deliver │ │
│ └────────────┬─────────────┘ │
│ │ │
└────────────────────────┘ │
Clean / tagged email │
──────────────────────────────────────────────────────────────► │
(downstream MTA re-delivery) │
└─────────────────────────────────────────┘

The Haraka relay is the only component you deploy. It connects to the platform’s channel-agnostic scan endpoint and receives a structured JSON response that drives the deliver/quarantine/reject decision. Raw .eml files for quarantined messages are stored on the platform filesystem at /var/quarantine; metadata is stored in the quarantined_emails database table.


Before configuring the relay, you need:

  • Haraka v3.0.3+ installed on a host reachable by your mail infrastructure
  • TLS certificate for the relay host (Let’s Encrypt or corporate CA) — required for STARTTLS on port 587
  • Platform API token with email:scan scope for authenticating to the scan endpoint
  • Downstream MTA that will accept re-delivery of released messages (e.g., your corporate mail relay, Office 365 smart host, or Gmail inbound gateway)
  • DNS access to configure SPF, DKIM, and DMARC records

Configure these DNS records for your relay domain before enabling live traffic:

Record type Name Value Purpose
MX @ or subdomain 10 relay.yourdomain.com Route inbound email to Haraka
SPF (TXT) @ v=spf1 ip4:<relay-ip> include:yourdomain.com -all Authorize relay to send
DKIM (TXT) arbitex._domainkey (public key from Haraka DKIM plugin) Message signing
DMARC (TXT) _dmarc v=DMARC1; p=quarantine; rua=mailto:[email protected] Policy enforcement

  1. Install Haraka globally:

    Terminal window
    npm install -g Haraka
  2. Initialize a new Haraka instance:

    Terminal window
    haraka -i /etc/haraka
    cd /etc/haraka
  3. Configure the listening ports in config/smtp.ini:

    [main]
    listen=0.0.0.0:25,0.0.0.0:587
    [tls]
    key=/etc/ssl/private/relay.key
    cert=/etc/ssl/certs/relay.crt
    requestCert=false
    rejectUnauthorized=false
  4. Enable required plugins in config/plugins:

    tls
    dkim_sign
    spf
    dmarc
    arbitex_dlp

The arbitex_dlp plugin ships with Haraka. Create its configuration file at /etc/haraka/config/arbitex_dlp.ini:

[main]
; Arbitex platform scan endpoint
scan_endpoint=https://platform.arbitex.ai/v1/internal/dlp/scan
; API token with email:scan scope
api_token=<your-api-token>
; Organization ID (leave empty to use token's default org)
org_id=
; Channel identifier — must be "email"
channel=email
; Connection timeout (milliseconds)
timeout_ms=30000
; Retry on transient failures (5xx, network errors)
retry_attempts=3
retry_delay_ms=500
[tls]
; Verify platform TLS certificate (set to false only in dev)
verify=true

The relay enforces an allowlist of sender domains. Email from domains not on the list is rejected before scanning. Configure per-org sender domain restrictions via the admin API:

PUT /v1/admin/email/config/{org_id}
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"allowed_sender_domains": ["acme.com", "acme-contractors.com"],
"quarantine_policy": "quarantine"
}

An empty allowed_sender_domains list ([]) permits all sender domains. Set explicit domains in production to prevent relay abuse.

For the full configuration reference, see Email DLP Configuration.


When a quarantined message is released, the platform re-delivers it via SMTP to the downstream MTA. Set these environment variables on the platform:

Variable Description Example
DOWNSTREAM_MTA_HOST Hostname or IP of the receiving MTA mail.acme.com
DOWNSTREAM_MTA_PORT SMTP port on the downstream MTA 25

Released messages include an X-Arbitex-DLP-Released header for traceability. See Quarantine Management for release procedures.


Configure Haraka’s DKIM plugin to sign outbound mail using your DKIM private key:

config/dkim_sign.ini
[main]
domain=yourdomain.com
selector=arbitex
private_key=/etc/haraka/config/dkim/arbitex.private

Generate a 2048-bit RSA key pair:

Terminal window
openssl genrsa -out /etc/haraka/config/dkim/arbitex.private 2048
openssl rsa -in /etc/haraka/config/dkim/arbitex.private \
-pubout -out /etc/haraka/config/dkim/arbitex.public

Publish the public key as a DNS TXT record at arbitex._domainkey.yourdomain.com:

v=DKIM1; k=rsa; p=<base64-public-key>

Test the end-to-end pipeline before routing live traffic.

Verify the scan endpoint is reachable and the token is valid:

Terminal window
curl -s -X POST https://platform.arbitex.ai/v1/internal/dlp/scan \
-H "Authorization: Bearer <your-api-token>" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"org_id": "<your-org-id>",
"content": {
"subject": "Test message",
"body": "Hello, this is a test email with no sensitive content.",
"from": "[email protected]",
}
}'

Expected response for a clean message:

{
"scan_id": "scan_01HXYZ",
"action": "allow",
"findings": [],
"latency_ms": 94,
"channel": "email"
}

Send a message containing a synthetic PII trigger to confirm quarantine works:

Terminal window
curl -s -X POST https://platform.arbitex.ai/v1/internal/dlp/scan \
-H "Authorization: Bearer <your-api-token>" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"org_id": "<your-org-id>",
"content": {
"subject": "Patient update",
"body": "Patient SSN: 123-45-6789. DOB: 01/15/1980.",
"from": "[email protected]",
}
}'

Expected response when HIPAA template is applied and quarantine policy is active:

{
"scan_id": "scan_01HABC",
"action": "quarantine",
"findings": [
{
"entity_type": "ssn",
"confidence": 0.97,
"detection_tier": 1
},
{
"entity_type": "date_of_birth",
"confidence": 0.88,
"detection_tier": 2
}
],
"latency_ms": 112,
"channel": "email"
}

Use swaks to send a live test through the Haraka relay:

Terminal window
swaks \
--server relay.yourdomain.com:587 \
--tls \
--header "Subject: DLP relay test" \
--body "This is a test message routed through Arbitex Email DLP."

Check the Haraka logs (/var/log/haraka/haraka.log) and confirm the scan response was received and the message was delivered or quarantined as expected.


The Email DLP pipeline scans common attachment formats automatically. No additional configuration is required.

Format Parser Notes
PDF pdfplumber Text-layer extraction only; scanned PDFs without OCR are unscanned
DOCX python-docx Body text, headers, footers, and tracked changes
XLSX openpyxl All sheets, all cell values
CSV Direct decode UTF-8 and Latin-1

Encrypted or password-protected files cannot be inspected. The scan endpoint returns them with status: "unscanned":

{
"attachment_findings": [
{
"filename": "patient-records.pdf",
"status": "unscanned",
"reason": "encrypted_or_password_protected"
}
]
}

Apply your org’s quarantine policy to messages containing unscanned attachments by setting quarantine_unscanned_attachments: true in the per-org config (defaults to false).

The default maximum attachment size is 10 MB per file. Attachments exceeding the limit are not scanned and are treated as unscanned. Adjust the limit per org via the config API (range: 1–50 MB):

PUT /v1/admin/email/config/{org_id}
Content-Type: application/json
{
"max_attachment_size_mb": 25
}