Skip to content

Instantly share code, notes, and snippets.

@i5heu
Last active June 16, 2026 11:32
Show Gist options
  • Select an option

  • Save i5heu/d4ec4461ae0ba3bebe3c296476c95901 to your computer and use it in GitHub Desktop.

Select an option

Save i5heu/d4ec4461ae0ba3bebe3c296476c95901 to your computer and use it in GitHub Desktop.
Automated anti-spam script for Mastodon Docker Compose instances. Securely syncs disposable email blocklists using tootctl. Hardened against injection and optimized with xargs batching to safely handle large amounts of domains without errors.

Mastodon Disposable Email Blocklist Sync

A Bash script to automatically stop spam signups on Mastodon Docker Compose instances by blocking temporary and throwaway email domains.

It automates downloading crowdsourced blocklists and imports them safely using the native tootctl email-domain-blocks add command.

⚡ Features

  • Fixes "Argument list too long": Uses xargs to batch imports (250 domains at a time). This prevents tootctl or Linux ARG_MAX errors when handling large lists of 60,000+ domains.
  • Security Hardened: Uses strict alphanumeric regex validation (grep -E) to filter incoming data, preventing command injection or shell exploits from untrusted files.
  • Punycode Support: Native compatibility with internationalized domain names formatted as xn--....

🛠️ Requirements

  • Self-hosted Mastodon using Docker Compose
  • Linux environment with bash, grep, xargs, and curl
  • For the cronjob: crontab and shuf

📅 Automated Cron Setup

Save the script as mastodon-spam-blocklist-sync.sh and add it to your crontab to run daly:

# Open crontab
crontab -e

# Run every day at 2:00 AM using bash, with a random delay of up to 30 minutes to prevent spikes
0 2 * * * sleep $(shuf -i 0-1800 -n 1) && PATH=$PATH:/usr/local/bin bash /opt/mastodon/mastodon-spam-blocklist-sync.sh > /dev/null 2>&1

License

mastodon_block_disposable_emails.sh Copyright 2026 Mia Heidenstedt and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#!/bin/bash
# -------------------------------------------------------------------------
# Secure Script to automate blocking disposable email domains
# Hardened against command injection, shell metacharacters, and spaces.
# Uses batched execution to prevent ARG_MAX kernel limitations.
# -------------------------------------------------------------------------
DOCKER_COMPOSE_DIR="/opt/mastodon"
BLOCKLIST_URL="https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf"
echo "⏳ Fetching and validating the disposable email domain list..."
# Securely read the validated output directly into a Bash array.
# The grep regex explicitly requires at least one dot and forbids all spaces/symbols.
# Note: Punycode (e.g., xn--...) is natively supported by this regex pattern.
mapfile -t SECURE_DOMAINS < <(curl -sL "$BLOCKLIST_URL" | \
tr -d '\r' | \
grep -E '^[a-zA-Z0-9][a-zA-Z0-9-]*(\.[a-zA-Z0-9-]+)+$')
# Security Check: Ensure the array is not empty (in case of a download failure or regex block)
if [ ${#SECURE_DOMAINS[@]} -eq 0 ]; then
echo "❌ Error: No valid domains passed the strict security filter."
exit 1
fi
echo "🛡️ Injecting ${#SECURE_DOMAINS[@]} sanitized domains into Mastodon in batches of 250..."
cd "$DOCKER_COMPOSE_DIR" || exit 1
# Execute the command by piping the safe array through xargs.
# We batch them in groups of 250 to avoid hitting ARG_MAX or crashing tootctl.
printf "%s\n" "${SECURE_DOMAINS[@]}" | xargs -n 250 docker compose exec -T web bundle exec tootctl email-domain-blocks add
echo "✅ Disposable email blocks successfully updated!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment