il-postino 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. il_postino-0.1.0/.gitignore +46 -0
  2. il_postino-0.1.0/LICENSE +21 -0
  3. il_postino-0.1.0/PKG-INFO +121 -0
  4. il_postino-0.1.0/README.md +86 -0
  5. il_postino-0.1.0/docs/superpowers/specs/2026-05-09-postino-design.md +691 -0
  6. il_postino-0.1.0/pyproject.toml +94 -0
  7. il_postino-0.1.0/scripts/check.sh +9 -0
  8. il_postino-0.1.0/src/postino/__init__.py +1 -0
  9. il_postino-0.1.0/src/postino/cli.py +129 -0
  10. il_postino-0.1.0/src/postino/commands/__init__.py +0 -0
  11. il_postino-0.1.0/src/postino/commands/alias.py +58 -0
  12. il_postino-0.1.0/src/postino/commands/check.py +31 -0
  13. il_postino-0.1.0/src/postino/commands/domain.py +76 -0
  14. il_postino-0.1.0/src/postino/commands/quota.py +37 -0
  15. il_postino-0.1.0/src/postino/commands/reconcile.py +9 -0
  16. il_postino-0.1.0/src/postino/commands/status.py +33 -0
  17. il_postino-0.1.0/src/postino/commands/user.py +159 -0
  18. il_postino-0.1.0/src/postino_core/__init__.py +1 -0
  19. il_postino-0.1.0/src/postino_core/check/__init__.py +0 -0
  20. il_postino-0.1.0/src/postino_core/check/consistency.py +103 -0
  21. il_postino-0.1.0/src/postino_core/config.py +123 -0
  22. il_postino-0.1.0/src/postino_core/db.py +40 -0
  23. il_postino-0.1.0/src/postino_core/enums.py +47 -0
  24. il_postino-0.1.0/src/postino_core/errors.py +37 -0
  25. il_postino-0.1.0/src/postino_core/fs.py +48 -0
  26. il_postino-0.1.0/src/postino_core/hooks.py +27 -0
  27. il_postino-0.1.0/src/postino_core/models.py +94 -0
  28. il_postino-0.1.0/src/postino_core/output.py +49 -0
  29. il_postino-0.1.0/src/postino_core/password.py +53 -0
  30. il_postino-0.1.0/src/postino_core/providers/__init__.py +0 -0
  31. il_postino-0.1.0/src/postino_core/providers/base.py +63 -0
  32. il_postino-0.1.0/src/postino_core/providers/local.py +69 -0
  33. il_postino-0.1.0/src/postino_core/quota.py +74 -0
  34. il_postino-0.1.0/src/postino_core/services/__init__.py +0 -0
  35. il_postino-0.1.0/src/postino_core/services/alias.py +100 -0
  36. il_postino-0.1.0/src/postino_core/services/bundle.py +84 -0
  37. il_postino-0.1.0/src/postino_core/services/domain.py +102 -0
  38. il_postino-0.1.0/src/postino_core/services/mailbox.py +257 -0
  39. il_postino-0.1.0/src/postino_core/services/quota.py +41 -0
  40. il_postino-0.1.0/tests/__init__.py +0 -0
  41. il_postino-0.1.0/tests/cli/__init__.py +0 -0
  42. il_postino-0.1.0/tests/cli/test_alias_cmd.py +34 -0
  43. il_postino-0.1.0/tests/cli/test_check_cmd.py +39 -0
  44. il_postino-0.1.0/tests/cli/test_domain_cmd.py +52 -0
  45. il_postino-0.1.0/tests/cli/test_user_cmd.py +126 -0
  46. il_postino-0.1.0/tests/conftest.py +77 -0
  47. il_postino-0.1.0/tests/fixtures/.gitkeep +0 -0
  48. il_postino-0.1.0/tests/fixtures/postfixadmin.sql +224 -0
  49. il_postino-0.1.0/tests/fixtures/sample_sql-virtual_mailbox_maps.cf +8 -0
  50. il_postino-0.1.0/tests/integration/__init__.py +0 -0
  51. il_postino-0.1.0/tests/integration/test_alias_service.py +79 -0
  52. il_postino-0.1.0/tests/integration/test_check.py +72 -0
  53. il_postino-0.1.0/tests/integration/test_domain_service.py +99 -0
  54. il_postino-0.1.0/tests/integration/test_local_provider.py +99 -0
  55. il_postino-0.1.0/tests/integration/test_mailbox_service.py +366 -0
  56. il_postino-0.1.0/tests/integration/test_quota_service.py +45 -0
  57. il_postino-0.1.0/tests/unit/__init__.py +0 -0
  58. il_postino-0.1.0/tests/unit/test_config_parser.py +65 -0
  59. il_postino-0.1.0/tests/unit/test_enums.py +39 -0
  60. il_postino-0.1.0/tests/unit/test_errors.py +39 -0
  61. il_postino-0.1.0/tests/unit/test_fs.py +36 -0
  62. il_postino-0.1.0/tests/unit/test_hooks.py +28 -0
  63. il_postino-0.1.0/tests/unit/test_models.py +136 -0
  64. il_postino-0.1.0/tests/unit/test_output.py +44 -0
  65. il_postino-0.1.0/tests/unit/test_password.py +43 -0
  66. il_postino-0.1.0/tests/unit/test_quota.py +55 -0
