diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4b559ac..2a3208c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,15 @@ repos: - repo: local hooks: - - id: run-just-test - name: All tests and checks - entry: just test + - id: mypy + name: Type checking + entry: just mypy + language: system + always_run: true + pass_filenames: false + - id: check + name: Formatting and linting + entry: just check language: system always_run: true pass_filenames: false diff --git a/README.md b/README.md index 4299876..7ebf421 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,7 @@ See the full documentation at [https://matthewcane.github.io/python-ntfy/](https - Scheduled delivery - Tags - Action buttons - -## Future Features - -- [Email notifications](https://docs.ntfy.sh/publish/#e-mail-notifications) -- Send to multiple topics at once +- Email notifications ## Contributing diff --git a/python_ntfy/_send_functions.py b/python_ntfy/_send_functions.py index dcb9481..f6dfbb6 100644 --- a/python_ntfy/_send_functions.py +++ b/python_ntfy/_send_functions.py @@ -192,6 +192,7 @@ def send( schedule: Optional[datetime] = None, format_as_markdown: bool = False, timeout_seconds: int = 5, + email: Optional[str] = None, ) -> dict: """Send a text-based message to the server. @@ -208,6 +209,7 @@ def send( format_as_markdown: If true, the message will be formatted as markdown. additional_topics: A list of additional topics to send the message to. timeout_seconds: The number of seconds to wait before timing out the reqest to the server. + email: Forward messages to an email address. Only one email address can be specified. Returns: dict: The response from the server. @@ -236,6 +238,9 @@ def send( if len(actions) > 0: headers["Actions"] = " ; ".join([action.to_header() for action in actions]) + if email: + headers["Email"] = email + if schedule: headers["Delay"] = str(int(schedule.timestamp())) @@ -259,6 +264,7 @@ def send_file( actions: Optional[list[Union[ViewAction, BroadcastAction, HttpAction]]] = None, schedule: Optional[datetime] = None, timeout_seconds: int = 30, + email: Optional[str] = None, ) -> dict: """Sends a file to the server. @@ -270,6 +276,7 @@ def send_file( actions: A list of ActionButton objects to attach to the message. schedule: The time to schedule the message to be sent. Must be more than 10 seconds away and less than 3 days in the future. timeout_seconds: The number of seconds to wait before timing out. + email: Forward messages to an email address. Only one email address can be specified. Returns: dict: The response from the server. @@ -293,6 +300,9 @@ def send_file( "Actions": " ; ".join([action.to_header() for action in actions]), } + if email: + headers["Email"] = email + if schedule: headers["Delay"] = str(int(schedule.timestamp())) diff --git a/tests/assets/test_containers.yml b/tests/assets/test_containers.yml index e6bb954..8a12bc6 100644 --- a/tests/assets/test_containers.yml +++ b/tests/assets/test_containers.yml @@ -3,24 +3,28 @@ services: image: binwiederhier/ntfy:latest command: serve healthcheck: - test: ["CMD-SHELL", "curl", "-f", "http://localhost/v1/health"] + test: ['CMD-SHELL', 'curl', '-f', 'http://localhost/v1/health'] interval: 1s retries: 3 ports: - - "8080:80" + - '8080:80' environment: NTFY_BASE_URL: 'http://localhost' NTFY_ATTACHMENT_CACHE_DIR: /var/lib/ntfy/attachments + NTFY_SMTP_SENDER_ADDR: 'localhost:1025' + NTFY_SMTP_SENDER_USER: 'test' + NTFY_SMTP_SENDER_PASS: 'test' + NTFY_SMTP_SENDER_FROM: 'test@test.com' ntfy-with-auth: image: binwiederhier/ntfy:latest command: serve healthcheck: - test: ["CMD-SHELL", "curl", "-f", "http://localhost/v1/health"] + test: ['CMD-SHELL', 'curl', '-f', 'http://localhost/v1/health'] interval: 1s retries: 3 ports: - - "8081:80" + - '8081:80' environment: NTFY_BASE_URL: 'http://localhost' NTFY_ATTACHMENT_CACHE_DIR: /var/lib/ntfy/attachments @@ -29,3 +33,9 @@ services: volumes: - ./auth.db:/var/lib/ntfy/auth.db + mailpit: + image: axllent/mailpit + ports: + - '1025:1025' + environment: + MP_SMTP_AUTH_ACCEPT_ANY: 'true' diff --git a/tests/test_send_file.py b/tests/test_send_file.py index 1b46be0..062bfb8 100644 --- a/tests/test_send_file.py +++ b/tests/test_send_file.py @@ -26,3 +26,11 @@ def test_send_scheduled_file(localhost_server_no_auth, no_auth) -> None: assert response["attachment"]["name"] == "test_text.txt" assert response["attachment"]["type"] == "text/plain; charset=utf-8" assert response["time"] == int(ts.timestamp()) + + +def test_send_file_with_email(localhost_server_no_auth, no_auth) -> None: + ntfy = NtfyClient(topic=topic) + response = ntfy.send_file("tests/assets/test_text.txt", email="test@test.com") + print(response) + assert response["attachment"]["name"] == "test_text.txt" + assert response["attachment"]["type"] == "text/plain; charset=utf-8" diff --git a/tests/test_send_message.py b/tests/test_send_message.py index 56cbf96..c797860 100644 --- a/tests/test_send_message.py +++ b/tests/test_send_message.py @@ -146,3 +146,11 @@ def test_send_message_without_auth(no_server, no_auth) -> None: print(response) assert response["event"] == "message" assert response["topic"] == topic + + +def test_send_message_with_email(localhost_server_no_auth, no_auth) -> None: + ntfy = NtfyClient(topic=topic) + response = ntfy.send(message="test_send_message_with_email", email="test@test.com") + print(response) + assert response["event"] == "message" + assert response["topic"] == topic