VeriTrust
PowerShell Gateway & SMTP Enforcement

Run VeriTrust from Windows PowerShell.

Use the persistent sender/receiver console to enforce VeriTrust inline between two laptops, or submit email text, raw .eml evidence, URLs, and reports through the API workflow. The live CLI installs its local prerequisites automatically.

Windows PowerShell
VeriTrust LabSMTP Enforcement CLI 2.0.1

> /send email.eml

[ANALYZE] Raw EML uploaded; waiting for policy decision...

[ALLOWED] 250 2.0.0 Message accepted after VeriTrust inspection

> /send phishing.eml

[BLOCKED] 550 5.7.1 Message rejected by VeriTrust policy

Session remains active. Type the next .eml filename.

> _

01Create keyOrganization-scoped access
02SubmitEmail text, .eml, URL, or media
03WaitFast path or worker
04DecideVerdict and evidence
01

Prerequisites

Before you start

Use Windows PowerShell 5.1 or PowerShell 7 on your own computer. You need a VeriTrust API key created inside the organization that will own the scans.

K

Organization API key

Create a fresh key from API Access. New keys include gateway scan, read, and cancel permissions.

Open API Access →
P

PowerShell

Open a normal PowerShell window. Administrator mode is not required.

S

Safe test content

Use content and files you are authorized to process. Start with a controlled test case.

Keep the key private.Never place the real key inside a command, screenshot, chat, repository, or shared document. The secure prompt below keeps it out of command history.
LIVE

Persistent sender + receiver console

Inline SMTP enforcement between two laptops

The live CLI keeps VeriTrust in the mail path: sender PowerShell → authenticated SMTP gateway → trusted-receiver analysis → policy decision → receiver. A passed message is relayed and saved; hold/manual-review returns SMTP 451; quarantine/block returns SMTP 550 with no downstream delivery.

VeriTrust Lab mark
VeriTrust Lab Persistent PowerShell SMTP CLI Version 2.0.1 · Windows PowerShell 5.1+ · persistent multi-message sessions
Fastest startDownload the complete package, extract it, then run Run-VeriTrust-Receiver.cmd on the receiver and Run-VeriTrust-Sender.cmd on the sender. The package also includes Validate-VeriTrust-CLI.cmd for a local Windows PowerShell parser check before launch. Tailscale and the receiver's portable Node.js/runtime dependencies are handled automatically when missing.
01Sender laptop

Run the persistent sender console, pair once, then type email.eml, /send another.eml, or an absolute path repeatedly.

02VeriTrust SMTP Gateway

Authenticates the sender, captures trusted SMTP facts, submits the exact RFC822 message to VeriTrust, and applies the Gateway recommendation.

03Receiver console

Only approved mail reaches the local receiver. Accepted .eml files are saved in the folder where the receiver console was started.

What installs automatically?The scripts detect Tailscale and install it when missing, connect the device, configure the receiver firewall boundary, and download a portable Node.js 24 runtime on the receiver when required. The SMTP gateway runtime is downloaded automatically. No global Node installation or manual repository extraction is required.
WindowsPowerShell 5.1 or newer

Run the receiver from a Windows account that can approve administrator elevation. The sender self-elevates only when Tailscale installation or service startup requires it.

TailnetBoth devices must be reachable

The easiest demo setup is the same Tailscale account on both laptops. Different accounts also work when both are invited/shared into a tailnet that permits the connection.

VeriTrustReceiver-only trust credentials

The receiver needs a scoped Gateway API key plus the server-configured VERITRUST_EMAIL_RECEIVER_SECRET. The sender never receives either secret.

Server owner setup — onceConfigure VERITRUST_EMAIL_RECEIVER_SECRET on the deployed VeriTrust API and set VERITRUST_TRUSTED_AUTHSERV_IDS=veritrust-smtp-gateway, then redeploy. Use the same receiver-secret value when the receiver CLI asks for it. Create a Gateway API key from API Access. Do not share these receiver credentials with the sender.
PowerShellGenerate a receiver secret when you do not already have one
$Bytes = New-Object byte[] 48
$Rng = [Security.Cryptography.RandomNumberGenerator]::Create()
$Rng.GetBytes($Bytes)
$ReceiverSecret = [Convert]::ToBase64String($Bytes)
$Rng.Dispose()
$ReceiverSecret

