2021-03-17 10:07:13 +01:00
|
|
|
import asyncio
|
|
|
|
import time
|
|
|
|
from email.message import Message
|
|
|
|
|
|
|
|
import aiospamc
|
|
|
|
|
|
|
|
from app.config import SPAMASSASSIN_HOST
|
|
|
|
from app.log import LOG
|
2022-04-28 14:43:24 +02:00
|
|
|
from app.message_utils import message_to_bytes
|
2021-03-17 10:07:13 +01:00
|
|
|
from app.models import EmailLog
|
|
|
|
from app.spamassassin_utils import SpamAssassin
|
|
|
|
|
|
|
|
|
|
|
|
async def get_spam_score_async(message: Message) -> float:
|
2022-04-28 14:43:24 +02:00
|
|
|
sa_input = message_to_bytes(message)
|
2021-03-17 10:07:13 +01:00
|
|
|
|
|
|
|
# Spamassassin requires to have an ending linebreak
|
|
|
|
if not sa_input.endswith(b"\n"):
|
|
|
|
LOG.d("add linebreak to spamassassin input")
|
|
|
|
sa_input += b"\n"
|
|
|
|
|
|
|
|
try:
|
|
|
|
# wait for at max 300s which is the default spamd timeout-child
|
|
|
|
response = await asyncio.wait_for(
|
|
|
|
aiospamc.check(sa_input, host=SPAMASSASSIN_HOST), timeout=300
|
|
|
|
)
|
|
|
|
return response.headers["Spam"].score
|
|
|
|
except asyncio.TimeoutError:
|
|
|
|
LOG.e("SpamAssassin timeout")
|
|
|
|
# return a negative score so the message is always considered as ham
|
|
|
|
return -999
|
|
|
|
except Exception:
|
|
|
|
LOG.e("SpamAssassin exception")
|
|
|
|
return -999
|
|
|
|
|
|
|
|
|
|
|
|
def get_spam_score(
|
|
|
|
message: Message, email_log: EmailLog, can_retry=True
|
|
|
|
) -> (float, dict):
|
|
|
|
"""
|
|
|
|
Return the spam score and spam report
|
|
|
|
"""
|
|
|
|
LOG.d("get spam score for %s", email_log)
|
2022-04-28 14:43:24 +02:00
|
|
|
sa_input = message_to_bytes(message)
|
2021-03-17 10:07:13 +01:00
|
|
|
|
|
|
|
# Spamassassin requires to have an ending linebreak
|
|
|
|
if not sa_input.endswith(b"\n"):
|
|
|
|
LOG.d("add linebreak to spamassassin input")
|
|
|
|
sa_input += b"\n"
|
|
|
|
|
|
|
|
try:
|
|
|
|
# wait for at max 300s which is the default spamd timeout-child
|
|
|
|
sa = SpamAssassin(sa_input, host=SPAMASSASSIN_HOST, timeout=300)
|
|
|
|
return sa.get_score(), sa.get_report_json()
|
|
|
|
except Exception:
|
|
|
|
if can_retry:
|
|
|
|
LOG.w("SpamAssassin exception, retry")
|
|
|
|
time.sleep(3)
|
|
|
|
return get_spam_score(message, email_log, can_retry=False)
|
|
|
|
else:
|
|
|
|
# return a negative score so the message is always considered as ham
|
2021-09-08 11:29:55 +02:00
|
|
|
LOG.e("SpamAssassin exception, ignore spam check")
|
2021-03-17 10:07:13 +01:00
|
|
|
return -999, None
|