diff --git a/Makefile b/Makefile index 67ff705..5867514 100644 --- a/Makefile +++ b/Makefile @@ -28,3 +28,6 @@ build: clean requirements.txt clean: rm -rf build rm -rf mail4one.pyz + +format: + black mail4one/*py diff --git a/mail4one/config.py b/mail4one/config.py index f929254..918bd85 100644 --- a/mail4one/config.py +++ b/mail4one/config.py @@ -56,13 +56,13 @@ class PopCfg(ServerCfg): class SmtpStartTLSCfg(ServerCfg): server_type = "smtp_starttls" - smtputf8 = True # Not used yet + smtputf8 = True # Not used yet port = 25 class SmtpCfg(ServerCfg): server_type = "smtp_starttls" - smtputf8 = True # Not used yet + smtputf8 = True # Not used yet port = 465 @@ -89,7 +89,6 @@ Checker = tuple[str, CheckerFn, bool] def parse_checkers(cfg: Config) -> list[Checker]: - def make_match_fn(m: Match): if m.addrs and m.addr_rexs: raise Exception("Both addrs and addr_rexs is set") @@ -97,8 +96,7 @@ def parse_checkers(cfg: Config) -> list[Checker]: return lambda malias: malias in m.addrs elif m.addr_rexs: compiled_res = [re.compile(reg) for reg in m.addr_rexs] - return lambda malias: any( - reg.match(malias) for reg in compiled_res) + return lambda malias: any(reg.match(malias) for reg in compiled_res) else: raise Exception("Neither addrs nor addr_rexs is set") @@ -114,13 +112,13 @@ def parse_checkers(cfg: Config) -> list[Checker]: return mbox_name, match_fn, rule.stop_check return [ - make_checker(mbox.name, Rule(rule)) for mbox in cfg.boxes or [] + make_checker(mbox.name, Rule(rule)) + for mbox in cfg.boxes or [] for rule in mbox.rules ] def get_mboxes(addr: str, checks: list[Checker]) -> list[str]: - def inner(): for mbox, match_fn, stop_check in checks: if match_fn(addr): diff --git a/mail4one/pop3.py b/mail4one/pop3.py index 8e5c25d..8d21b21 100644 --- a/mail4one/pop3.py +++ b/mail4one/pop3.py @@ -44,7 +44,6 @@ class State: class SharedState: - def __init__(self, mails_path: Path, users: dict[str, tuple[PWInfo, str]]): self.mails_path = mails_path self.users = users @@ -56,8 +55,7 @@ class SharedState: return self.counter -c_shared_state: contextvars.ContextVar = contextvars.ContextVar( - "pop_shared_state") +c_shared_state: contextvars.ContextVar = contextvars.ContextVar("pop_shared_state") def scfg() -> SharedState: @@ -72,7 +70,6 @@ def state() -> State: class PopLogger(logging.LoggerAdapter): - def __init__(self): super().__init__(logging.getLogger("pop3"), None) @@ -280,8 +277,7 @@ def get_deleted_items(deleted_items_path: Path) -> set[str]: return set() -def save_deleted_items(deleted_items_path: Path, - deleted_items: set[str]) -> None: +def save_deleted_items(deleted_items_path: Path, deleted_items: set[str]) -> None: with deleted_items_path.open(mode="w") as f: f.writelines(f"{did}\n" for did in deleted_items) @@ -298,8 +294,9 @@ async def transaction_stage() -> None: new_deleted_items: set[str] = await process_transactions(mails_list) logger.info(f"completed transactions. Deleted:{len(new_deleted_items)}") if new_deleted_items: - save_deleted_items(deleted_items_path, - existing_deleted_items.union(new_deleted_items)) + save_deleted_items( + deleted_items_path, existing_deleted_items.union(new_deleted_items) + ) logger.info(f"Saved deleted items") @@ -330,7 +327,6 @@ async def start_session() -> None: def parse_users(users: list[User]) -> dict[str, tuple[PWInfo, str]]: - def inner(): for user in users: user = User(user) @@ -340,15 +336,13 @@ def parse_users(users: list[User]) -> dict[str, tuple[PWInfo, str]]: return dict(inner()) -def make_pop_server_callback(mails_path: Path, users: list[User], - timeout_seconds: int): +def make_pop_server_callback(mails_path: Path, users: list[User], timeout_seconds: int): scfg = SharedState(mails_path=mails_path, users=parse_users(users)) async def session_cb(reader: StreamReader, writer: StreamWriter): c_shared_state.set(scfg) ip, _ = writer.get_extra_info("peername") - c_state.set( - State(reader=reader, writer=writer, ip=ip, req_id=scfg.next_id())) + c_state.set(State(reader=reader, writer=writer, ip=ip, req_id=scfg.next_id())) logger.info(f"Got pop server callback") try: try: diff --git a/mail4one/poputils.py b/mail4one/poputils.py index 5bb618b..c325ff1 100644 --- a/mail4one/poputils.py +++ b/mail4one/poputils.py @@ -86,7 +86,7 @@ def parse_command(bline: bytes) -> Request: if parts: request.arg2, *parts = parts if parts: - (request.rest, ) = parts + (request.rest,) = parts return request @@ -130,7 +130,6 @@ def get_mail(entry: MailEntry) -> bytes: class MailList: - def __init__(self, entries: list[MailEntry]): self.entries = entries set_nid(self.entries) diff --git a/mail4one/pwhash.py b/mail4one/pwhash.py index 01a3704..d8566c4 100644 --- a/mail4one/pwhash.py +++ b/mail4one/pwhash.py @@ -19,17 +19,13 @@ KEY_LEN = 64 # This is python default def gen_pwhash(password: str) -> str: salt = os.urandom(SALT_LEN) - sh = scrypt(password.encode(), - salt=salt, - n=SCRYPT_N, - r=SCRYPT_R, - p=SCRYPT_P, - dklen=KEY_LEN) + sh = scrypt( + password.encode(), salt=salt, n=SCRYPT_N, r=SCRYPT_R, p=SCRYPT_P, dklen=KEY_LEN + ) return b32encode(VERSION + salt + sh).decode() class PWInfo: - def __init__(self, salt: bytes, sh: bytes): self.salt = salt self.scrypt_hash = sh @@ -40,12 +36,13 @@ def parse_hash(pwhash_str: str) -> PWInfo: if not len(pwhash) == 1 + SALT_LEN + KEY_LEN: raise Exception( - f"Invalid hash size, {len(pwhash)} != {1 + SALT_LEN + KEY_LEN}") + f"Invalid hash size, {len(pwhash)} != {1 + SALT_LEN + KEY_LEN}" + ) if (ver := pwhash[0:1]) != VERSION: raise Exception(f"Invalid hash version, {ver!r} != {VERSION!r}") - salt, sh = pwhash[1:SALT_LEN + 1], pwhash[-KEY_LEN:] + salt, sh = pwhash[1 : SALT_LEN + 1], pwhash[-KEY_LEN:] return PWInfo(salt, sh) diff --git a/mail4one/server.py b/mail4one/server.py index 113f57d..72704ba 100644 --- a/mail4one/server.py +++ b/mail4one/server.py @@ -22,21 +22,22 @@ def create_tls_context(certfile, keyfile) -> ssl.SSLContext: def setup_logging(cfg: config.LogCfg): - logging_format = "%(asctime)s %(name)s %(levelname)s %(message)s @ %(filename)s:%(lineno)d" + logging_format = ( + "%(asctime)s %(name)s %(levelname)s %(message)s @ %(filename)s:%(lineno)d" + ) if cfg.logfile == "CONSOLE": logging.basicConfig(level=cfg.level, format=logging_format) else: - logging.basicConfig(filename=cfg.logfile, - level=cfg.level, - format=logging_format) + logging.basicConfig( + filename=cfg.logfile, level=cfg.level, format=logging_format + ) async def a_main(cfg: config.Config) -> None: default_tls_context: ssl.SSLContext | None = None if tls := cfg.default_tls: - logging.info( - f"Initializing default tls {tls.certfile=}, {tls.keyfile=}") + logging.info(f"Initializing default tls {tls.certfile=}, {tls.keyfile=}") default_tls_context = create_tls_context(tls.certfile, tls.keyfile) def get_tls_context(tls: config.TLSCfg | str): diff --git a/mail4one/smtp.py b/mail4one/smtp.py index 6f9ae3e..25ba5d6 100644 --- a/mail4one/smtp.py +++ b/mail4one/smtp.py @@ -25,15 +25,14 @@ logger = logging.getLogger("smtp") class MyHandler(AsyncMessage): - - def __init__(self, mails_path: Path, mbox_finder: Callable[[str], - list[str]]): + def __init__(self, mails_path: Path, mbox_finder: Callable[[str], list[str]]): super().__init__() self.mails_path = mails_path self.mbox_finder = mbox_finder - async def handle_DATA(self, server: SMTPServer, session: SMTPSession, - envelope: SMTPEnvelope) -> str: + async def handle_DATA( + self, server: SMTPServer, session: SMTPSession, envelope: SMTPEnvelope + ) -> str: self.rcpt_tos = envelope.rcpt_tos self.peer = session.peer return await super().handle_DATA(server, session, envelope) @@ -63,9 +62,9 @@ class MyHandler(AsyncMessage): ) -def protocol_factory_starttls(mails_path: Path, - mbox_finder: Callable[[str], list[str]], - context: ssl.SSLContext): +def protocol_factory_starttls( + mails_path: Path, mbox_finder: Callable[[str], list[str]], context: ssl.SSLContext +): logger.info("Got smtp client cb starttls") try: handler = MyHandler(mails_path, mbox_finder) @@ -81,8 +80,7 @@ def protocol_factory_starttls(mails_path: Path, return smtp -def protocol_factory(mails_path: Path, mbox_finder: Callable[[str], - list[str]]): +def protocol_factory(mails_path: Path, mbox_finder: Callable[[str], list[str]]): logger.info("Got smtp client cb") try: handler = MyHandler(mails_path, mbox_finder) @@ -105,8 +103,7 @@ async def create_smtp_server_starttls( ) loop = asyncio.get_event_loop() return await loop.create_server( - partial(protocol_factory_starttls, mails_path, mbox_finder, - ssl_context), + partial(protocol_factory_starttls, mails_path, mbox_finder, ssl_context), host=host, port=port, start_serving=False, diff --git a/mail4one/version.py b/mail4one/version.py index 799ec46..74b866f 100644 --- a/mail4one/version.py +++ b/mail4one/version.py @@ -1,2 +1 @@ - VERSION = "DEVELOMENT"