@@ -0,0 +1,46 @@
1
+ # Secrets
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+
6
+ # Python
7
+ __pycache__/
8
+ *.py[cod]
9
+ *$py.class
10
+ *.egg-info/
11
+ .eggs/
12
+ build/
13
+ dist/
14
+ *.whl
15
+
16
+ # Virtualenvs
17
+ .venv/
18
+ venv/
19
+ env/
20
+
21
+ # Testing
22
+ .pytest_cache/
23
+ .coverage
24
+ .coverage.*
25
+ htmlcov/
26
+ .tox/
27
+
28
+ # Type checkers
29
+ .pyright/
30
+ .mypy_cache/
31
+ .ruff_cache/
32
+
33
+ # Editor
34
+ .vscode/
35
+ .idea/
36
+ *.swp
37
+ *.swo
38
+ .DS_Store
39
+
40
+ # Local data
41
+ *.db
42
+ *.sqlite
43
+ *.sqlite3
44
+
45
+ # Worktrees
46
+ .worktrees/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marcello Barnaba
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.4
2
+ Name: il-postino
3
+ Version: 0.1.0
4
+ Summary: Typed Python CLI for administering Postfix + Dovecot mail servers (PostfixAdmin schema). Pluggable identity backend.
5
+ Project-URL: Homepage, https://github.com/vjt/postino
6
+ Project-URL: Issues, https://github.com/vjt/postino/issues
7
+ Author-email: Marcello Barnaba <marcello.barnaba@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: POSIX
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Communications :: Email
17
+ Classifier: Topic :: System :: Systems Administration
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.13
20
+ Requires-Dist: bcrypt<5,>=4.0
21
+ Requires-Dist: email-validator>=2.2
22
+ Requires-Dist: passlib>=1.7
23
+ Requires-Dist: pydantic-settings>=2.3
24
+ Requires-Dist: pydantic>=2.7
25
+ Requires-Dist: pymysql>=1.1
26
+ Requires-Dist: rich>=13.7
27
+ Requires-Dist: sqlalchemy>=2.0
28
+ Requires-Dist: typer>=0.12
29
+ Provides-Extra: dev
30
+ Requires-Dist: pyright>=1.1.370; extra == 'dev'
31
+ Requires-Dist: pytest-freezer>=0.4; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.5; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # postino
37
+
38
+ CLI tool to administer a Postfix + Dovecot mail server with the
39
+ PostfixAdmin SQL schema as user/alias/domain backend.
40
+
41
+ Pluggable identity backend (local password column or external IdP via
42
+ Zitadel/SCIM). Built for FreeBSD mail hosts but portable.
43
+
44
+ ## Status
45
+
46
+ MVP shipping. Design spec: [`docs/superpowers/specs/2026-05-09-postino-design.md`](docs/superpowers/specs/2026-05-09-postino-design.md).
47
+
48
+ Requires Python 3.13+.
49
+
50
+ ## Install
51
+
52
+ ```sh
53
+ pipx install il-postino
54
+ ```
55
+
56
+ Import name remains `postino`. The PyPI distribution is published as
57
+ `il-postino` because the bare `postino` name is squatted by an unrelated
58
+ 2017 package.
59
+
60
+ ### From git (mail host / production)
61
+
62
+ ```sh
63
+ git clone https://github.com/vjt/postino.git /usr/local/src/postino
64
+ cd /usr/local/src/postino
65
+ python3.13 -m venv .venv
66
+ . .venv/bin/activate
67
+ pip install .
68
+ ln -s /usr/local/src/postino/.venv/bin/postino /usr/local/bin/postino
69
+
70
+ # update later: cd /usr/local/src/postino && git pull && .venv/bin/pip install .
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ ```sh
76
+ # All commands inherit POSTINO_* env vars or read /usr/local/etc/postino/postino.toml
77
+
78
+ postino domain add example.com --max-mailboxes 100 --default-quota 5G
79
+ postino user add foo@example.com --password 'hunter2' --name "Foo Bar" --quota 5G
80
+ postino user list --domain example.com --json
81
+ postino alias add foo@example.com forwarded@elsewhere.test
82
+ postino quota show foo@example.com
83
+ postino check
84
+ postino status
85
+ ```
86
+
87
+ ## Configuration
88
+
89
+ postino reads `/usr/local/etc/postino/postino.toml`. Example:
90
+
91
+ ```toml
92
+ identity_backend = "local"
93
+ postfix_sql_dir = "/usr/local/etc/postfix"
94
+ virtual_mailbox_base = "/srv/mail"
95
+ postcreation_hook = "/usr/local/sbin/postfixadmin-mailbox-postcreation.sh"
96
+ vmail_uid = 1006
97
+ vmail_gid = 1006
98
+ default_password_scheme = "BLF-CRYPT"
99
+ default_quota_bytes = 1073741824
100
+ ```
101
+
102
+ DB credentials are NOT duplicated here — postino parses
103
+ `/usr/local/etc/postfix/sql-virtual_mailbox_maps.cf` to extract them.
104
+
105
+ ## Development
106
+
107
+ Set up a test MySQL/MariaDB schema (see
108
+ `docs/superpowers/plans/2026-05-09-postino-mvp.md` § Test Database
109
+ Prerequisites for the DDL), then:
110
+
111
+ ```sh
112
+ python3.13 -m venv .venv
113
+ . .venv/bin/activate
114
+ pip install -e '.[dev]'
115
+ export POSTINO_TEST_DB_URL='mysql+pymysql://postino_test:postino_test_dev@localhost/postino_test'
116
+ ./scripts/check.sh
117
+ ```
118
+
119
+ ## License
120
+
121
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,86 @@
1
+ # postino
2
+
3
+ CLI tool to administer a Postfix + Dovecot mail server with the
4
+ PostfixAdmin SQL schema as user/alias/domain backend.
5
+
6
+ Pluggable identity backend (local password column or external IdP via
7
+ Zitadel/SCIM). Built for FreeBSD mail hosts but portable.
8
+
9
+ ## Status
10
+
11
+ MVP shipping. Design spec: [`docs/superpowers/specs/2026-05-09-postino-design.md`](docs/superpowers/specs/2026-05-09-postino-design.md).
12
+
13
+ Requires Python 3.13+.
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ pipx install il-postino
19
+ ```
20
+
21
+ Import name remains `postino`. The PyPI distribution is published as
22
+ `il-postino` because the bare `postino` name is squatted by an unrelated
23
+ 2017 package.
24
+
25
+ ### From git (mail host / production)
26
+
27
+ ```sh
28
+ git clone https://github.com/vjt/postino.git /usr/local/src/postino
29
+ cd /usr/local/src/postino
30
+ python3.13 -m venv .venv
31
+ . .venv/bin/activate
32
+ pip install .
33
+ ln -s /usr/local/src/postino/.venv/bin/postino /usr/local/bin/postino
34
+
35
+ # update later: cd /usr/local/src/postino && git pull && .venv/bin/pip install .
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```sh
41
+ # All commands inherit POSTINO_* env vars or read /usr/local/etc/postino/postino.toml
42
+
43
+ postino domain add example.com --max-mailboxes 100 --default-quota 5G
44
+ postino user add foo@example.com --password 'hunter2' --name "Foo Bar" --quota 5G
45
+ postino user list --domain example.com --json
46
+ postino alias add foo@example.com forwarded@elsewhere.test
47
+ postino quota show foo@example.com
48
+ postino check
49
+ postino status
50
+ ```
51
+
52
+ ## Configuration
53
+
54
+ postino reads `/usr/local/etc/postino/postino.toml`. Example:
55
+
56
+ ```toml
57
+ identity_backend = "local"
58
+ postfix_sql_dir = "/usr/local/etc/postfix"
59
+ virtual_mailbox_base = "/srv/mail"
60
+ postcreation_hook = "/usr/local/sbin/postfixadmin-mailbox-postcreation.sh"
61
+ vmail_uid = 1006
62
+ vmail_gid = 1006
63
+ default_password_scheme = "BLF-CRYPT"
64
+ default_quota_bytes = 1073741824
65
+ ```
66
+
67
+ DB credentials are NOT duplicated here — postino parses
68
+ `/usr/local/etc/postfix/sql-virtual_mailbox_maps.cf` to extract them.
69
+
70
+ ## Development
71
+
72
+ Set up a test MySQL/MariaDB schema (see
73
+ `docs/superpowers/plans/2026-05-09-postino-mvp.md` § Test Database
74
+ Prerequisites for the DDL), then:
75
+
76
+ ```sh
77
+ python3.13 -m venv .venv
78
+ . .venv/bin/activate
79
+ pip install -e '.[dev]'
80
+ export POSTINO_TEST_DB_URL='mysql+pymysql://postino_test:postino_test_dev@localhost/postino_test'
81
+ ./scripts/check.sh
82
+ ```
83
+
84
+ ## License
85
+
86
+ MIT — see [LICENSE](LICENSE).