# DNS Email

## Overview

The **DNS Email** integration lets your organization send workflow and notification emails from **your own verified domain** (for example `noreply@notifications.acme.com`) instead of the default Suger sender (`noreply@suger.io`). Delivery is powered by AWS Simple Email Service (SES) with a DKIM-verified domain identity.

Use this integration when you want:

- **Branded sender addresses** — recipients see your domain, not Suger's.
- **Reputation isolation** — outbound mail from your workflows is scoped to a subdomain you control.
- **Deliverability hardening** — DKIM signatures, a custom MAIL FROM domain (proper SPF alignment), and a DMARC policy are configured for you automatically.

Once verified, the integration is consumable by the **DNS Email** workflow node, so any workflow you build can send mail from your domain.

:::tip[Why a subdomain?]
We strongly recommend a dedicated subdomain (for example `notifications.acme.com`, `updates.acme.com`, or `billing.acme.com`) rather than your root domain. A subdomain isolates Suger's sending reputation from the rest of your company's mail and is easier to delegate DNS changes for.
:::

### Org-Level vs User-Level

> **Org-Level**: The DNS Email integration is **org-level only**. All workflows in the organization share a single verified domain identity.
>
> **User-Level**: Not supported. There is no per-user variant of this integration.

## Prerequisites

Before creating the integration, make sure you have:

- A domain (or subdomain) you control — for example `notifications.acme.com`.
- Access to the DNS zone for that domain so you can add 6 records (3 CNAME + 1 MX + 2 TXT).
- Admin rights in your Suger organization to create integrations.

Domain rules enforced at creation:

- Must be a valid domain name (`example.com`, `mail.example.com`, …).
- Internationalized Domain Names (IDN / `xn--` punycode) are **rejected**.
- IP addresses are **rejected**.
- The value is normalized to lowercase.

## Create Integration (Org-Level)

1. Navigate to **Settings → Integrations** in the Suger console.
2. Click **Connect** on the **DNS Email** card.
3. Fill in the form:
   - **Domain** *(required)* — the custom (sub)domain you want to send from, e.g. `notifications.acme.com`.
   - **From Email** *(optional)* — the default sender address used by workflows that don't override it, e.g. `noreply@notifications.acme.com`. If left empty, Suger will use `noreply@<your-domain>`. The domain portion **must match** the integration domain.
4. Click **Create**.

When you submit, Suger calls AWS SES on your behalf and:

1. Registers your domain as a SES sending identity and obtains 3 DKIM tokens.
2. Configures a custom MAIL FROM subdomain (`mail.<your-domain>` by default) for proper SPF alignment and bounce handling.
3. Returns the 6 DNS records you need to add to your DNS provider.

The integration is created in `CREATED` status. It moves to `VERIFIED` only after the DNS records propagate and you click **Verify** (see below).

### Configure DNS Records

After creation, the integration detail page shows 6 records across 3 categories. **Not all of them gate the same thing** — the table below shows exactly what each one is for and what happens if you skip it.

Assume your integration domain is `notifications.acme.com`; values below use realistic placeholders.

#### Requirement Summary

| # | Record | Status | Required for `VERIFIED` status? | Required for actual delivery? | Why |
|---|--------|--------|---------------------------------|-------------------------------|-----|
| 1–3 | DKIM CNAMEs (×3) | **Required** | ✅ Yes | ✅ Yes | Proves domain ownership to SES *and* attaches a DKIM signature to every outbound email. SES blocks the identity from sending until all three are detected. |
| 4 | MAIL FROM MX (×1) | **Required** | ✅ Yes | ✅ Yes | SES checks this MX record to mark the custom MAIL FROM subdomain as `Success`. Without it the integration cannot reach `VERIFIED` and the workflow node refuses to send. |
| 5 | MAIL FROM SPF TXT (×1) | **Required for deliverability** | ❌ No | ✅ Yes (effectively) | Not part of SES's verification gate, so the integration *can* technically reach `VERIFIED` without it — but downstream receivers (Gmail, Outlook, corporate filters) will fail SPF on the custom MAIL FROM domain and quarantine or reject your mail. Skip it and you have a "verified-but-undeliverable" integration. |
| 6 | DMARC TXT (×1) | **Recommended** | ❌ No | ⚠️ Strongly recommended | Not checked by SES or by Suger. Provides a published policy + reporting address so receivers know how to treat unauthenticated mail from your domain. Modern providers (notably Gmail/Yahoo for bulk senders) increasingly require a valid DMARC record; without it, deliverability degrades over time. |

> **TL;DR**: Records 1–4 are **must-add** (without them, **Verify** never succeeds). Record 5 is **must-add for any real-world use** (without it, recipients reject your mail even though Suger says "verified"). Record 6 is **strongly recommended** and trivially cheap to add.

#### 1. DKIM (3 × CNAME) — **Required**

Proves domain ownership to SES (modern replacement for the legacy TXT verification token) and DKIM-signs every outbound email.

| Type  | Name                                                  | Value                                              |
|-------|-------------------------------------------------------|----------------------------------------------------|
| CNAME | `<token1>._domainkey.notifications.acme.com`          | `<token1>.dkim.amazonses.com`                      |
| CNAME | `<token2>._domainkey.notifications.acme.com`          | `<token2>.dkim.amazonses.com`                      |
| CNAME | `<token3>._domainkey.notifications.acme.com`          | `<token3>.dkim.amazonses.com`                      |

> **Why all three?** SES rotates DKIM keys. All three CNAMEs must resolve at any given time, or signing fails for some outbound messages.

#### 2. MAIL FROM MX (1 × MX) — **Required**

Routes bounce / complaint feedback for your custom MAIL FROM subdomain (`mail.<your-domain>`) back to SES. SES's MAIL FROM verification gate (`CustomMailFromStatus=Success`) is satisfied by the presence of this record.

| Type | Name                              | Value                                            |
|------|-----------------------------------|--------------------------------------------------|
| MX   | `mail.notifications.acme.com`     | `10 feedback-smtp.us-west-2.amazonses.com`       |

> The region in the value (`us-west-2`) matches the SES region Suger uses. **Do not change it.**

#### 3. MAIL FROM SPF (1 × TXT) — **Required for deliverability**

Publishes an SPF record on the MAIL FROM subdomain authorising Amazon SES to send on its behalf. Receivers use this to validate SPF alignment under DMARC.

| Type | Name                              | Value                                            |
|------|-----------------------------------|--------------------------------------------------|
| TXT  | `mail.notifications.acme.com`     | `v=spf1 include:amazonses.com ~all`              |

> **This is the most commonly skipped record** because Suger's `VERIFIED` status doesn't depend on it. Skip it and your mail will pass SES's gate but fail at Gmail/Outlook with `spf=softfail` or `spf=fail`. Add it.

#### 4. DMARC (1 × TXT) — **Recommended**

Tells receivers what to do with mail that fails DKIM or SPF on your domain, and (optionally) where to send aggregate reports. Not enforced by SES or by Suger, but essential modern hygiene — and increasingly required for bulk senders by Gmail and Yahoo.

| Type | Name                                  | Value                       |
|------|---------------------------------------|-----------------------------|
| TXT  | `_dmarc.notifications.acme.com`       | `v=DMARC1; p=quarantine;`   |

> The default policy is `p=quarantine;`. You may relax it (`p=none;` for monitor-only) or tighten it (`p=reject;`) once you're confident your alignment is correct. Adding `rua=mailto:dmarc-reports@yourcompany.com` lets you receive daily aggregate reports.

:::note
The exact `token1/token2/token3` values are unique to your integration and are shown in the console after creation. Copy them verbatim from the Suger UI.
:::

#### Strip the zone suffix on providers that auto-append it

Suger shows record names as **fully-qualified domain names** (FQDN), e.g. `_dmarc.notifications.acme.com`. That is the canonical form — and it is what a few providers (notably AWS Route 53) want verbatim.

**However, many popular DNS hosts silently append the parent zone to whatever you type in the `Name` field.** Pasting the FQDN into them produces a doubled, broken record.

Providers known to auto-append the zone (you MUST strip the suffix):

- **Squarespace Domains** (formerly Google Domains)
- **Cloudflare**
- **GoDaddy**
- **Namecheap**
- **Hover**
- **Porkbun**
- **DNSimple**
- **DigitalOcean DNS**
- Most cPanel-based hosts (Bluehost, HostGator, SiteGround…)

Providers that take the FQDN verbatim (do NOT strip):

- **AWS Route 53**
- **NS1**
- Cloudflare when driven via API / Terraform with a trailing-dot FQDN (the UI still auto-appends)

**How to strip:** chop `.<your-integration-domain>` off the end of every `Name` field. The root of the zone itself is usually entered as `@` (or left blank).

Worked example for integration domain `notifications.acme.com`, with DKIM tokens shortened to `abc1` / `abc2` / `abc3`:

| What Suger shows (FQDN)                              | What to enter on Squarespace / Cloudflare / GoDaddy / … |
|------------------------------------------------------|---------------------------------------------------------|
| `abc1._domainkey.notifications.acme.com`             | `abc1._domainkey`                                       |
| `abc2._domainkey.notifications.acme.com`             | `abc2._domainkey`                                       |
| `abc3._domainkey.notifications.acme.com`             | `abc3._domainkey`                                       |
| `mail.notifications.acme.com` *(MX)*                 | `mail`                                                  |
| `mail.notifications.acme.com` *(SPF TXT)*            | `mail`                                                  |
| `_dmarc.notifications.acme.com`                      | `_dmarc`                                                |

