Domains

Add and verify your domains to send emails with your own sender identity.

Why Verify Domains?

Domain verification improves email deliverability and protects your brand:

  • Better deliverability - Verified domains have higher inbox placement rates
  • Brand protection - DKIM signing prevents email spoofing
  • Professional appearance - Send from your own domain, not a shared sender

Add a Domain

Register a domain for verification.

POST /v1/domains
add-domain.ts
const domain = await client.domains.create({
  domain: 'mail.example.com',
});

console.log(domain.status); // 'pending'
console.log(domain.dnsRecords); // DNS records to configure

DNS Configuration

After adding a domain, you will receive DNS records to configure. Add these records to your DNS provider:

Required Records

TypeHostValuePurpose
TXTmailv=spf1 include:spf.veilmail.xyz ~allSPF (sender verification)
TXTveilmail._domainkeyk=rsa; p=MIGfMA0GCS...DKIM (signing)
CNAMEbouncebounce.veilmail.xyzBounce handling

DNS Propagation

DNS changes can take up to 48 hours to propagate. Most changes are visible within a few minutes to a few hours.

Verify Domain

After configuring DNS records, trigger verification to check the setup.

POST /v1/domains/:id/verify
verify-domain.ts
const domain = await client.domains.verify('domain_xxxxx');

if (domain.status === 'verified') {
  console.log('Domain verified successfully!');
} else {
  // Check which records are still pending
  for (const record of domain.dnsRecords) {
    console.log(`${record.type} ${record.host}: ${record.status}`);
  }
}

Domain Status

StatusDescription
pendingDNS records not yet verified
verifiedAll DNS records verified, ready to send
failedVerification failed (records may be incorrect)

List Domains

GET /v1/domains
list-domains.ts
const { data } = await client.domains.list();

for (const domain of data) {
  console.log(`${domain.domain}: ${domain.status}`);
}

DMARC Configuration

DMARC (Domain-based Message Authentication, Reporting, and Conformance) is required by Google and Yahoo for bulk senders. It builds on SPF and DKIM to prevent spoofing.

Getting Started

Add a TXT record for _dmarc.yourdomain.com with a monitoring-only policy to start:

_dmarc.yourdomain.com TXT record
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com

Progressive Enforcement

After monitoring reports for a few weeks and confirming SPF/DKIM alignment, progress to stricter policies:

PolicyRecordBehavior
p=nonev=DMARC1; p=none; rua=mailto:...Monitor only, no action on failures
p=quarantinev=DMARC1; p=quarantine; rua=mailto:...Move failing emails to spam
p=rejectv=DMARC1; p=reject; rua=mailto:...Reject failing emails entirely

SPF and DKIM Alignment

DMARC requires either SPF or DKIM to pass and align with the "From" domain. Verify your domain in Veil Mail first to ensure DKIM is configured, then add your DMARC record.

Tracking Configuration

Control open and click tracking per domain. Both are enabled by default. Disabling tracking will prevent the email provider from injecting tracking pixels (opens) or rewriting links (clicks) for emails sent from this domain.

PATCH /v1/domains/:id
update-tracking.ts
// Disable open tracking, keep click tracking enabled
const domain = await client.domains.update('domain_xxxxx', {
  trackOpens: false,
  trackClicks: true,
});

console.log(domain.tracking);
// { opens: false, clicks: true }

Response

All domain responses include a tracking object:

response.json
{
  "id": "domain_xxxxx",
  "domain": "mail.example.com",
  "status": "verified",
  "tracking": {
    "opens": false,
    "clicks": true
  },
  "dnsHealth": {
    "healthy": true,
    "issues": [],
    "lastCheckedAt": "2025-01-15T16:00:00Z"
  },
  "verifiedAt": "2025-01-15T10:00:00Z",
  "createdAt": "2025-01-10T10:00:00Z"
}

Python SDK

update_tracking.py
domain = client.domains.update(
    "domain_xxxxx",
    track_opens=False,
    track_clicks=True,
)
print(domain["tracking"])
# {"opens": False, "clicks": True}

DNS Health Monitoring

Veil Mail automatically monitors DNS records for all verified domains every 6 hours. If records change or disappear, the domain's health status is updated and visible in the dashboard and API responses.

Health Status

All domain responses include a dnsHealth object:

FieldTypeDescription
healthybooleanWhether all required DNS records are valid
issuesstring[]List of detected DNS issues (empty when healthy)
lastCheckedAtstring | nullISO timestamp of the last health check
check-dns-health.ts
const domain = await client.domains.get('domain_xxxxx');

