mirror of
				https://github.com/simple-login/app.git
				synced 2025-11-04 04:58:25 +08:00 
			
		
		
		
	move get_spam_score_async(), get_spam_score() to email/spam.py
This commit is contained in:
		
							parent
							
								
									f6d3172e3e
								
							
						
					
					
						commit
						d1d81e6a6d
					
				
					 3 changed files with 64 additions and 55 deletions
				
			
		
							
								
								
									
										0
									
								
								app/email/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/email/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										63
									
								
								app/email/spam.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								app/email/spam.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
import asyncio
 | 
			
		||||
import time
 | 
			
		||||
from email.message import Message
 | 
			
		||||
 | 
			
		||||
import aiospamc
 | 
			
		||||
 | 
			
		||||
from app.config import SPAMASSASSIN_HOST
 | 
			
		||||
from app.email_utils import to_bytes
 | 
			
		||||
from app.log import LOG
 | 
			
		||||
from app.models import EmailLog
 | 
			
		||||
from app.spamassassin_utils import SpamAssassin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def get_spam_score_async(message: Message) -> float:
 | 
			
		||||
    sa_input = to_bytes(message)
 | 
			
		||||
 | 
			
		||||
    # 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)
 | 
			
		||||
    sa_input = to_bytes(message)
 | 
			
		||||
 | 
			
		||||
    # 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
 | 
			
		||||
            LOG.exception("SpamAssassin exception, ignore spam check")
 | 
			
		||||
            return -999, None
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,6 @@ It should contain the following info:
 | 
			
		|||
 | 
			
		||||
"""
 | 
			
		||||
import argparse
 | 
			
		||||
import asyncio
 | 
			
		||||
import email
 | 
			
		||||
import time
 | 
			
		||||
import uuid
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +44,6 @@ from io import BytesIO
 | 
			
		|||
from smtplib import SMTP, SMTPRecipientsRefused, SMTPServerDisconnected
 | 
			
		||||
from typing import List, Tuple, Optional
 | 
			
		||||
 | 
			
		||||
import aiospamc
 | 
			
		||||
import arrow
 | 
			
		||||
import spf
 | 
			
		||||
from aiosmtpd.controller import Controller
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +81,7 @@ from app.config import (
 | 
			
		|||
    POSTFIX_PORT_FORWARD,
 | 
			
		||||
    NOT_SEND_EMAIL,
 | 
			
		||||
)
 | 
			
		||||
from app.email.spam import get_spam_score
 | 
			
		||||
from app.email_utils import (
 | 
			
		||||
    send_email,
 | 
			
		||||
    add_dkim_signature,
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +124,6 @@ from app.models import (
 | 
			
		|||
    TransactionalEmail,
 | 
			
		||||
)
 | 
			
		||||
from app.pgp_utils import PGPException, sign_data_with_pgpy, sign_data
 | 
			
		||||
from app.spamassassin_utils import SpamAssassin
 | 
			
		||||
from app.utils import sanitize_email
 | 
			
		||||
from init_app import load_pgp_public_keys
 | 
			
		||||
from server import create_app, create_light_app
 | 
			
		||||
| 
						 | 
				
			
			@ -1672,58 +1670,6 @@ def handle_bounce(envelope, rcpt_to) -> str:
 | 
			
		|||
        return "550 SL E26 Email cannot be forwarded to mailbox"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def get_spam_score_async(message: Message) -> float:
 | 
			
		||||
    sa_input = to_bytes(message)
 | 
			
		||||
 | 
			
		||||
    # 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)
 | 
			
		||||
    sa_input = to_bytes(message)
 | 
			
		||||
 | 
			
		||||
    # 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
 | 
			
		||||
            LOG.exception("SpamAssassin exception, ignore spam check")
 | 
			
		||||
            return -999, None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def sl_sendmail(
 | 
			
		||||
    from_addr,
 | 
			
		||||
    to_addr,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue