63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
import asyncio
|
|
import io
|
|
import logging
|
|
import mailbox
|
|
import ssl
|
|
from functools import partial
|
|
from pathlib import Path
|
|
|
|
from aiosmtpd.handlers import Mailbox
|
|
from aiosmtpd.smtp import SMTP, DATA_SIZE_DEFAULT
|
|
|
|
|
|
class MaildirCRLF(mailbox.Maildir):
|
|
_append_newline = True
|
|
|
|
def _dump_message(self, message, target, mangle_from_=False):
|
|
temp_buffer = io.BytesIO()
|
|
super()._dump_message(message, temp_buffer, mangle_from_=mangle_from_)
|
|
temp_buffer.seek(0)
|
|
data = temp_buffer.read()
|
|
data = data.replace(b'\n', b'\r\n')
|
|
target.write(data)
|
|
|
|
|
|
class MailboxCRLF(Mailbox):
|
|
def __init__(self, mail_dir: Path):
|
|
super().__init__(mail_dir)
|
|
for sub in ('new', 'tmp', 'cur'):
|
|
sub_path = mail_dir / sub
|
|
sub_path.mkdir(mode=0o755, exist_ok=True, parents=True)
|
|
self.mailbox = MaildirCRLF(mail_dir)
|
|
|
|
|
|
def protocol_factory(dirpath: Path, context: ssl.SSLContext = None):
|
|
logging.info("Got smtp client cb")
|
|
try:
|
|
handler = MailboxCRLF(dirpath)
|
|
smtp = SMTP(handler=handler,
|
|
require_starttls=True,
|
|
tls_context=context,
|
|
data_size_limit=DATA_SIZE_DEFAULT,
|
|
enable_SMTPUTF8=True)
|
|
except Exception as e:
|
|
logging.error("Something went wrong", e)
|
|
raise
|
|
return smtp
|
|
|
|
|
|
async def create_smtp_server(dirpath: Path, port: int, host="", context: ssl.SSLContext = None):
|
|
loop = asyncio.get_event_loop()
|
|
return await loop.create_server(partial(protocol_factory, dirpath, context),
|
|
host=host, port=port, start_serving=False)
|
|
|
|
|
|
async def a_main(*args, **kwargs):
|
|
server = await create_smtp_server(*args, **kwargs)
|
|
await server.serve_forever()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
asyncio.run(a_main(Path("/tmp/mails"), 9995))
|