After setting up a mail server, configure its DNS records so that other mail systems can locate the server and authenticate messages sent from the domain. A, MX, PTR, SPF, DKIM, and DMARC records provide the addressing and authentication information used for mail delivery and anti-spoofing checks.
ℹ️
The domain must already be delegated to CDB name servers — the Getting started guide covers zone creation and delegation.
An A record maps a subdomain to an IP address — for a mail server at 192.0.2.1, the record for mail.sample-test.com looks like this:
mail.sample-test.com. IN A 192.0.2.1
Step 2. Set up an MX record
An MX record binds a domain to the mail server. Without an MX record, incoming mail will not work. It is recommended to have more than one mail server so that the second one acts as a backup if the first one fails. For a domain sample-test.com with a mail server at mail.sample-test.com, the record looks like this:
sample-test.com. IN MX 10 mail.sample-test.com.
Step 3. Set up a PTR record
A PTR record, or reverse DNS record, links an IP address to a domain name to help verify server authenticity. The reverse DNS guide covers the full configuration.
PTR records are provisioned by the hosting provider that owns the IP address. Contact the provider to create a reverse DNS zone (RDNS).
For a mail server at 192.0.2.1, the PTR record looks like this:
1.2.0.192.in-addr.arpa IN PTR mail.sample-test.com.
Step 4. Set up SPF (TXT)
An SPF (Sender Policy Framework) record defines which IP addresses are allowed to send mail from a domain. It is added as a TXT record in DNS and helps prevent spam from being sent. An example SPF record for sample-test.com is:
sample-test.com. IN TXT "v=spf1 mx -all"
This means that only the IP addresses associated with the MX records for sample-test.com — here, 192.0.2.1 for mail.sample-test.com — are allowed to send mail on behalf of the domain. -all means that senders not matched by the preceding SPF mechanisms are not authorized to send mail for the domain.
Step 5. Set up a DKIM record
A DKIM record (DomainKeys Identified Mail) adds a digital signature to outgoing messages, allowing recipients to verify that the mail came from the listed server.
A DKIM record requires adjustments to the mail server configuration, including generating a public/private key pair for signing and verification. The EasyDMARC and DMARCLY key generators automate this process.
Once the key pair is generated, the public key is published as a TXT record under a selector subdomain. For a selector named selector1 on sample-test.com, the record looks like this:
selector1._domainkey.sample-test.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
The p= field contains the base64-encoded public key generated for the domain.
Step 6. Set up a DMARC policy (TXT)
A DMARC (Domain-based Message Authentication, Reporting, and Conformance) record defines how to handle emails that fail SPF and DKIM checks. When a message fails the applicable authentication checks, the recipient's mail server applies the DMARC policy: none (no requested action), quarantine, or reject.
The following record sets the policy to quarantine and configures report recipients:
_dmarc.sample-test.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@sample-test.com; ruf=mailto:dmarc-forensics@sample-test.com;"
In this example, the domain owner has set a DMARC policy to quarantine any emails that fail authentication. The rua parameter specifies the email address where aggregate reports will be sent, while the ruf parameter specifies the email address where forensic (detailed) reports will be sent.
Step 7. Verify the records
The CDB DNS Lookup tool and dig confirm whether each record is published:
For the PTR record, run a reverse lookup against the mail server IP address:
dig -x 192.0.2.1
Configuring a mail server requires six DNS record types. The CDB DNS API manages five of them — PTR records are provisioned by the hosting provider that owns the IP address block.
All requests authenticate with an API token. Export these variables before running the commands:
An A record maps the mail subdomain to the server IP address. Receiving servers perform forward-confirmed reverse DNS (FCrDNS) checks — the A record must resolve to the same IP as the PTR record configured on the hosting side.
An MX record designates the mail server for the domain. The priority value (first element of content) determines preference when multiple mail servers exist — a lower number is preferred. The hostname requires a trailing dot to indicate an absolute domain name.
PTR records link an IP address to a domain name and are managed by the provider that owns the IP address block, not by CDB Managed DNS.
ℹ️
Contact the hosting provider to configure a reverse DNS zone (RDNS) for the mail server IP address.
Add an SPF record
An SPF record is a TXT record published at the zone apex. The mx mechanism authorizes all IPs listed in MX records to send mail for the domain; -all rejects all other senders.
A DKIM record is a TXT record published under the selector subdomain selector1._domainkey.zone-name. Generate the public/private key pair using EasyDMARC or DMARCLY, then publish the public key as the TXT content.
A DMARC record is a TXT record at _dmarc.zone-name. It instructs receiving servers how to handle messages that fail SPF or DKIM checks — set p to none, quarantine, or reject, and configure rua and ruf to receive aggregate and forensic reports.
import os
from gcore import CDB
client = CDB()
zone = os.environ["ZONE_NAME"]
dmarc_value = (
"v=DMARC1; p=quarantine; "
+ "rua=mailto:dmarc@" + zone + "; "
+ "ruf=mailto:dmarc-forensics@" + zone + ";"
)
rrset = client.dns.zones.rrsets.create(
"TXT",
zone_name=zone,
rrset_name="_dmarc." + zone,
ttl=300,
resource_records=[{"content": [dmarc_value]}],
)
print(rrset.type, rrset.name)
Run DNS queries to confirm each record is published. CDB authoritative nameservers reflect changes immediately; external resolvers may cache responses for up to the record's TTL.
For the PTR record, run a reverse lookup — this queries the IP provider's nameservers, not CDB DNS:
dig -x 192.0.2.1
Declare all five email DNS records in one configuration using the gcore_dns_zone_rrset resource from the CDB Terraform provider v2. PTR records are managed by the hosting provider that owns the IP block — contact that provider to configure reverse DNS separately.
Configure email records
The configuration below creates the zone, the mail server A record, and the MX, SPF, DKIM, and DMARC TXT records. Apply it once to provision the full email DNS setup.
resource "gcore_dns_zone" "example" {
name = "yourdomain.com"
}
# A record: mail server address
resource "gcore_dns_zone_rrset" "mail_a" {
zone_name = gcore_dns_zone.example.name
rrset_name = "mail.${gcore_dns_zone.example.name}"
rrset_type = "A"
ttl = 300
resource_records = [
{ content = ["192.0.2.1"] }, # replace with the mail server IP
]
# terraform import gcore_dns_zone_rrset.mail_a yourdomain.com/mail.yourdomain.com/A
}
# MX record: directs incoming mail to the mail server
resource "gcore_dns_zone_rrset" "mx" {
zone_name = gcore_dns_zone.example.name
rrset_name = gcore_dns_zone.example.name
rrset_type = "MX"
ttl = 300
resource_records = [
{ content = ["10", "mail.${gcore_dns_zone.example.name}."] }, # priority, then hostname with trailing dot
]
# terraform import gcore_dns_zone_rrset.mx yourdomain.com/yourdomain.com/MX
}
# SPF record: authorizes the mail server to send on behalf of the domain
resource "gcore_dns_zone_rrset" "spf" {
zone_name = gcore_dns_zone.example.name
rrset_name = gcore_dns_zone.example.name
rrset_type = "TXT"
ttl = 300
resource_records = [
{ content = ["v=spf1 mx -all"] },
]
# terraform import gcore_dns_zone_rrset.spf yourdomain.com/yourdomain.com/TXT
}
# DKIM record: publishes the public key for message signing verification
resource "gcore_dns_zone_rrset" "dkim" {
zone_name = gcore_dns_zone.example.name
rrset_name = "selector1._domainkey.${gcore_dns_zone.example.name}"
rrset_type = "TXT"
ttl = 300
resource_records = [
{ content = ["v=DKIM1; k=rsa; p=<BASE64_PUBLIC_KEY>"] }, # replace with the generated public key
]
# terraform import gcore_dns_zone_rrset.dkim yourdomain.com/selector1._domainkey.yourdomain.com/TXT
}
# DMARC record: policy for messages that fail SPF or DKIM checks
resource "gcore_dns_zone_rrset" "dmarc" {
zone_name = gcore_dns_zone.example.name
rrset_name = "_dmarc.${gcore_dns_zone.example.name}"
rrset_type = "TXT"
ttl = 300
resource_records = [
{ content = ["v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; ruf=mailto:dmarc-forensics@yourdomain.com;"] },
]
# terraform import gcore_dns_zone_rrset.dmarc yourdomain.com/_dmarc.yourdomain.com/TXT
}
Generate the DKIM key pair using EasyDMARC or DMARCLY, then paste the base64 public key into the p= field.
Delete the email configuration
Remove all resource blocks — Terraform deletes each RRset on the next terraform apply. Remove gcore_dns_zone.example last, or let Terraform handle the dependency order automatically.