#!/bin/bash
=== CONFIG === IP
API_URL="https://domain.com/api"
ORG_ID="Your ORG ID"
API_TOKEN="Your Token"
AUTH_HEADER="Authorization: Bearer $API_TOKEN"
CONTENT_TYPE="Content-Type: application/json"
Replacement values
OLD_PART="include:x.com"
NEW_PART="include:y.com"
TTL=86400
echo "π Fetching all websites with domains..."
Get all domains that have SPF records with OLD_PART
DOMAINS_WITH_SPF=$(curl -s "$API_URL/orgs/$ORG_ID/websites?recursion=infinite" -H "$AUTH_HEADER" |
jq -r --arg old "$OLD_PART" '
.items[]
| select(.domain.id != null)
| {
org_id: "'$ORG_ID'",
website_id: .id,
domain_id: .domain.id,
domain_name: .domain.domain
}
' | jq -s '.')
TOTAL_DOMAINS=$(echo "$DOMAINS_WITH_SPF" | jq 'length')
if [[ "$TOTAL_DOMAINS" -eq 0 ]]; then
echo "β No domains found."
exit 1
fi
Pick one random domain with SPF record to dry-run
echo "π² Selecting random domain for dry run..."
RANDOM_INDEX=$((RANDOM % TOTAL_DOMAINS))
SAMPLE=$(echo "$DOMAINS_WITH_SPF" | jq ".[$RANDOM_INDEX]")
SAMPLE_WEBSITE_ID=$(echo "$SAMPLE" | jq -r '.website_id')
SAMPLE_DOMAIN_ID=$(echo "$SAMPLE" | jq -r '.domain_id')
SAMPLE_DOMAIN_NAME=$(echo "$SAMPLE" | jq -r '.domain_name')
Fetch its DNS zone
ZONE=$(curl -s "$API_URL/orgs/$ORG_ID/websites/$SAMPLE_WEBSITE_ID/domains/$SAMPLE_DOMAIN_ID/dns-zone" -H "$AUTH_HEADER")
SPF_RECORD=$(echo "$ZONE" | jq -r --arg old "$OLD_PART" '.records[] | select(.kind == "TXT" and (.value | test("v=spf1") and contains($old)))')
if [[ -z "$SPF_RECORD" ]]; then
echo "β οΈ No SPF record with '$OLD_PART' found for $SAMPLE_DOMAIN_NAME"
exit 1
fi
Extract ID and value
SAMPLE_RECORD_ID=$(echo "$SPF_RECORD" | jq -r '.id')
SAMPLE_SPF_OLD=$(echo "$SPF_RECORD" | jq -r '.value')
SAMPLE_SPF_NEW="${SAMPLE_SPF_OLD//$OLD_PART/$NEW_PART}"
Display dry-run info
echo "π§ͺ Dry Run Preview β Domain: $SAMPLE_DOMAIN_NAME"
echo "----------------------------------------"
echo "Old SPF: $SAMPLE_SPF_OLD"
echo "New SPF: $SAMPLE_SPF_NEW"
echo "----------------------------------------"
read -p "β
Proceed to update SPF for ALL domains? (y/n): " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
echo "β Cancelled. No changes were made."
exit 0
fi
Proceed with full update across all matching domains
echo "π Updating SPF records across all matching domains..."
Iterate through all domains again
echo "$DOMAINS_WITH_SPF" | jq -c '.' | while read -r DOMAIN; do
WEBSITE_ID=$(echo "$DOMAIN" | jq -r '.website_id')
DOMAIN_ID=$(echo "$DOMAIN" | jq -r '.domain_id')
DOMAIN_NAME=$(echo "$DOMAIN" | jq -r '.domain_name')
Fetch zone and locate SPF record
ZONE=$(curl -s "$API_URL/orgs/$ORG_ID/websites/$WEBSITE_ID/domains/$DOMAIN_ID/dns-zone" -H "$AUTH_HEADER")
SPF_RECORD=$(echo "$ZONE" | jq -r --arg old "$OLD_PART" '.records[] | select(.kind == "TXT" and (.value | test("v=spf1") and contains($old)))')
if [[ -n "$SPF_RECORD" ]]; then
RECORD_ID=$(echo "$SPF_RECORD" | jq -r '.id')
OLD_SPF=$(echo "$SPF_RECORD" | jq -r '.value')
NEW_SPF="${OLD_SPF//$OLD_PART/$NEW_PART}"
# PATCH request
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH \
"$API_URL/orgs/$ORG_ID/websites/$WEBSITE_ID/domains/$DOMAIN_ID/dns-zone/records/$RECORD_ID" \
-H "$AUTH_HEADER" -H "$CONTENT_TYPE" \
-d "{\"value\": \"$NEW_SPF\", \"ttl\": $TTL}")
if [[ "$RESPONSE" == "204" ]]; then
echo "β
Updated SPF for $DOMAIN_NAME"
else
echo "β Failed to update SPF for $DOMAIN_NAME (HTTP $RESPONSE)"
fi
fi
done