mailmail 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 (41) hide show
  1. mailmail-0.1.0/.github/dependabot.yml +17 -0
  2. mailmail-0.1.0/.github/workflows/check.yml +117 -0
  3. mailmail-0.1.0/.github/workflows/publish.yml +34 -0
  4. mailmail-0.1.0/.gitignore +22 -0
  5. mailmail-0.1.0/LICENSE +21 -0
  6. mailmail-0.1.0/PKG-INFO +487 -0
  7. mailmail-0.1.0/README.ko.md +424 -0
  8. mailmail-0.1.0/README.md +458 -0
  9. mailmail-0.1.0/pyproject.toml +80 -0
  10. mailmail-0.1.0/scripts/check_blocked_list.py +85 -0
  11. mailmail-0.1.0/skills/send/SKILL.md +214 -0
  12. mailmail-0.1.0/src/mailmail/__init__.py +268 -0
  13. mailmail-0.1.0/src/mailmail/__main__.py +11 -0
  14. mailmail-0.1.0/src/mailmail/account.py +31 -0
  15. mailmail-0.1.0/src/mailmail/attachment.py +593 -0
  16. mailmail-0.1.0/src/mailmail/cli.py +358 -0
  17. mailmail-0.1.0/src/mailmail/config.py +229 -0
  18. mailmail-0.1.0/src/mailmail/contacts.py +78 -0
  19. mailmail-0.1.0/src/mailmail/credentials.py +270 -0
  20. mailmail-0.1.0/src/mailmail/errors.py +140 -0
  21. mailmail-0.1.0/src/mailmail/mailer.py +396 -0
  22. mailmail-0.1.0/src/mailmail/message.py +283 -0
  23. mailmail-0.1.0/src/mailmail/provider.py +124 -0
  24. mailmail-0.1.0/src/mailmail/py.typed +0 -0
  25. mailmail-0.1.0/tests/__init__.py +6 -0
  26. mailmail-0.1.0/tests/conftest.py +161 -0
  27. mailmail-0.1.0/tests/test_attachment.py +720 -0
  28. mailmail-0.1.0/tests/test_cli.py +353 -0
  29. mailmail-0.1.0/tests/test_config.py +221 -0
  30. mailmail-0.1.0/tests/test_construction.py +45 -0
  31. mailmail-0.1.0/tests/test_contacts.py +130 -0
  32. mailmail-0.1.0/tests/test_credentials.py +370 -0
  33. mailmail-0.1.0/tests/test_docstrings.py +135 -0
  34. mailmail-0.1.0/tests/test_mailer.py +496 -0
  35. mailmail-0.1.0/tests/test_message.py +241 -0
  36. mailmail-0.1.0/tests/test_packaging.py +60 -0
  37. mailmail-0.1.0/tests/test_readme.py +156 -0
  38. mailmail-0.1.0/tests/test_send.py +137 -0
  39. mailmail-0.1.0/tests/test_send_bulk.py +264 -0
  40. mailmail-0.1.0/tests/test_skill.py +201 -0
  41. mailmail-0.1.0/tests/test_tls.py +161 -0
