On 07/03/19, Jeremy Harris via Exim-users (exim-users@???) wrote:
> There's a page on the wiki with some ideas on rate limiting outbound. It is unfortunately much harder than rate limiting inbound in Exim.
Thanks Jeremy
I glanced at the page.
https://github.com/Exim/exim/wiki/RatelimitOutbound
mentions "redirect supplied by an acl expansion" or "msg:delivery Event"
or a queue-runner methodology.
While the first looks quite interesting I've made my sketch in the
previous email work. It is an external programme linked to a very simple
sqlite database recording day | domain | counter. It seems to work, as a
first router on a stock Debian setup.
dns_warmup:
debug_print = "R: dns_warmup for $local_part@$domain"
driver = dnslookup
domains = aol.com : yahoo.com # ... etc ...
transport = remote_smtp
same_domain_copy_routing = no
condition = ${run{/fullpath/exim_domain_warmup.py "$domain"}{yes}{no}}
no_more
I'm using the script below in case anyone finds it useful.
Thanks
Rory
-- begin script --
#!/usr/bin/python
""" exim_domain_warmup.py """
import sqlite3
import sys
from datetime import datetime
# settings
dbname = 'domain_count.db'
STARTDATE = '2019-03-07' # start date for sending
STARTEMAILS = 4 # number of start emails to send per domain
# calculate dates
datefmt = ("%Y-%m-%d")
datestart = datetime.strptime(STARTDATE, datefmt)
today = datetime.today()
todaystr = today.strftime(datefmt)
datedelta = today - datestart
DAYDELTA = datedelta.days + 1
def day_mail_limit(startemails=STARTEMAILS, days=DAYDELTA):
"""
Work out how many emails to send based on the start amount of emails
and days elapsed since the start date
"""
if days < 1:
return False
# 25 : 50 : 100 etc
return startemails * (2 ** (days-1))
def dbinit():
"""database table init"""
conn = sqlite3.connect(dbname, timeout=3)
conn.execute(r'''
CREATE TABLE IF NOT EXISTS domaincounter (
dater TEXT, domain TEXT, counter INT
)
''')
conn.commit()
def domain_check(domain):
"""
Check if the domain is in the db, against today
"""
# work out current day limits
domainlimit = day_mail_limit()
if not domainlimit:
return False
conn = sqlite3.connect(dbname, timeout=3)
q = conn.execute(r'''SELECT * FROM domaincounter WHERE dater=? AND domain=?''',
(todaystr, domain))
r = q.fetchone()
if not r:
conn.execute(r'''INSERT INTO domaincounter VALUES (?, ?, ?)''',
(todaystr, domain, 1)
)
conn.commit()
return True
else:
# if over limit return
if r[2] >= domainlimit:
conn.commit()
return False
# update record
conn.execute(r'''
UPDATE domaincounter SET dater=?, domain=?, counter=?
WHERE dater=? AND domain=?''',
(todaystr, domain, r[2] + 1, todaystr, domain))
conn.commit()
return True
if __name__ == '__main__':
# read sys.argv1 (domain name from exim)
try:
domain = sys.argv[1]
except:
sys.exit(1)
# dbinit()
dc = domain_check(domain)
if not dc:
sys.exit(1)
else:
sys.exit(0)