Skip to content

Commit

Permalink
Merge branch 'main' into hagi/#306-disable-ipv6
Browse files Browse the repository at this point in the history
  • Loading branch information
missytake authored Jul 28, 2024
2 parents 9c58100 + 89c65d3 commit 6f0429b
Show file tree
Hide file tree
Showing 25 changed files with 537 additions and 382 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## untagged

- Migrate and remove sqlite database in favor of password/lastlogin tracking
in a user's maildir. This removes the need for "passdb" setting in ini file
which was introduced through #351 below.
([#379](https://github.com/deltachat/chatmail/pull/379))

- BREAKING: new required chatmail.ini values:

mailboxes_dir = /home/vmail/mail/{mail_domain}
Expand Down
1 change: 1 addition & 0 deletions chatmaild/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ filtermail = "chatmaild.filtermail:main"
echobot = "chatmaild.echo:main"
chatmail-metrics = "chatmaild.metrics:main"
delete_inactive_users = "chatmaild.delete_inactive_users:main"
lastlogin = "chatmaild.lastlogin:main"

[project.entry-points.pytest11]
"chatmaild.testplugin" = "chatmaild.tests.plugin"
Expand Down
21 changes: 15 additions & 6 deletions chatmaild/src/chatmaild/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import iniconfig

from chatmaild.user import User

echobot_password_path = Path("/run/echobot/password")


def read_config(inipath):
assert Path(inipath).exists(), inipath
Expand Down Expand Up @@ -39,12 +43,17 @@ def __init__(self, inipath, params):
def _getbytefile(self):
return open(self._inipath, "rb")

def get_user_maildir(self, addr):
if addr and addr != "." and "/" not in addr:
res = self.mailboxes_dir.joinpath(addr).resolve()
if res.is_relative_to(self.mailboxes_dir):
return res
raise ValueError(f"invalid address {addr!r}")
def get_user(self, addr):
if not addr or "@" not in addr or "/" in addr:
raise ValueError(f"invalid address {addr!r}")

maildir = self.mailboxes_dir.joinpath(addr)
if addr.startswith("echo@"):
password_path = echobot_password_path
else:
password_path = maildir.joinpath("password")

return User(maildir, addr, password_path, uid="vmail", gid="vmail")


def write_initial_config(inipath, mail_domain, overrides):
Expand Down
133 changes: 0 additions & 133 deletions chatmaild/src/chatmaild/database.py

This file was deleted.

28 changes: 13 additions & 15 deletions chatmaild/src/chatmaild/delete_inactive_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,30 @@
Remove inactive users
"""

import os
import shutil
import sys
import time

from .config import read_config
from .database import Database
from .doveauth import iter_userdb_lastlogin_before


def delete_inactive_users(db, config, CHUNK=100):
def delete_inactive_users(config):
cutoff_date = time.time() - config.delete_inactive_users_after * 86400
for addr in os.listdir(config.mailboxes_dir):
try:
user = config.get_user(addr)
except ValueError:
continue

old_users = iter_userdb_lastlogin_before(db, cutoff_date)
chunks = (old_users[i : i + CHUNK] for i in range(0, len(old_users), CHUNK))
for sublist in chunks:
for user in sublist:
user_mail_dir = config.get_user_maildir(user)
shutil.rmtree(user_mail_dir, ignore_errors=True)

with db.write_transaction() as conn:
for user in sublist:
conn.execute("DELETE FROM users WHERE addr = ?", (user,))
read_timestamp = user.get_last_login_timestamp()
if read_timestamp and read_timestamp < cutoff_date:
path = config.mailboxes_dir.joinpath(addr)
assert path == user.maildir
shutil.rmtree(path, ignore_errors=True)


def main():
(cfgpath,) = sys.argv[1:]
config = read_config(cfgpath)
db = Database(config.passdb_path)
delete_inactive_users(db, config)
delete_inactive_users(config)
Loading

0 comments on commit 6f0429b

Please sign in to comment.