Store the generated value as VERITRUST_EMAIL_RECEIVER_SECRET in the deployed VeriTrust environment. If an existing receiver secret is already configured and known, keep using that value instead of rotating it unnecessarily.

Receiver laptopDownload and launch the persistent receiver console
$Receiver = Join-Path $PWD "VeriTrust-Receiver-CLI.ps1"
Invoke-WebRequest `
    -Uri "https://www.veritrustlab.in/assets/powershell/VeriTrust-Receiver-CLI.ps1" `
    -OutFile $Receiver `
    -UseBasicParsing `
    -ErrorAction Stop

Set-ExecutionPolicy Bypass -Scope Process -Force
& $Receiver
Receiver resultKeep the receiver console open. It prints a one-line VTCLI2|... pairing code and copies it to the clipboard. Give only that pairing code to the sender. Approved messages appear live and are saved into the receiver console's starting directory.
Sender laptopDownload and launch the persistent sender console
$Sender = Join-Path $PWD "VeriTrust-Sender-CLI.ps1"
Invoke-WebRequest `
    -Uri "https://www.veritrustlab.in/assets/powershell/VeriTrust-Sender-CLI.ps1" `
    -OutFile $Sender `
    -UseBasicParsing `
    -ErrorAction Stop

Set-ExecutionPolicy Bypass -Scope Process -Force
& $Sender
Persistent sender promptPair once, then send as many EML files as needed
pair> VTCLI2|100.x.x.x|2525|veritrust-sender|...|lab.local

> email.eml
> /send phishing-test.eml
> /send C:\MailTests\invoice.eml
> /history
> /status
> /check
> /help
> /quit
Sender commands/send <file.eml>/files/status/check/pair/pwd/cd <path>/last/history/clear/help/quit
Receiver commands/status/pair/files/view last/view <file.eml>/path/reset-credentials/clear/help/quit
Same-laptop testYou can run the receiver in one PowerShell window and the sender in another on the same Windows laptop. When the pairing code contains the same Tailscale IP as the sender, the CLI automatically routes the SMTP connection through 127.0.0.1 while preserving the complete VeriTrust analysis path.
250Allow / Warn

Message passed VeriTrust and was relayed to the receiver.

451Hold / Manual review

Temporary rejection. The receiver does not receive the message.

550Quarantine / Block

Permanent policy rejection. The receiver does not receive the message.

02

Run once per session

Secure setup and authentication

Copy this complete block into PowerShell. When prompted, paste the API key and press Enter. The key appears only as asterisks.

PowerShellSecure session setup
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$BaseUrl = "https://www.veritrustlab.in"
$SecureApiKey = Read-Host "Paste your VeriTrust API key" -AsSecureString
$ApiKey = (New-Object System.Net.NetworkCredential("", $SecureApiKey)).Password

if ($ApiKey -notmatch '^vtg_(live|test)_[A-Za-z0-9_-]{20,}$') {
    throw "The entered value is not a valid VeriTrust API key."
}

$AuthHeaders = @{ Authorization = "Bearer $ApiKey" }
$Authentication = Invoke-RestMethod `
    -Method Get `
    -Uri "$BaseUrl/api/v1/gateway/scans?limit=1" `
    -Headers $AuthHeaders `
    -ErrorAction Stop

if ($Authentication.ok -ne $true) {
    throw "VeriTrust authentication failed."
}

Write-Host "Authenticated with VeriTrust." -ForegroundColor Green
Expected outputAuthenticated with VeriTrust. Keep this PowerShell window open for the examples below.
03

Email investigation workflow

Investigate email text or an .eml file

Load the verified VeriTrust email command once per PowerShell session. It sends pasted text or the exact bytes of an original email through the Evidence Correlation Gateway and returns a clear result, risk score, recommended action, and report ID.

