Skip to content

How to Fix Exim Rate Limiting Configuration Error

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about How to Fix Exim Rate Limiting Configuration Error. We cover key concepts, practical examples, and best practices.

Exim rate limiting is not working — outgoing mail is not being limited even though ratelimit ACL is configured, or legitimate mail is being incorrectly rate-limited.

The Problem

# Rate limit configuration that doesn't work:
deny message = Rate limit exceeded
     ratelimit = 100 / 1h

Without specifying the per_ option, this rate limit counts all senders together.

Step-by-Step Fix

Step 1: Set per-mail-from rate limiting

# /etc/exim4/conf.d/acl/30_exim4-config_check_rcpt

# Rate limit per sender
deny message = Too many messages from you in the last hour
     ratelimit = 100 / 1h / per_mail / noreply

Step 2: Use per-address rate limiting

# Per recipient rate limit
acl_check_rcpt:
  deny message = Too many recipients from this sender
       ratelimit = 50 / 1h / per_addr

Step 3: Slow down instead of denying

# Defer (slow down) instead of deny
defer message = Please slow down, too many connections
     ratelimit = 20 / 1m / per_conn / strict

Step 4: Log rate limit events

warn log_message = Rate limit approaching for $sender_address
     ratelimit = 80 / 1h / per_mail / noreply

Step 5: Whitelist trusted senders

# Skip rate limiting for authenticated users
deny message = Rate limit exceeded
     condition = ${if !eq{$authenticated_id}{}}
     ratelimit = 1000 / 1h / per_mail

Step 6: Test rate limiting

for i in $(seq 1 10); do
  echo "Test $i" | mail -s "Test $i" recipient@example.com
done

Prevention Tips

  • Use per_mail for per-sender rate limiting
  • Combine noreply with warning logs to monitor approaching limits
  • Test rate limits in a staging environment first
  • Use defer instead of deny for temporary traffic spikes

Common Mistakes with ratelimit

  1. Using return to exit a function early instead of wrapping a pure value in the monad
  2. Mixing let bindings with <- bindings in do notation, producing type errors
  3. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors

These mistakes appear frequently in real-world EXIM code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Why is my Exim rate limit not working?

Rate limiting requires the ratelimit ACL condition in the check_rcpt or check_data ACL. Without specifying per_mail, per_conn, or per_what, the rate is counted globally. Add per_mail for per-sender limiting.

What is the difference between per_mail and per_conn in Exim rate limiting?

per_mail limits the number of messages from a sender within a time period. per_conn limits the number of connections from an IP. per_addr limits the number of recipients per sender. Use the appropriate type for your use case.

How do I set different rate limits for authenticated and unauthenticated senders?

Use a condition check: provide different ratelimit values based on $authenticated_id. Authenticated senders can have higher limits: ratelimit = 500 / 1h / per_mail vs unauthenticated ratelimit = 20 / 1h / per_mail.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro