c3lf-system-3/core/mail/protocol.py

70 lines
2.4 KiB
Python
Raw Normal View History

2023-11-27 00:38:43 +00:00
import logging
import aiosmtplib
def make_reply(message, to, subject):
from email.message import EmailMessage
from core.settings import MAIL_DOMAIN
reply = EmailMessage()
reply["From"] = "noreply@" + MAIL_DOMAIN
reply["To"] = to
reply["Subject"] = subject
reply.set_content(message)
return reply
async def send_smtp(message, log):
log.info('Sending message to %s' % message['To'])
await aiosmtplib.send(message, hostname="127.0.0.1", port=25, use_tls=False, start_tls=False)
class LMTPHandler:
async def handle_RCPT(self, server, session, envelope, address, rcpt_options):
from core.settings import MAIL_DOMAIN
if not address.endswith('@' + MAIL_DOMAIN):
return '550 not relaying to that domain'
envelope.rcpt_tos.append(address)
return '250 OK'
async def handle_DATA(self, server, session, envelope):
import email
log = logging.getLogger('mail.log')
log.info('Message from %s' % envelope.mail_from)
log.info('Message for %s' % envelope.rcpt_tos)
log.info('Message data:\n')
try:
parsed = email.message_from_bytes(envelope.content)
body = ""
if parsed.is_multipart():
for part in parsed.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
# skip any text/plain (txt) attachments
if ctype == 'text/plain' and 'attachment' not in cdispo:
body = part.get_payload(decode=True)
else:
log.info("Attachment", ctype, cdispo)
else:
body = parsed.get_payload(decode=True)
log.info(body)
header_from = parsed.get('From')
header_to = parsed.get('To')
if header_from != envelope.mail_from:
log.warning("Header from does not match envelope from")
if header_to != envelope.rcpt_tos[0]:
log.warning("Header to does not match envelope to")
await send_smtp(make_reply("Thank you for your message.", envelope.mail_from, 'Message received'), log)
log.info("Sent reply")
return '250 Message accepted for delivery'
except Exception as e:
log.error(e)
return '550 Message rejected'