:::danger[Double-suffix is the #1 reason `Verify` fails]
If you paste `abc1._domainkey.notifications.acme.com` into a zone-appending provider, the record that actually gets published is `abc1._domainkey.notifications.acme.com.notifications.acme.com` — which SES will never find. Symptoms:

- **Verify** keeps reporting DKIM pending well past the propagation window.
- `dig CNAME abc1._domainkey.notifications.acme.com +short` from your laptop returns nothing (NXDOMAIN).
- Looking up the doubled name (`abc1._domainkey.notifications.acme.com.notifications.acme.com`) *does* return the expected value — the smoking gun.

**Fix:** edit each broken record in your provider's UI and remove the trailing `.notifications.acme.com` from the `Name` field. DNS re-propagates within minutes once the TTL expires; click **Verify** again.
:::

**Special case — verifying the zone apex (e.g. `acme.com` itself):** if your integration domain *is* the zone apex, FQDN-stripping leaves an empty string. Most providers represent the apex as `@`. So `acme.com` → `@`, `_dmarc.acme.com` → `_dmarc`, `mail.acme.com` → `mail`. Using a subdomain avoids this edge case entirely — another reason to prefer one.

#### Other common DNS-provider gotchas

:::caution
- **TXT quoting.** Some DNS UIs wrap TXT values in extra quotes. The published value must be the bare string (e.g. `v=spf1 include:amazonses.com ~all`) — not `"v=spf1 include:amazonses.com ~all"`. Cloudflare's UI strips one layer of quotes; Squarespace and GoDaddy do not.
- **Conflicting existing records.** If `mail.<your-domain>` already has an MX (from a previous experiment or another vendor), the new SES MX may conflict or be ignored. Remove the old one first.
- **MX priority field.** When the provider asks for the MX `Priority` and `Value` separately, enter `10` in Priority and `feedback-smtp.us-west-2.amazonses.com` in Value — not the combined string `10 feedback-smtp.us-west-2.amazonses.com`.
- **CNAME at apex.** A few providers reject CNAMEs at the zone apex. DKIM CNAMEs live at `<token>._domainkey.<your-domain>`, not at the apex, so this generally isn't an issue — but it bites you if you try to verify the apex itself with a CNAME-flattening trick.
- **Slow TTLs.** Default TTLs of 24h–72h delay verification. Drop the TTL on these 6 records to 300s while you're setting up; raise it later if you prefer.

To sanity-check your records before clicking **Verify**, run:

```bash
dig CNAME <token1>._domainkey.notifications.acme.com +short
dig MX    mail.notifications.acme.com                +short
dig TXT   mail.notifications.acme.com                +short
dig TXT   _dmarc.notifications.acme.com              +short
```

Each should return exactly the value Suger showed you — no doubled suffix, no extra quotes, no missing pieces.
:::

### Verify

DNS propagation typically takes a few minutes but can take up to 72 hours depending on your provider's TTLs.

1. On the integration detail page, click **Verify**.
2. Suger queries AWS SES for the current DKIM status and the MAIL FROM domain status.
3. The integration moves to `VERIFIED` **only when both** DKIM and MAIL FROM report success. If either is still pending, the integration stays in its current status and you can click **Verify** again later.

Common reasons verification stays pending:

- DNS records haven't propagated yet → wait, then re-verify.
- **Double-suffix** — you pasted the FQDN (e.g. `mail.notifications.acme.com`) into a provider that auto-appends the zone (Squarespace, Cloudflare, GoDaddy, …), producing `mail.notifications.acme.com.notifications.acme.com`. See [Strip the zone suffix](#strip-the-zone-suffix-on-providers-that-auto-append-it) above.
- The CNAME or TXT value was wrapped in quotes by the DNS UI.
- A conflicting existing record (e.g. an older MX on `mail.<domain>`) is shadowing the new one.
- Records exist but TTL hasn't expired yet — propagation can be capped by your old TTL, not the new one.

### Test

Once the integration is `VERIFIED`, use the **Test** action to send a real end-to-end email:

1. On the integration detail page, click **Test**.
2. Enter a recipient address.
3. Suger sends a one-shot test email from your configured `FromEmail` (or `noreply@<your-domain>` if you didn't set one) to that recipient.
4. The response includes the SES `MessageId`. Check the recipient's inbox (and spam folder) to confirm delivery and sender headers.

:::caution
**Test sends a real email.** It is gated on `VERIFIED` status and uses your AWS SES domain identity — it will count against your SES sending quota.
:::

## Use in Workflows

After verification, the **DNS Email** node becomes a usable sender in the workflow editor.

### DNS Email Node

| Property        | Required | Description                                                                                                                                                                                                                                                       |
|-----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| To Email        | yes      | Recipient address. Must be a valid email.                                                                                                                                                                                                                         |
| CC Email List   | no       | Additional recipients. Accepts comma-joined strings; whitespace and duplicates are stripped automatically.                                                                                                                                                         |
| BCC Email List  | no       | Same rules as CC.                                                                                                                                                                                                                                                 |
| From Email      | no       | Override the default sender for this node only. **The domain portion MUST match the verified integration domain** (case-insensitive). Both bare (`alerts@notifications.acme.com`) and angle-bracket (`"Acme Alerts" <alerts@notifications.acme.com>`) forms are accepted. |
| Subject         | yes      | Subject line.                                                                                                                                                                                                                                                     |
| Email Format    | yes      | `text`, `html`, or `both`. Determines which body fields are required.                                                                                                                                                                                             |
| Text            | cond.    | Plain-text body. Required when format is `text` or `both`.                                                                                                                                                                                                        |
| HTML            | cond.    | HTML body. Required when format is `html` or `both`.                                                                                                                                                                                                              |

### Sender (From) Resolution

For each item the node processes, the effective From address is resolved in this order:

1. The node's **From Email** field (if non-empty) — validated against the integration domain.
2. The integration's **From Email** (if non-empty) — set when the integration was created.
3. `noreply@<integration-domain>` — implicit fallback so a send always has a sender.

This means an org admin can configure a sensible default once on the integration and individual workflows can override it on a per-node basis when needed.

:::caution[Security gate]
A workflow author **cannot** send mail "as" a domain the organization hasn't verified. If you put `alerts@evil.com` in the node's From Email field while the integration is verified for `notifications.acme.com`, the node fails with `fromEmail domain "evil.com" must match the verified integration domain "notifications.acme.com"`. This is enforced server-side, before any SES call is made.
:::

### Status Gate

The DNS Email node refuses to send if the integration is not `VERIFIED`. If you see workflow runs failing with `DNS email integration is not verified (status=...)`, finish DNS setup and re-run **Verify** in the console.

### Multi-Item Sends

The node executes once per input item from the upstream node. If the upstream produces 10 records, the node makes 10 SES `SendEmail` calls — one email per item — and emits one result entry per send.

## Edit Integration

> Editing is **not supported** for security and DNS-consistency reasons. To change the domain or the default From address, delete the integration and create a new one with the new values. (You will need to re-add the DNS records for the new domain.)

## Delete Integration

Deleting the integration in Suger:

1. Removes the SES domain identity in AWS — your verified domain is unregistered.
2. Removes the integration record and its `FromEmail` / `MailFromDomain` / DNS-record metadata from Suger.
3. Causes any workflow that references the **DNS Email** node to start failing on subsequent runs until a new integration is created or the node is removed.

:::warning
- Deletion is **immediate and permanent** in Suger and in AWS SES. There is no undo and no recovery window.
- Suger does **not** clean up the DNS records you added to your zone. You are free to leave them, but if you do not plan to recreate the integration we recommend removing the DKIM CNAMEs, the MAIL FROM MX/TXT records, and the DMARC TXT record at `_dmarc.<your-domain>` to keep your DNS zone tidy.
- Any in-flight workflow executions that were about to call the DNS Email node will fail because the integration is gone.
:::

## FAQ

**Which AWS region is used?**
SES domain identities are created in **`us-west-2`**. This is reflected in the MX value for the custom MAIL FROM record (`feedback-smtp.us-west-2.amazonses.com`).

**Do I have to use a subdomain?**
No, you can verify a root domain (`acme.com`). We strongly recommend a subdomain to isolate sending reputation and avoid conflicts with existing MX/SPF/DKIM records on your primary mail domain.

**Can I configure a different MAIL FROM subdomain?**
The default `mail.<your-domain>` is set automatically at creation. There is currently no UI to override it — recreate the integration if you need a different value.

**Can each workflow use a different sender?**
Yes — set the node's **From Email** field. The domain must match the integration domain, but the local-part (and display name) is free. Example: `alerts@notifications.acme.com`, `billing@notifications.acme.com`, `"Acme Updates" <updates@notifications.acme.com>`.

**Does this support attachments / reply-to / display name?**
The current DNS Email node supports `to`, `cc`, `bcc`, `from` (with display name via angle brackets), `subject`, and text/HTML bodies. Per-send attachments and a dedicated reply-to field are not yet exposed on this node.

**What happens to outbound mail if the integration becomes unverified?**
SES periodically re-checks DKIM and MAIL FROM. If the records are removed from your DNS zone, SES will revoke the identity and Suger workflow runs will start failing the status gate (`DNS email integration is not verified`). Restore the records and click **Verify** to recover.
