How to Verify PTR Records for Email Deliverability in Scripting Applications


2 views

When sending emails programmatically, PTR (Pointer) records serve as a critical authentication mechanism. These DNS records map IP addresses to domain names, creating reverse DNS lookups that email servers use to verify sender legitimacy.

The most reliable way to check PTR records is using DNS query tools. Here are three common approaches:

# Using dig (Unix/Linux/macOS)
dig -x 192.0.2.1 +short

# Using nslookup (Cross-platform)
nslookup -q=ptr 192.0.2.1

# Using host command
host 192.0.2.1

For Python applications, you can implement automated PTR verification:

import socket
import dns.resolver

def check_ptr_record(ip_address):
    try:
        ptr_record = socket.gethostbyaddr(ip_address)[0]
        print(f"PTR record found: {ptr_record}")
        
        # Additional validation with dnspython
        answers = dns.resolver.resolve(ptr_record, 'A')
        for rdata in answers:
            if str(rdata) == ip_address:
                return True
        return False
    except Exception as e:
        print(f"PTR verification failed: {str(e)}")
        return False

When PTR checks fail, examine these potential problems:

  • Mismatch between PTR record and SMTP HELO/EHLO domain
  • Missing or incorrect reverse DNS zone configuration
  • Propagation delays after recent DNS changes
  • Multiple PTR records for a single IP

Here's how to implement PTR validation in a Node.js email script:

const dns = require('dns');
const util = require('util');
const resolvePtr = util.promisify(dns.reverse);

async function validateSenderIP(ip) {
  try {
    const hostnames = await resolvePtr(ip);
    if (hostnames.length === 0) {
      throw new Error('No PTR record configured');
    }
    console.log(Valid PTR record: ${hostnames[0]});
    return true;
  } catch (err) {
    console.error(PTR validation error: ${err.message});
    return false;
  }
}

// Usage in email sending function
await validateSenderIP('192.0.2.1');

For production systems, consider these additional checks:

# SPF record validation example
dig txt example.com +short | grep "v=spf1"

# DKIM verification
dig selector._domainkey.example.com +short txt

# DMARC policy check
dig _dmarc.example.com +short txt


PTR (Pointer) records, also known as reverse DNS records, are crucial for email deliverability. They map an IP address back to a domain name, allowing receiving mail servers to verify the sender's authenticity. Without a properly configured PTR record, your emails might end up in spam folders or get rejected entirely.

The most straightforward way to check PTR records is using the dig command (Linux/macOS) or nslookup (Windows). Here's how:

# Using dig (Linux/macOS)
dig -x 192.0.2.1 +short

# Using nslookup (Windows)
nslookup -type=PTR 192.0.2.1

For example, if you want to check the PTR record for IP 192.0.2.1:

$ dig -x 192.0.2.1 +short
mail.example.com.

Here's a Python script to automate PTR record verification:

import socket
import dns.resolver

def check_ptr(ip_address):
    try:
        # Perform reverse DNS lookup
        hostname = socket.gethostbyaddr(ip_address)[0]
        
        # Verify forward DNS matches
        resolver = dns.resolver.Resolver()
        a_record = resolver.resolve(hostname, 'A')[0].address
        
        if a_record == ip_address:
            return f"Valid PTR record: {hostname}"
        else:
            return "PTR exists but doesn't match forward DNS"
            
    except (socket.herror, dns.resolver.NXDOMAIN):
        return "No PTR record found"
    except dns.resolver.NoAnswer:
        return "PTR record exists but no matching A record"

# Example usage
print(check_ptr("192.0.2.1"))

Problem: PTR record exists but doesn't match forward DNS.
Solution: Ensure your PTR record resolves to a hostname that has an A record pointing back to the original IP.

Problem: No PTR record found.
Solution: Contact your ISP or hosting provider to set up the PTR record. Most providers have a control panel or support ticket system for this.

For those managing multiple servers, here's a Bash script to check PTR records for multiple IPs:

#!/bin/bash
# Bulk PTR checker
IPS=("192.0.2.1" "192.0.2.2" "192.0.2.3")

for ip in "${IPS[@]}"; do
    ptr=$(dig -x "$ip" +short)
    if [ -z "$ptr" ]; then
        echo "$ip: No PTR record"
    else
        echo "$ip: $ptr"
    fi
done

Here's how to add PTR verification to your email sending script (Python example using smtplib):

import smtplib
import socket

def send_email_with_pt_check(sender, recipients, message):
    # Get server IP
    server_ip = socket.gethostbyname('mail.example.com')
    
    # Check PTR record
    try:
        ptr_record = socket.gethostbyaddr(server_ip)[0]
        print(f"Using server with PTR: {ptr_record}")
        
        # Proceed with email sending
        with smtplib.SMTP('mail.example.com') as server:
            server.sendmail(sender, recipients, message)
            
    except socket.herror:
        print("WARNING: No PTR record found - emails may be marked as spam")
        raise

Several online tools can help verify your PTR records:

  • MXToolbox (https://mxtoolbox.com/ReverseLookup.aspx)
  • DNS Checker (https://dnschecker.org/reverse-dns.php)
  • WhatsMyDNS (https://www.whatsmydns.net/)