Make sending emails a bit easier in Python
Project description
iposi
"iposi" is the word for "post" or "post office" in isiXhosa, one of South Africa's twelve official languages. It reflects what this package is for: making sending simple emails with Python a bit simpler.
Installation
pip install iposi
Configuration
You need to provide a few environment variables, so that iposi knows how to communicate with your SMTP server.
Environment variable | Required? | Description | Example |
---|---|---|---|
IPOSI_HOST |
Yes | Hostname of the SMTP server. | smtp.example.com |
IPOSI_PASSWORD |
No | Password for the SMTP server. | not_secret |
IPOSI_PORT |
No | Port on which the SMTP server is listening. | 587 |
IPOSI_USERNAME |
No | Username for the SMTP server. | john.doe |
IPOSI_USE_TLS |
No | Whether to use the Transport Layer Security (TLS) protocol. | 1 |
IPOSI_USERNAME
and IPOSI_PASSWORD
must only be set if the SMTP server supports authentication. If you set either of the two, you must set the other as well.
IPOSI_USE_TLS
should be set to 1 if the SMTP server supports TLS, and to 0 otherwise. It is optional; the default value is 1.
If IPOSI_PORT
is not set, it is assumed that the SMTP server is listening on port 587.
Usage
Once you have configured all the environment variables, sending emails is as simple as
calling mail
.
from iposi import mail
mail(
sender="John Doe <john@example.org>",
recipients=["Anna Glencore <anna@example.org>", "logging@example.org"],
subject="Daily Observations",
plain="Here is the breakdown of the daily observations...",
html="<p>Here is the breakdown of the daily observations...</p>",
)
The sender must be the address for the email's From field. The recipients must either be a string with a single address or a list of addresses. Only one of plain text or HTML content needs to be supplied.
The mail function sends the email to each recipient individually, i.e. the To field of the email only contains the recipient's address, irrespective of whether there is more than one recipient.
If the email is rejected by the server for a recipient, the function still tries sending it to the remaining recipients. However, after all recipients have been handled it raises a MailError
. This error contains a dictionary recipient_errors
, whose keys are the failing recipient addresses and whose values are RecipientError
instances containing the SMTP code for the failure, the error message and (if available) the exception causing the failure.
The following example shows how you could handle errors when sending an email.
from iposi import mail, MailError
recipients = ["Anna Glencore <anna@example.org>", "logging@example.org", "invalid"]
try:
mail(
sender="John Doe <john@example.org>",
recipients=recipients,
subject="Daily Observations",
plain="Here is the breakdown of the daily observations...",
html="<p>Here is the breakdown of the daily observations...</p>",
)
except MailError as e:
print("The email could not be sent to the following recipient(s):")
for recipient, error in e.recipient_failures.items():
print()
print(f"{recipient}:")
print(f" SMTP code: {error.smtp_code if error.smtp_code else 'n/a'}")
print(f" Message: {error.message}")
Development and deployment
PDM is used as the package manager for this project. There are several ways to install PDM; one is to use pipx.
pipx install pdm
Also, nox is used as a test runner. It can be installed with pipx.
pipx install nox
Managing dependencies
Use PDM's add
command for adding dependencies. For example:
pdm add numpy
To add an optional dependency, use -G/--group <name>
option. For example, if you want to add pyjwt
to the optional group jwt
:
pdm add -G pyjwt
Optional groups are listed in the project.optional-dependencies
section of pyproject.toml
.
In case the dependency is required for development purposes only, you should use the -dG <name>
option. For example, the following will add pytest to the development only group test
:
pdm add -dG test pytest
Development only dependency groups are listed in the tool.pdm.dev-dependencies
section of pyproject.toml
. They `re not included in the published package.
Linting and testing
There are some PDM scripts you can use during development, in addition to PDM's own commands.
Script | Description |
---|---|
lint |
Lint the code. This includes running the precommit and mypy scripts. |
test |
Run the tests. |
precommit |
Run pre-commit on all files. |
testcov |
Run the tests (with coverage). |
typecheck |
Run mypy. |
You should run pdm lint
and pdm test
frequently, ideally before every commit. Before pushing to GitHub, you should run nox
(with no arguments); this will run the lint and test PDM scripts, using multiple Python versions for the test one.
Deployment
There is a GitHub workflow (publish.xml
) for deploying the package to a package repository (such as PyPI). This workflow assumes that the GitHub repository is a trusted publisher. Refer to the PyPI documentation on how to create a PyPI project with a trusted publisher.
The workflow is triggered whenever a release is created for the GitHub repository. The tag for the release must be the package's version number preceded by a "v". For example, if the package version is "1.4.2"
, the tag must be "v1.4.2"
. The tag must be for the current commit in the main branch.
Acknowledgements
The mocking in the unit tests draws heavily on an article in Engineering for Data Science.
Release history
v0.1.0 (26 June 2024)
Initial release
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file iposi-0.1.0.tar.gz
.
File metadata
- Download URL: iposi-0.1.0.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: pdm/2.16.1 CPython/3.10.12 Linux/6.5.0-1022-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 002b85d5f6ab1ccc9659845f9151df7724d6181dc6eebc96ac8d56d04ba7e186 |
|
MD5 | c4ef8f292cdf222acd6a84b993904bb7 |
|
BLAKE2b-256 | e58f9e83e71bf2792e9eea46c2ba33d4899b13c0686fd2cb06fc09d3a0595bbe |
File details
Details for the file iposi-0.1.0-py3-none-any.whl
.
File metadata
- Download URL: iposi-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: pdm/2.16.1 CPython/3.10.12 Linux/6.5.0-1022-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2080b28def9f0c60ff9d606c6bdfa3c40ad6553ce71720ddc812ee81b537bc27 |
|
MD5 | d36a1b6389ce6a7d9f9967dab159be48 |
|
BLAKE2b-256 | ad876238866b2c3e6917929079c3df3a3689c7a06137355c5c4b690fc1a1eea3 |