Send Mail Via Python (smvp)
The smvp utility reads a file, uses its contents as the body of an
email, and sends it to a specified recipient. The input file can be a
text file with ANSI color codes, HTML, or plain text. The resulting
message is sent as a multipart MIME email that renders properly in both
plain text and HTML. The --content-type option can auto-detect the
input type or force it to be handled as plain text or HTML.
Note: The file itself is not sent as an attachment; instead, the contents of the file are put into the body of the email.
Compatibility
The smvp runtime is supported on Windows, Linux, and macOS.
Local project tooling supports Linux and macOS. The GitHub release
workflow runs on Linux; the cron examples below are Linux-specific.
Use Case
There are several use cases, but smvp was developed for two primary purposes:
- Configuring
postfixandsendmailcan require more setup than a small script needs. - Cron scripts often need to email status information and the contents
of various log files. Some of the files contain ANSI escape sequences
for terminal colors. The smvp utility converts those ANSI escape
sequences into styled HTML, so the resulting emails are nicely
formatted. You could set
$MAILTOin your crontab, but you would not get proper handling of ANSI escape sequences, and you would still have the problem mentioned in item 1.
Installation
Use your preferred Python package installer for command line tools, for example:
pipx install smvp
or
uv tool install smvp
or
python -m venv .venv
# Linux / macOS
source .venv/bin/activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
# Windows Command Prompt
.venv\Scripts\activate.bat
python -m pip install smvp
Requirements
SMTP Environment Variables
Set the following environment variables in the shell you are using
before running smvp.
Linux / macOS shells:
export SMVP_USER="<your email>" # e.g. "myemail@gmail.com"
export SMVP_TOKEN="<your token>" # e.g. "<gmail app password>"
export SMVP_SERVER="<smtp server>" # e.g. "smtp.gmail.com"
Windows PowerShell:
$env:SMVP_USER = "<your email>"
$env:SMVP_TOKEN = "<your token>"
$env:SMVP_SERVER = "<smtp server>"
Windows Command Prompt:
set SMVP_USER=<your email>
set SMVP_TOKEN=<your token>
set SMVP_SERVER=<smtp server>
If you want these variables to persist across sessions, add them to your shell profile or your Windows user environment settings.
Linux automation note:
Tip: If you're using
cronand sending mail with smvp from within a script, make sure to include the environment variables at the top of yourcrontabso your scripts will have access to them during execution. Also include a line in your script that exports the directory where your Python tool installer places executables. For example, if you're usinguvon Ubuntu, you could put something like this near the top of your bash script:
# Setup PATH export so the script can find installed Python tools
export PATH="$PATH:/home/<yourhome>/.local/bin"
SMTP Server
The SMVP_SERVER you select must support secure TLS connections on port
587. Check the SMTP settings for your email provider. This is the
default TLS port on Gmail, so if you are using your Gmail account to
send email, this requirement is usually already satisfied.
Styling
smvp offers custom font and font size options for your email. The
default font for formatted HTML email is Courier New, 12px. Beyond
the default, you can choose any font size from 2px up to and
including 100px, from the following font families:
"Andale Mono", "Arial", "Brush Script MT", "Comic Sans MS",
"Courier New", "Garamond", "Georgia", "Helvetica", "Impact",
"Luminari", "Monaco", "Tahoma", "Times New Roman", "Trebuchet MS",
"Verdana", "fantasy", "monospace", "sans-serif", "serif"
Note: Not every font will render properly on every device. When in doubt, fonts such as "monospace", "sans-serif", "fantasy", and "serif" are generally safe. You may need to try a few options to find the right one for your use case.
Content Type
By default, smvp uses --content-type auto, which inspects the input
and decides whether to treat it as plain text or HTML. You can override
that behavior when needed:
auto Auto-detect whether the input should be treated as text or HTML
text Always treat the input as plain text, including HTML-like content
html Always treat the input as HTML
This is useful when the input contains angle brackets that should be sent literally, or when you want to force HTML rendering for a file that would not otherwise be detected as HTML.
Usage
usage: smvp [-h] [-c {auto,text,html}] [-f FONT_FAMILY] [-s FONT_SIZE] [-v] recipient subject file
For example:
smvp friend@gmail.com "Hello, Friend" ~/logfile.txt -f "Trebuchet MS" -s 14
On Windows, the same command works after installation. The only difference is the path style, for example:
smvp friend@gmail.com "Hello, Friend" .\logfile.txt -f "Trebuchet MS" -s 14
Force plain-text handling for HTML-like input:
smvp friend@gmail.com "Raw Markup" ./snippet.txt --content-type text
Force HTML handling:
smvp friend@gmail.com "Rendered Markup" ./fragment.txt --content-type html
For more details, run:
smvp -h
Development
Local development requires uv, just, Git, and
Git Cliff. After installing those tools, run:
just setup
just check
Use just changelog to preview user-facing changes. Release preparation
uses just bump <version> followed by just tag-release from an
up-to-date main branch.
Pull-request titles use Conventional Commits. Accepted types are feat,
change, deprecate, remove, fix, security, perf, deploy,
docs, revert, build, chore, ci, refactor, style, and test.
Metadata
Release files for smvp 0.4.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| smvp-0.4.9.tar.gz | 27.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| smvp-0.4.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.8 kB
Release files / smvp-0.4.9.tar.gz
| Download URL | smvp-0.4.9.tar.gz |
|---|---|
| Size | 27.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c327b992a1d8db6478ca97a2307633e494cdbbb0f015c8f71990f691983d366
|
|
BLAKE2b-256 checksum How to use checksums |
178e4141d4a3b40405de2bb930723e4dd59ea07458ff40cb9d3842a2bdf59e4b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logRelease files / smvp-0.4.9-py3-none-any.whl
| Download URL | smvp-0.4.9-py3-none-any.whl |
|---|---|
| Size | 10.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87839087202977d42a9b16e9f4820fb36838724ebbd99ea47b6ad213199caca0
|
|
BLAKE2b-256 checksum How to use checksums |
6a11613e060c24011a500ab0d5b8926089703528589fd686ffa383fff7b5465a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency log