pysmtp/mayordomo/resolver.py

133 lines
4.2 KiB
Python
Raw Normal View History

2021-12-28 03:01:00 -03:00
# coding: utf-8
import traceback
import asyncio
import time
import os
from async_dns.core import types, Address
from async_dns.resolver import DNSClient
from sqlalchemy.future import select
from .model import db, update_mx, update_a, FQDN, MXRecord, ARecord, IPV4Addr, Direccion, Destinatario
from .registro import log
if not os.environ.get('DNS_RELAY'):
dns_relay = '192.168.0.1'
else:
dns_relay = os.environ.get('DNS_RELAY')
async def updateDNS():
pendientes = 0
destinos = 0
2021-12-28 03:01:00 -03:00
# await log.debug('Updatedns')
try:
rdestino = await db.execute(select(Destinatario).join(Direccion).join(FQDN).where(Destinatario.enviado==0).distinct(FQDN.id))
for destinatario in rdestino.scalars():
result = await db.execute(select(Direccion).where(Direccion.id==destinatario.direccionid))
dbemail = result.scalar_one_or_none()
destinos += 1
2021-12-28 03:01:00 -03:00
tieneMXValido = False
valido = int(time.time())
retries = 3
while tiemeMXValido is False and retries > 0:
retries -= 1
dbmx = await db.execute(select(MXRecord).where(MXRecord.fqdnid==dbemail.dominioid))
for mx_record in dbmx.scalars():
if mx_record.validohasta > valido:
tieneMXValido = True
break
if tiemeMXValido is False:
updateExitoso = updateExitoso and await servidores_correo(dbemail.dominioid)
if retries <= 0:
await log.error('Error al actualizar los servidores MX de {}'.format(dbemail.direccion))
pendientes += 1
2021-12-28 03:01:00 -03:00
except:
await log.error('Traceback {}'.format(traceback.format_exc()))
if destinos>0 and pendientes == 0:
await log.info('Todos los servidores MX estan disponibles para enviar los correos')
elif destinos>0 and pendientes>0:
await log.info('Algunos servidores MX no pudieron resolverse')
2021-12-28 03:01:00 -03:00
if destinos > pendientes:
return True #hay correos que mandar
else:
return False #nada que hacer
2021-12-28 03:01:00 -03:00
async def servidores_correo(dominioid):
try:
result = await db.execute(select(FQDN).where(FQDN.id==dominioid))
dominio = result.scalar_one_or_none()
servidores = await resolver(types.MX, dominio.fqdn)
except:
# await log.error('Traceback {}'.format(traceback.format_exc()))
await log.error("No se pudo resolver los servidores de correo de '{}'".format(dominio.fqdn))
return False
2021-12-28 03:01:00 -03:00
await log.info("Actualizando los servidores de correo de: {}".format(dominio.fqdn))
for host in servidores:
typename = host.data.type_name
prioridad, fqdn = host.data.data
tiempo = int(time.time())+10 #add the 10, because of the sleep delay
2021-12-28 03:01:00 -03:00
validohasta = tiempo
try:
direcciones = await resolver(types.A, fqdn)
except:
# await log.error('Traceback {}'.format(traceback.format_exc()))
# await log.debug("No se pudo resolver la dirección A => {}".format(fqdn))
continue
dbmx = await update_mx(dominio.id, fqdn, prioridad)
# await log.debug("Servidor {}: '{}' prioridad {} validohasta: {}".format(typename, fqdn, prioridad, dbmx.validohasta))
for direccion in direcciones:
if direccion.qtype == types.A:
ttl = direccion.ttl + tiempo
typename = direccion.data.type_name
ipv4 = direccion.data.data
if ttl > validohasta:
validohasta = ttl
await update_a(dbmx.fqdnmxid, ipv4, ttl)
# await log.debug("Dirección {}: '{}' TTL {} (time:{}, ttl:{})".format(typename, ipv4, ttl, tiempo, direccion.ttl))
dbmx.validohasta = validohasta
await db.commit()
return True
2021-12-28 03:01:00 -03:00
# await log.debug("Servidor {}: '{}' prioridad {} validohasta: {}".format(typename, fqdn, prioridad, dbmx.validohasta))
async def resolver(tipo=types.A, fqdn='ilab.cl'):
client = DNSClient()
retry = 10
while retry > 0:
try:
return await client.query(fqdn, tipo, Address.parse(dns_relay))
# for valor in res:
# await log.debug('valor => {}'.format(valor))
# typename = valor.data.type_name
# if tipo == types.A:
# fqdn = valor.data.data
# await log.debug('data => {}'.format(fqdn))
# else:
# await log.debug('data => {}'.format(valor.data))
# prioridad, fqdn = valor.data.data
# return res
2021-12-28 03:01:00 -03:00
except asyncio.exceptions.TimeoutError:
retry = retry - 1
log.warning(u'Quedan {} intentos'.format(retry))
2021-12-28 03:01:00 -03:00
continue
raise asyncio.exceptions.TimeoutError('Intentos excedidos')