Which input should I use?Text is fastest and checks wording plus links. An .eml file also preserves sender verification, sender consistency, attachment details, and the recorded delivery route.
PowerShellLoad and verify the email investigation command
$CommandUrl = "$BaseUrl/assets/powershell/VeriTrust.EmailInvestigation.ps1"
$CommandPath = Join-Path ([IO.Path]::GetTempPath()) "VeriTrust.EmailInvestigation.ps1"

Invoke-WebRequest `
    -Uri $CommandUrl `
    -OutFile $CommandPath `
    -UseBasicParsing `
    -ErrorAction Stop

. $CommandPath
Get-Command Invoke-VeriTrustEmailInvestigation -ErrorAction Stop
Expected outputPowerShell displays Invoke-VeriTrustEmailInvestigation with command type Function. You can also download the command script, review it, and dot-source it locally. The command returns a concise report object; complete evidence remains available through .TechnicalReport. Requests use UTF-8, require an HTTPS origin, and time out after 90 seconds. Set -TimeoutSec to change that limit. When retrying the same submission, reuse an explicit -IdempotencyKey to avoid creating another investigation.
PowerShellOption A: investigate pasted email text
if (-not (Get-Command Invoke-VeriTrustEmailInvestigation -ErrorAction SilentlyContinue)) {
    $CommandPath = Join-Path ([IO.Path]::GetTempPath()) "VeriTrust.EmailInvestigation.ps1"
    Invoke-WebRequest -Uri "$BaseUrl/assets/powershell/VeriTrust.EmailInvestigation.ps1" -OutFile $CommandPath -UseBasicParsing -ErrorAction Stop
    . $CommandPath
}

$EmailText = @"
URGENT: Your Microsoft 365 account will be suspended today.
Confirm your password immediately using the verification link.
"@

$EmailResult = Invoke-VeriTrustEmailInvestigation `
    -Subject "Action required" `
    -Body $EmailText

$EmailResult | Select-Object `
    Result, RiskPercent, RecommendedAction, MissingChecks, ReportId |
    Format-List
PowerShellOption B: upload an original .eml file
if (-not (Get-Command Invoke-VeriTrustEmailInvestigation -ErrorAction SilentlyContinue)) {
    $CommandPath = Join-Path ([IO.Path]::GetTempPath()) "VeriTrust.EmailInvestigation.ps1"
    Invoke-WebRequest -Uri "$BaseUrl/assets/powershell/VeriTrust.EmailInvestigation.ps1" -OutFile $CommandPath -UseBasicParsing -ErrorAction Stop
    . $CommandPath
}

$EmailResult = Invoke-VeriTrustEmailInvestigation -EmlPath "C:\SecurityTests\suspicious-email.eml"

$EmailResult | Select-Object `
    Result, RiskPercent, RecommendedAction, InputType, MissingChecks, ReportId |
    Format-List

# Show the complete forensic evidence when needed:
$EmailResult.TechnicalReport.evidence | ConvertTo-Json -Depth 30
Same evidence, any interface.Both commands use the production email investigation service behind VeriTrust. The report ID can be opened in the Gateway and appears in the organization case history.
08

Audit output

Fetch reports and scan history

Every example above leaves the completed identifier in $ScanId. Use it to retrieve the unified report and save a JSON copy to the Desktop.

PowerShellFetch and save the current report
$ReportResponse = Invoke-RestMethod `
    -Method Get `
    -Uri "$BaseUrl/api/v1/gateway/reports/$ScanId" `
    -Headers $AuthHeaders `
    -ErrorAction Stop

$ReportPath = Join-Path `
    ([Environment]::GetFolderPath("Desktop")) `
    "veritrust-report-$ScanId.json"

$ReportResponse |
    ConvertTo-Json -Depth 50 |
    Set-Content -LiteralPath $ReportPath -Encoding UTF8

