68 lines
No EOL
2.3 KiB
Python
68 lines
No EOL
2.3 KiB
Python
import httpx
|
|
from app.workers.base_worker import BaseWorker
|
|
from app.job_registry import routing_key
|
|
from app.config import settings
|
|
from app.workers.utils import resolve_txt
|
|
|
|
class MTASTSWorker(BaseWorker):
|
|
async def process(self, payload: dict, **meta) -> dict:
|
|
domain = payload.get('domain')
|
|
if not domain:
|
|
raise ValueError('payload.domain is required')
|
|
txt_name = f"_mta-sts.{domain}"
|
|
txts = await resolve_txt(txt_name)
|
|
txt_policy = None
|
|
for t in txts:
|
|
if t.lower().startswith('v=stsv1'):
|
|
txt_policy = t
|
|
break
|
|
# Fetch policy file
|
|
url = f"https://mta-sts.{domain}/.well-known/mta-sts.txt"
|
|
policy = {
|
|
'version': None,
|
|
'mode': None,
|
|
'max_age': None,
|
|
'mx': [],
|
|
}
|
|
content = None
|
|
try:
|
|
timeout = httpx.Timeout(settings.HTTP_TIMEOUT)
|
|
async with httpx.AsyncClient(timeout=timeout) as client:
|
|
resp = await client.get(url)
|
|
if resp.status_code == 200:
|
|
content = resp.text
|
|
except Exception as e:
|
|
pass
|
|
if content:
|
|
for raw in content.splitlines():
|
|
line = raw.strip()
|
|
if not line or line.startswith('#'):
|
|
continue
|
|
if ':' in line:
|
|
k, v = [s.strip() for s in line.split(':', 1)]
|
|
lk = k.lower()
|
|
if lk == 'version':
|
|
policy['version'] = v
|
|
elif lk == 'mode':
|
|
policy['mode'] = v
|
|
elif lk == 'max_age':
|
|
try:
|
|
policy['max_age'] = int(v)
|
|
except ValueError:
|
|
policy['max_age'] = None
|
|
elif lk == 'mx':
|
|
policy['mx'].append(v)
|
|
return {
|
|
'txt_record': txt_policy,
|
|
'policy_url': url,
|
|
'policy': policy,
|
|
'has_policy': bool(policy['version']),
|
|
}
|
|
|
|
async def main():
|
|
worker = MTASTSWorker(routing_key("MailCheck", "MTASTSCheck"), worker_id="mtasts-worker-1")
|
|
await worker.run()
|
|
|
|
if __name__ == '__main__':
|
|
import asyncio as _a
|
|
_a.run(main()) |