if (!domain.dnsHealth.healthy) {
  console.warn('DNS issues:', domain.dnsHealth.issues);
  // ["DKIM record not found at veil._domainkey.mail.example.com"]
}

BIMI (Brand Indicators for Message Identification)

BIMI allows your brand logo to appear next to your emails in supported email clients (Gmail, Apple Mail, Yahoo). When recipients see your verified logo, it builds trust and increases engagement.

Prerequisites

  • DMARC enforcement - Your domain must have a DMARC policy of p=quarantine or p=reject
  • Brand logo - An SVG file in Tiny P/S format, hosted at a public HTTPS URL
  • VMC (optional) - A Verified Mark Certificate from DigiCert or Entrust for Gmail support

DNS Record Format

Add a TXT record at default._bimi.yourdomain.com:

default._bimi.yourdomain.com TXT record
v=BIMI1; l=https://example.com/logo.svg; a=https://example.com/vmc.pem
TagRequiredDescription
v=BIMI1YesBIMI version identifier
l=YesHTTPS URL to your brand logo (SVG Tiny P/S format)
a=NoHTTPS URL to your Verified Mark Certificate (VMC)

Check BIMI Status

GET /v1/domains/:id/bimi
check-bimi.ts
const bimi = await client.domains.checkBimi('domain_xxxxx');

if (bimi.bimi.configured) {
  console.log('Logo URL:', bimi.bimi.logoUrl);
  console.log('VMC URL:', bimi.bimi.authorityUrl);
} else {
  console.log('BIMI not configured:', bimi.errors);
}

Response

bimi-response.json
{
  "domainId": "domain_xxxxx",
  "domain": "mail.example.com",
  "bimi": {
    "configured": true,
    "logoUrl": "https://example.com/logo.svg",
    "authorityUrl": "https://example.com/vmc.pem",
    "rawRecord": "v=BIMI1; l=https://example.com/logo.svg; a=https://example.com/vmc.pem"
  },
  "dnsRecord": {
    "type": "TXT",
    "name": "default._bimi.mail.example.com",
    "expectedFormat": "v=BIMI1; l=<logo_url>; a=<authority_url>"
  },
  "errors": []
}

BIMI status is also included in all domain list and detail responses under the bimi field, and is automatically re-checked during periodic DNS health monitoring.

SVG Requirements

The logo must be in SVG Tiny P/S (Portable/Secure) format — not standard SVG. Many email clients reject logos that do not meet this specification. Use a tool like the BIMI Group SVG converter to validate your file.

Link Branding (Custom Tracking Domains)

By default, click and open tracking links use Veil Mail's domain. Link branding lets you replace those with your own custom domain (e.g., track.yourdomain.com), improving deliverability and maintaining a consistent brand experience for recipients.

Why Use Link Branding?

  • Better deliverability - Links from your own domain are less likely to be flagged by spam filters
  • Brand consistency - Recipients see your domain in tracking links, not a third-party URL
  • Recipient trust - Users are more likely to click links that match your brand

Step 1: Set Your Tracking Domain

POST /v1/domains/:id/tracking-domain
set-tracking-domain.ts
const result = await client.domains.setTrackingDomain('domain_xxxxx', {
  trackingDomain: 'track.example.com',
});

console.log(result.dnsInstructions);
// { type: 'CNAME', name: 'track.example.com', value: 'track.veilmail.xyz' }

Step 2: Configure DNS

Add a CNAME record at your DNS provider:

TypeHostValue
CNAMEtracktrack.veilmail.xyz

Step 3: Verify

POST /v1/domains/:id/tracking-domain/verify
verify-tracking-domain.ts
const result = await client.domains.verifyTrackingDomain('domain_xxxxx');

if (result.trackingDomain.verified) {
  console.log('Tracking domain verified!');
  // All click/open tracking links will now use track.example.com
} else {
  console.log('Errors:', result.errors);
}

Remove Tracking Domain

DELETE /v1/domains/:id/tracking-domain
remove-tracking-domain.ts
await client.domains.removeTrackingDomain('domain_xxxxx');
// Tracking links will revert to using the default Veil Mail domain

Response

All domain responses now include a trackingDomain object:

tracking-domain-response.json
{
  "id": "domain_xxxxx",
  "domain": "mail.example.com",
  "status": "verified",
  "trackingDomain": {
    "domain": "track.example.com",
    "verified": true,
    "cname": "track.veilmail.xyz"
  },
  ...
}

SSL Certificates

Custom tracking domains require SSL/TLS. Veil Mail automatically provisions certificates for verified tracking domains. Allow a few minutes after verification for certificate provisioning to complete.

Delete Domain

DELETE /v1/domains/:id
delete-domain.ts
await client.domains.delete('domain_xxxxx');