Write-Host "Report saved to $ReportPath" -ForegroundColor Green
$ReportResponse.report.decision | Format-List
PowerShellList the 20 most recent scans
$History = Invoke-RestMethod `
    -Method Get `
    -Uri "$BaseUrl/api/v1/gateway/scans?limit=20" `
    -Headers $AuthHeaders `
    -ErrorAction Stop

$History.scans |
    Select-Object display_id, source, status, processing_mode, degraded, created_at |
    Format-Table -AutoSize
Case persistenceEvery gateway scan is stored against the organization that owns the API key. After the request is accepted, it appears in Dashboard > Cases with normalized evidence and decision history, including scans submitted from Windows PowerShell. Refresh the case to load the latest status and final decision.
09

Interpretation

Understand the response

Decision

One policy outcome

risk, verdict, and recommendation summarize the correlated result across applicable artifacts.

Evidence

Per-model findings

Each entry identifies its model, score, verdict, confidence, reason codes, and recorded model version.

Status

Processing lifecycle

completed is final. Image scans can move through accepted, processing, and partially completed states first.

Review

Human checkpoint

Manual review means the case should be examined with source context before a consequential action.

Low0–44%
Medium45–74%
High75–89%
Critical90–100%
Interface distinctionThe generic Gateway API remains advisory unless a downstream integration applies its recommendation. The live SMTP CLI above is that enforcement integration: it maps the Gateway recommendation to relay, SMTP 451 defer, or SMTP 550 reject.
10

Recovery

Common errors

TAIL Tailscale reports “no matching peer”

The sender cannot see the receiver in its tailnet. For the simplest demo, log both laptops into the same Tailscale account. With different accounts, invite/share the receiver into a tailnet whose policy permits the sender. Then run tailscale status and confirm the receiver appears before retrying /check.

2525 Receiver SMTP endpoint is unreachable

Keep the receiver CLI running. It automatically disables Tailscale shields-up and recreates the Windows Firewall rule for TCP 2525 from Tailscale peers. If reachability still fails, verify the tailnet access policy allows the sender to reach the receiver and use /check again.

TRUST Trusted receiver authentication fails

The value entered on the receiver must exactly match the deployed VERITRUST_EMAIL_RECEIVER_SECRET, and VERITRUST_TRUSTED_AUTHSERV_IDS must include veritrust-smtp-gateway. Redeploy after changing server-side environment values.

CLI PowerShell parser or local script problem

Download the current CLI package above and use the included validated 2.0.1 scripts. The package includes a Windows PowerShell parser validator. Do not reuse older generated scripts from previous tests.

CMD Invoke-VeriTrustEmailInvestigation is not recognized

The command script has not been loaded in this PowerShell session. Run the “Load and verify” block above, then confirm that Get-Command Invoke-VeriTrustEmailInvestigation returns a Function. The text and .eml examples now load it automatically when it is missing.

401 This endpoint requires a valid Bearer token

The key is missing, invalid, expired, or revoked. Create a new organization API key and rerun the secure setup block. Do not type the key inside the Read-Host prompt label.

403 API key has no gateway permissions

Create a new key after gateway access is enabled. It must include gateway:scan, gateway:read, and gateway:cancel.

409 Idempotency conflict

Reuse an idempotency key only when retrying the exact same request body. Generate a new GUID when the content changes.

415 Unsupported image type

Use JPG, JPEG, PNG, WEBP, or BMP. The declared MIME type must match the stored file.

429 Gateway quota exceeded

The API key or organization has reached its current plan limit. Review usage and plan information in the dashboard.

11

Operational safety

Finish securely

Never print the key

Avoid commands such as Write-Host $ApiKey and never include the value in screenshots.

Use one key per integration

Separate keys make rotation, revocation, scopes, and usage attribution manageable.

Preserve request IDs

Store the scan, request, trace, and external event identifiers with your incident record.

Clear the session

Remove the decrypted key from variables when the session is finished.

PowerShellClear credentials from the current session
$ApiKey = $null
$SecureApiKey = $null
$AuthHeaders = $null
[System.GC]::Collect()
Write-Host "VeriTrust session cleared." -ForegroundColor Green