@@ -0,0 +1,17 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ # Monthly and grouped into one pull request, because the alternative is a
6
+ # treadmill: setup-uv ships several releases some weeks, nearly all of them
7
+ # just checksums for a newly released uv, and a pull request per release on
8
+ # a two-action workflow would be noise that gets skimmed and then ignored.
9
+ # Once a month is often enough for what this has to catch: the major bumps,
10
+ # which an exact pin cannot follow at all.
11
+ schedule:
12
+ interval: monthly
13
+ groups:
14
+ actions:
15
+ patterns: ["*"]
16
+ commit-message:
17
+ prefix: build
@@ -0,0 +1,117 @@
1
+ name: check
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ schedule:
9
+ - cron: "0 0 * * 1"
10
+
11
+ jobs:
12
+ check:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ # The floor and the current release. requires-python says >=3.11, so 3.11 is
18
+ # the version that claim has to actually hold on. Nothing pins the upper end
19
+ # -- >=3.11 promises every release above it, with no ceiling to read off --
20
+ # so it tracks whatever CPython currently ships: left behind, it stops being
21
+ # evidence the promise holds on new releases and becomes a version nobody runs.
22
+ python-version: ["3.11", "3.14"]
23
+
24
+ steps:
25
+ # Both pinned past a moving tag: @v7 is a pointer its owner can repoint, and the
26
+ # next run here would execute the new target without a commit of its own. The two
27
+ # forms differ because the actions do -- setup-uv publishes no moving tag from v8
28
+ # on and marks its releases immutable, so the version itself cannot move, while
29
+ # checkout's releases stay mutable and only the commit is fixed. Neither follows
30
+ # a new release on its own; dependabot proposes both (.github/dependabot.yml).
31
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
32
+ - uses: astral-sh/setup-uv@v8.3.2
33
+
34
+ - name: Install
35
+ # A venv per matrix version, not `uv pip --system`: the runner's system
36
+ # Python is externally managed and is 3.12 whatever the matrix says, so
37
+ # --system both failed and ignored the version under test. This is also
38
+ # exactly what the README tells a person to run.
39
+ run: |
40
+ uv venv --python ${{ matrix.python-version }}
41
+ uv pip install -e ".[dev]"
42
+ .venv/bin/python -c "import sys; print('testing on', sys.version)"
43
+
44
+ - name: Test
45
+ run: .venv/bin/pytest -q
46
+
47
+ - name: Lint
48
+ run: .venv/bin/ruff check src tests scripts
49
+
50
+ - name: Types
51
+ run: .venv/bin/mypy
52
+
53
+ - name: Confirm the package still has no runtime dependencies
54
+ # The zero-dependency claim is in the README and the pyproject comment; a
55
+ # claim nothing checks is a claim that quietly stops being true. Installed
56
+ # into a bare environment, mailmail must import with nothing else present.
57
+ run: |
58
+ uv venv /tmp/bare --python ${{ matrix.python-version }}
59
+ uv pip install --python /tmp/bare/bin/python .
60
+ /tmp/bare/bin/python -c "
61
+ import importlib.metadata as md
62
+ requires = md.requires('mailmail') or []
63
+ runtime = [r for r in requires if 'extra ==' not in r]
64
+ assert not runtime, f'runtime dependencies appeared: {runtime}'
65
+ import mailmail
66
+ print('mailmail', mailmail.__version__, 'imports with no third-party packages')
67
+ "
68
+
69
+ - name: Confirm the console script installed
70
+ # pyproject declares a `mailmail` entry point; a wheel that dropped it
71
+ # would leave the CLI, the skill, and the docs pointing at a command that
72
+ # is not there. `--version` is the cheapest call that proves it runs.
73
+ run: |
74
+ uv venv /tmp/cli --python ${{ matrix.python-version }}
75
+ uv pip install --python /tmp/cli/bin/python .
76
+ /tmp/cli/bin/mailmail --version
77
+
78
+ - name: Confirm a user's type checker can see the hints
79
+ # Every hint in this package is invisible to a user unless py.typed ships
80
+ # alongside it (PEP 561), and the source cannot answer whether it did:
81
+ # src/mailmail/py.typed can sit there in git while the built wheel omits it.
82
+ # So ask it the way a user does -- install the built package into a clean
83
+ # environment and run their checker over their code. It shipped without the
84
+ # marker once, which made `to` being required a promise that held only
85
+ # inside this repo.
86
+ run: |
87
+ uv venv /tmp/typed --python ${{ matrix.python-version }}
88
+ uv pip install --python /tmp/typed/bin/python . mypy
89
+ cat > /tmp/user_code.py <<'PY'
90
+ from mailmail import Message, send
91
+
92
+ Message(subject="s", body="b", to="lead@example.com") # 16 recipients
93
+ send(subject="s", body="b") # no recipient
94
+ PY
95
+ /tmp/typed/bin/mypy /tmp/user_code.py > /tmp/mypy_out 2>&1 || true
96
+ cat /tmp/mypy_out
97
+ grep -q 'incompatible type "str"' /tmp/mypy_out
98
+ grep -q 'Missing named argument "to"' /tmp/mypy_out
99
+
100
+ blocked-list-drift:
101
+ # The size limit is asked of the server on every send, so it cannot go stale.
102
+ # The blocked-extension list can: it is a snapshot of what Google published,
103
+ # and Google can change it without telling anyone. This is the only part of
104
+ # what the package knows that has no way of noticing it went wrong.
105
+ #
106
+ # Weekly and on demand, never on a push: a code change is not the reason the
107
+ # list would move, and a Google page edit must not turn someone's pull
108
+ # request red.
109
+ if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
110
+ runs-on: ubuntu-latest
111
+ steps:
112
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
113
+ - uses: astral-sh/setup-uv@v8.3.2
114
+ - run: |
115
+ uv venv
116
+ uv pip install -e .
117
+ - run: .venv/bin/python scripts/check_blocked_list.py
@@ -0,0 +1,34 @@
1
+ name: publish
2
+
3
+ # Publish to PyPI when a GitHub Release is published. Authentication is PyPI
4
+ # Trusted Publishing (OIDC): no token or password is stored anywhere -- GitHub
5
+ # mints a short-lived identity that PyPI verifies against the publisher
6
+ # registered for this repo (owner seokhoonj / repo mailmail / workflow
7
+ # publish.yml / environment "pypi"). Register that publisher on PyPI first; until
8
+ # the project exists there it is registered as a "pending" publisher.
9
+
10
+ on:
11
+ release:
12
+ types: [published]
13
+
14
+ jobs:
15
+ publish:
16
+ runs-on: ubuntu-latest
17
+ environment: pypi
18
+ permissions:
19
+ # Naming any permission drops every unnamed one to `none`, so `contents`
20
+ # has to be listed back: checkout clones with the job token, and this repo
21
+ # is private, so without read here that clone fails "repository not found".
22
+ contents: read
23
+ id-token: write # required for OIDC; this is what replaces a stored token
24
+ steps:
25
+ # Pinned the same way check.yml is: checkout past its mutable tag to a
26
+ # commit, setup-uv on its immutable v8 tag, and the publish action past its
27
+ # moving release/v1 branch to a commit. dependabot proposes all three
28
+ # (.github/dependabot.yml). uv build writes the sdist and wheel to dist/,
29
+ # which the publish action uploads.
30
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
31
+ - uses: astral-sh/setup-uv@v8.3.2
32
+ - name: Build sdist and wheel
33
+ run: uv build
34
+ - uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
@@ -0,0 +1,22 @@
1
+ # AI coding agents
2
+ CLAUDE.md
3
+ .claude/
4
+ AGENTS.md
5
+ AGENT.md
6
+ .codex/
7
+ GEMINI.md
8
+ .gemini/
9
+
10
+ dev/
11
+
12
+ # Python
13
+ __pycache__/
14
+ *.py[cod]
15
+ *.egg-info/
16
+ build/
17
+ dist/
18
+ .venv/
19
+ venv/
20
+ .pytest_cache/
21
+ .ruff_cache/
22
+ .mypy_cache/
mailmail-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Seokhoon Joo
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.