# DKIM: digital signatures

> How DKIM signs your outgoing emails, how DKIM records and headers work, how to set up keys with your email provider, and how to fix common issues and edge cases.

[DKIM](https://verifiedinbox.ai/docs/glossary.md#dkim) (DomainKeys Identified Mail, defined in [RFC 6376](https://datatracker.ietf.org/doc/html/rfc6376)) attaches a cryptographic digital signature to every email you send. Think of it like a tamper-proof seal: receiving mail servers use it to verify that the email genuinely came from your [domain](https://verifiedinbox.ai/docs/glossary.md#domain) and that neither the headers nor the message body were altered in transit.

Together with [SPF](https://verifiedinbox.ai/docs/spf.md) and [DMARC](https://verifiedinbox.ai/docs/dmarc.md), DKIM protects your domain from spoofing, builds long-term domain reputation with inbox providers, and is required before inboxes will display your [BIMI](https://verifiedinbox.ai/docs/bimi.md) logo and verified checkmark. We recommend enabling DKIM for every service that sends email from your domain, following each provider's official documentation.

## Why DKIM matters (and what it does not do)

- **Confirms authenticity and integrity:** Proves that an authorized mail server signed the message and that the signed headers (`From`, `To`, `Subject`) and body were not modified on the way.
- **Survives email forwarding:** Unlike [SPF](https://verifiedinbox.ai/docs/spf.md) (which checks the sending server's IP address and breaks when a recipient auto-forwards an email), a DKIM signature travels inside the message headers and remains valid across forwards as long as the message content is not changed.
- **Builds domain reputation:** Inbox providers such as Gmail, Yahoo, and Apple Mail track sending reputation against the domain in your DKIM signature (`d=`). Gmail and Yahoo require both SPF and DKIM for bulk senders (5,000+ messages per day).
- **Does not encrypt the email body:** DKIM verifies *who* sent the message and that it was not tampered with, but it does not encrypt the message content itself (transport encryption is handled separately by TLS).

## How DKIM works

DKIM has two parts: a **public key** published in your domain's [DNS](https://verifiedinbox.ai/docs/glossary.md#dns) and a **private key** kept on your email provider's outgoing mail server.

1. **Key generation:** Your email provider generates a public/private key pair for your domain.
2. **Public key in DNS:** You publish the public key at `<selector>._domainkey.<yourdomain.com>` as a DNS [TXT record](https://verifiedinbox.ai/docs/glossary.md#txt-record) (or as a `CNAME` record pointing to a TXT record hosted by your provider).
3. **Signing outgoing mail:** When you send an email, your provider hashes the message body and selected headers, signs them with the private key, and attaches a `DKIM-Signature` header to the message.
4. **Verification at the inbox:** The receiving server reads the domain (`d=`) and [DKIM selector](https://verifiedinbox.ai/docs/glossary.md#dkim-selector) (`s=`) from the `DKIM-Signature` header, looks up `<s\>._domainkey.<d\>` in DNS, and uses the public key to verify the signature.

### Multiple DKIM records on one domain

Unlike SPF and DMARC (where a domain may only have a single record), **your domain can have as many DKIM records as you need**. Each email service you use (such as Google Workspace, Postmark, or SendGrid) publishes its key under its own unique selector name:

```text
google._domainkey.yourcompany.com
20261019120000pm._domainkey.yourcompany.com
s1._domainkey.yourcompany.com
```

Because DNS does not allow listing all selectors automatically, you can find any sender's active selector by sending a test email, opening **More → Show original** in Gmail, and checking the `s=` value inside the `DKIM-Signature` header. In the VerifiedInbox **Email security** step, you can also send a free test email to the address we give you: we read its signature and check that key for you.

## How to configure and verify DKIM

1. **Generate a DKIM key in your email provider's dashboard.**
   Choose a **2048-bit** key whenever your DNS provider supports it (2048-bit keys are much stronger than 1024-bit keys; keys shorter than 1024 bits are insecure and rejected by modern inboxes).
2. **Add the DNS record at your domain host.**
   Copy the **Host / Name** (which always contains `._domainkey`, such as `google._domainkey`) and the **Value** (either a `v=DKIM1; k=rsa; p=...` TXT value or a `CNAME` target) into your domain's DNS settings.
3. **Turn on DKIM signing in your provider.**
   After saving the DNS record, click **Start authentication** or **Verify** in your email provider's admin console so it begins signing outgoing messages.
4. **Verify with a real external test email.**
   Send an email to an external Gmail address (or to the free test address in the VerifiedInbox **Email security** or **Go live** step) rather than to your own address. In Gmail, open **Show original** and confirm `Authentication-Results` shows `dkim=pass` with `header.d=yourcompany.com`.

## Reputable, developer-friendly email providers

Follow the official guide for each service that sends email for you:

### Postmark

| Field | Value |
|---|---|
| **Selector & record type** | Timestamped TXT selector (for example `20261019120000pm._domainkey`) |
| **Official guide** | [Postmark DKIM setup](https://postmarkapp.com/support/article/1091-how-do-i-set-up-dkim-on-my-domain) |

### Resend

| Field | Value |
|---|---|
| **Selector & record type** | `resend._domainkey` (TXT record) |
| **Official guide** | [Resend domain verification docs](https://resend.com/docs/dashboard/domains/introduction) |

### Amazon SES

| Field | Value |
|---|---|
| **Selector & record type** | Three Easy DKIM CNAME records (`<token>._domainkey`) |
| **Official guide** | [Amazon SES Easy DKIM guide](https://docs.aws.amazon.com/ses/latest/dg/send-email-authentication-dkim-easy.html) |

### SendGrid

| Field | Value |
|---|---|
| **Selector & record type** | `s1._domainkey` and `s2._domainkey` (CNAME records) |
| **Official guide** | [SendGrid domain authentication](https://www.twilio.com/docs/sendgrid/ui/account-and-settings/how-to-set-up-domain-authentication) |

### Mailgun

| Field | Value |
|---|---|
| **Selector & record type** | `smtp._domainkey`, `krs._domainkey`, or `mx._domainkey` (TXT or CNAME) |
| **Official guide** | [Mailgun DKIM setup](https://documentation.mailgun.com/docs/mailgun/user-manual/get-started/verify-domain) |

### Google Workspace

| Field | Value |
|---|---|
| **Selector & record type** | `google._domainkey` (TXT record, 2048-bit recommended) |
| **Official guide** | [Set up DKIM for Google Workspace](https://knowledge.workspace.google.com/admin/security/set-up-dkim) |

### Microsoft 365

| Field | Value |
|---|---|
| **Selector & record type** | `selector1._domainkey` and `selector2._domainkey` (CNAME records) |
| **Official guide** | [Use DKIM with Microsoft 365](https://learn.microsoft.com/en-us/defender-office-365/email-authentication-dkim-configure) |

## Technical reference: DKIM record & header tags

### DKIM DNS TXT record tags

A DKIM DNS record at `<selector>._domainkey.<domain>` is a semicolon-separated list of `tag=value` pairs:

```text
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
```

| Tag | Required? | Meaning |
|---|---|---|
| `v=DKIM1` | Recommended first | Identifies the TXT record as a DKIM key record. |
| `k=rsa` | Optional (default `rsa`) | Key algorithm: `rsa` (most common) or `ed25519`. |
| `p=<base64>` | Required | The base64-encoded public key. **Note:** An empty `p=` (`v=DKIM1; p=`) explicitly **revokes** that key. |
| `t=y` / `t=s` | Optional | Flags: `t=y` indicates the domain is testing DKIM; `t=s` requires strict subdomain matching. Avoid `t=y` in production. |

### `DKIM-Signature` email header tags

Every signed email carries a `DKIM-Signature` header similar to this:

```text
DKIM-Signature: v=1; a=rsa-sha256; d=yourcompany.com; s=google;
  h=from:to:subject:date:message-id;
  bh=uMixy0BsCqhbru4fqPZQdeZY5Pq865sNAnOAxNgUS0s=;
  b=LiIvJeRyqMo0gngiCygwpiKphJjYezb5kXBKCNj8DqRV...
```

| Tag | Example | What it means |
|---|---|---|
| `v=` | `v=1` | DKIM signature version (always `1`). |
| `d=` | `d=yourcompany.com` | The signing domain. To pass [DMARC](https://verifiedinbox.ai/docs/dmarc.md) via DKIM, `d=` must [align](https://verifiedinbox.ai/docs/glossary.md#alignment) with the visible `From:` domain. |
| `s=` | `s=google` | The [DKIM selector](https://verifiedinbox.ai/docs/glossary.md#dkim-selector) used to query `<s\>._domainkey.<d\>` in DNS. |
| `a=` | `a=rsa-sha256` | Algorithm used to hash the message and generate the signature (`rsa-sha256` or `ed25519-sha256`). |
| `h=` | `h=from:to:subject` | Colon-separated list of email headers covered by the signature. |
| `bh=` | `bh=uMixy0Bs...=` | Base64 hash of the canonicalized email body. Computed separately so receivers can verify headers before reading a large body. |
| `b=` | `b=LiIvJeRy...=` | The digital signature computed over the headers in `h=` and the `bh=` body hash using the private key. |

## Common issues & edge cases

- **Record added in DNS, but signing not turned on in the provider.** Many providers (including Google Workspace and Microsoft 365) do not start signing outgoing mail until you click **Start authentication** or enable DKIM in their admin console *after* the DNS record is published.
- **Provider signing with its own default domain (`d=`) instead of yours.** Before you verify a custom domain in a third-party sender (or before you click **Start authentication** in Google Workspace), the provider may sign messages with a shared domain such as `d=*.gappssmtp.com`, `d=*.onmicrosoft.com`, or `d=sendgrid.info`. Even though `dkim=pass` appears in the raw header, DMARC [alignment](https://verifiedinbox.ai/docs/glossary.md#alignment) fails because `d=` does not match your `From:` domain.
- **2048-bit key length limits (255-character DNS TXT strings).** A 2048-bit RSA public key is roughly 400 characters long, which exceeds the 255-character limit of a single DNS TXT string. Most modern DNS hosts automatically split long TXT values into multiple quoted strings (which DNS resolvers concatenate without spaces). If your DNS host rejects values over 255 characters, split the string according to your host's instructions or generate a 1024-bit key. Never paste stray spaces, line breaks, or quotation marks inside the `p=` key.
- **Outbound gateways or security appliances modifying messages after signing.** If an outbound gateway, archiving proxy, or mailing list appends a legal disclaimer footer, rewrites tracking links, or modifies the `Subject:` header *after* the message was signed, the body hash (`bh=`) or signature (`b=`) breaks and DKIM fails. Make sure DKIM signing happens at the final outbound hop, or configure gateways not to alter signed messages.
- **Google Workspace 24–72 hour new-account delay and stale warning banner.** After turning on Gmail for a new Google Workspace organization, you may need to wait 24 to 72 hours before the Admin console lets you generate a DKIM key. In addition, the Google Admin console can continue showing *"You must update the DNS records for this domain"* for up to 48 hours after your record is live.
- **Selector prefix conflict (`google._domainkey` already in use).** If another service already uses the `google` selector on your domain, choose a custom prefix selector (such as `google2`) when generating your key in Google Workspace.
- **Cloudflare proxy ("orange cloud") enabled on DKIM CNAME records.** When a provider gives you `CNAME` records for DKIM (such as Amazon SES, SendGrid, or Microsoft 365), set them to **DNS only** (grey cloud) in Cloudflare so mail servers can resolve the target TXT record.
- **Duplicated domain name in the Host field.** Some DNS providers automatically append `.yourcompany.com` to the Host field. Entering `google._domainkey.yourcompany.com` creates `google._domainkey.yourcompany.com.yourcompany.com`. VerifiedInbox queries your [authoritative nameservers](https://verifiedinbox.ai/docs/glossary.md#authoritative-dns) directly and warns you if this happens.
- **Testing by emailing yourself in the same mailbox.** Sending a message from your address to the exact same address often bypasses external gateway signing or verification. Always test by sending to an external Gmail address or to the test address in the VerifiedInbox **Email security** or **Go live** step.
