fix syntax errors and format

This commit is contained in:
Balakrishnan Balasubramanian 2023-06-03 20:34:13 -04:00
parent 5600d30f54
commit 5cdf36fe32
4 changed files with 41 additions and 78 deletions

View File

@ -33,6 +33,7 @@ class Config(Jata):
smtp_port_tls = 465
smtp_port_submission = 587
pop_port = 995
pop_timeout_seconds = 60
smtputf8 = True
rules: list[Rule]
boxes: list[Mbox]

View File

@ -8,44 +8,13 @@ from hashlib import sha256
from pathlib import Path
from typing import ClassVar, List, Set
from .config import User
from .pwhash import parse_hash, check_pass
from .pwhash import parse_hash, check_pass, PWInfo
from asyncio import StreamReader, StreamWriter
from .poputils import InvalidCommand, parse_command, err, Command, ClientQuit, ClientError, AuthError, ok, msg, end, \
Request, MailEntry, get_mail, get_mails_list, MailList
def add_season(content: bytes, season: bytes):
return sha256(season + content).digest()
# noinspection PyProtectedMember
@dataclass
class Session:
_reader: StreamReader
_writer: asyncio.StreamWriter
username: str
mbox: str
# common state
all_sessions: ClassVar[Set] = set()
mails_path: ClassVar[Path] = Path("")
users: ClassVar[list[User]] = list()
current_session: ClassVar = ContextVar("session")
@classmethod
def get(cls):
return cls.current_session.get()
@classmethod
def reader(cls):
return cls.get()._reader
@classmethod
def writer(cls):
return cls.get()._writer
async def next_req():
for _ in range(InvalidCommand.RETRIES):
line = await state().reader.readline()
@ -254,12 +223,13 @@ async def start_session():
assert username is not None
config().loggedin_users.add(username)
_, mbox = config().users[username]
deleted_items_path = config().mails_path/ mbox / username
deleted_items_path = config().mails_path / mbox / username
logging.info(f"User:{username} logged in successfully")
existing_deleted_items: Set = get_deleted_items(deleted_items_path)
new_deleted_items: Set = await transaction_stage(existing_deleted_items)
new_deleted_items: Set = await transaction_stage(existing_deleted_items
)
logging.info(
f"{username=} completed transactions. Deleted:{len(new_deleted_items)}"
)
@ -300,11 +270,12 @@ class State:
mbox: str = ""
@dataclass
class Config:
mails_path: Path
users: dict[str, tuple[pwhash.PWInfo, str]]
loggedin_users: set[str] = set()
def __init__(self, mails_path: Path, users: dict[str, tuple[PWInfo, str]]):
self.mails_path = mails_path
self.users = users
self.loggedin_users: set[str] = set()
c_config = contextvars.ContextVar('config')
@ -336,11 +307,11 @@ def make_pop_server_callback(dirpath: Path, users: list[User],
return session_cb
async def create_pop_server(dirpath: Path,
async def create_pop_server(host: str,
port: int,
mails_path: Path,
users: list[User],
host="",
context: ssl.SSLContext = None,
ssl_context: ssl.SSLContext = None,
timeout_seconds: int = 60):
logging.info(
f"Starting POP3 server {dirpath=}, {host=}, {port=}, {timeout_seconds=}, ssl={context != None}"

View File

@ -1,8 +1,4 @@
import asyncio
# Though we don't use requests, without the below import, we crash https://stackoverflow.com/a/13057751
# When running on privilege port after dropping privileges.
# noinspection PyUnresolvedReferences
import encodings.idna
import logging
import os
import ssl
@ -22,27 +18,6 @@ def create_tls_context(certfile, keyfile):
return context
def parse_args():
parser = ArgumentParser()
parser.add_argument('--certfile')
parser.add_argument('--keyfile')
parser.add_argument('--password_hash')
parser.add_argument("mail_dir_path")
args = parser.parse_args()
args.mail_dir_path = Path(args.mail_dir_path)
# Hardcoded args
args.host = '0.0.0.0'
args.smtp_port = 25
args.smtp_port_tls = 465
args.smtp_port_submission = 587
args.pop_port = 995
args.smtputf8 = True
args.debug = True
return args
def setup_logging(args):
if args.debug:
logging.basicConfig(level=logging.DEBUG)
@ -51,11 +26,13 @@ def setup_logging(args):
async def a_main(config, tls_context):
pop_server = await create_pop_server(config.mails_path,
port=config.pop_port,
host=config.host,
context=tls_context,
users=config.users)
pop_server = await create_pop_server(
host=config.host,
port=config.pop_port,
mails_path=config.mails_path,
users=config.users,
ssl_context=tls_context,
timeout_seconds=config.pop_timeout_seconds)
smtp_server_starttls = await create_smtp_server_starttls(
config.mail_dir_path,
@ -74,7 +51,6 @@ async def a_main(config, tls_context):
def main():
config_path = sys.argv[1]
parser = ArgumentParser()
parser.add_argument("config_path")
args = parser.parse_args()

View File

@ -23,6 +23,7 @@ class MaildirCRLF(mailbox.Maildir):
class MailboxCRLF(Mailbox):
def __init__(self, mail_dir: Path):
super().__init__(mail_dir)
for sub in ('new', 'tmp', 'cur'):
@ -50,23 +51,37 @@ def protocol_factory(dirpath: Path):
logging.info("Got smtp client cb")
try:
handler = MailboxCRLF(dirpath)
smtp = SMTP(handler=handler, data_size_limit=DATA_SIZE_DEFAULT, enable_SMTPUTF8=True)
smtp = SMTP(handler=handler,
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_starttls(dirpath: Path, port: int, host="", context: ssl.SSLContext = None):
async def create_smtp_server_starttls(dirpath: Path,
port: int,
host="",
context: ssl.SSLContext = None):
loop = asyncio.get_event_loop()
return await loop.create_server(partial(protocol_factory_starttls, dirpath, context),
host=host, port=port, start_serving=False)
return await loop.create_server(partial(protocol_factory_starttls, dirpath,
context),
host=host,
port=port,
start_serving=False)
async def create_smtp_server_tls(dirpath: Path, port: int, host="", context: ssl.SSLContext = None):
async def create_smtp_server_tls(dirpath: Path,
port: int,
host="",
context: ssl.SSLContext = None):
loop = asyncio.get_event_loop()
return await loop.create_server(partial(protocol_factory, dirpath),
host=host, port=port, ssl=context, start_serving=False)
host=host,
port=port,
ssl=context,
start_serving=False)
async def a_main(*args, **kwargs):