Send personalised welcome emails to guests loaded from iCal calendar URLs
Project description
welcomer
Sends configurable welcome emails to guests loaded from iCal calendar URLs. Built for accommodation businesses — reads reservations from a calendar and emails each guest a personalised welcome message.
Install
pip install welcomer
# or with uv (recommended)
uv tool install welcomer
# or with pipx
pipx install welcomer
Container
podman run --rm \
-v ~/.config/welcomer:/root/.config/welcomer:ro \
ghcr.io/pdostal/welcomer --dry-run
latest is updated on every push to master. Tagged releases follow vX.Y.Z.
Setup
brew install uv taplo
uv sync
# copy the example config below to config.toml and edit it
Usage
uv run welcomer --dry-run # preview recipients list
uv run welcomer --dry-run --print-note # also show rendered message per guest
uv run welcomer # interactive send (default)
uv run welcomer --yes # send to all without prompting
uv run welcomer --yes --silent # send silently (suppress info messages)
uv run welcomer --dry-run --test-config # test with bundled sample calendars
Config
Config is loaded from the first path that exists:
config.tomlin the current directory~/.config/welcomer/config.toml
Example config:
subject = "Reservation confirmed – {name}"
# Only show reservations starting within this many days from today (optional)
# days = 30
# Days before check-in when a reservation becomes eligible to send (default: 14)
# advance = 14
body = """
Dear {name},
Thank you for your reservation from {start} to {end}.
We look forward to hosting you ({adults} adults, {kids} kids).
"""
[smtp]
host = "smtp.example.com"
port = 587
from = "info@myproperty.com"
username = "info@myproperty.com"
password = "secret"
tls = true # use STARTTLS (port 587)
# ssl = true # use SSL/TLS instead (port 465)
[[calendars]]
name = "My Property"
provider = "BookingProvider"
url = "https://example.com/calendar.ics"
Template variables: {name}, {email}, {phone}, {start}, {end}, {summary}, {adults},
{kids}.
Local SMTP testing with Mailpit
Mailpit catches outgoing emails locally without actually
delivering them. It gives you a web inbox at http://localhost:8025 and listens for SMTP on port
1025 — no account, no real delivery, no risk of accidentally mailing guests.
brew install mailpit
mailpit # starts in the foreground; Ctrl-C to stop
Mailpit also runs as a macOS service if you prefer:
brew services start mailpit
Add this to your config while testing:
[smtp]
host = "localhost"
port = 1025
from = "test@localhost"
# no username / password / tls needed for Mailpit
Then run welcomer as normal — all emails land in the Mailpit inbox at http://localhost:8025
instead of being delivered.
Interactive mode
Interactive mode is on by default. The app prompts before sending each eligible email (check-in
within the advance window, default 14 days). Use --yes to skip prompts. Previously sent
reservations are tracked in ~/.config/welcomer/sent.log and skipped automatically on future runs.
The Sent column shows the status of each reservation:
| Symbol | Colour | Meaning | | ------ | ------ | ------- | | ✓ | green | Already sent (in
sent.log) | | ● | green | Eligible to send now (check-in within advance window) | | ○ | yellow |
Not yet eligible (check-in too far away) | | (empty) | — | No email address, or check-in already
passed and not yet sent |
Calendar cache
Remote iCal URLs are cached for 5 hours in ~/.config/welcomer/cache/. This avoids hitting your
calendar provider on every run. Use --force-refresh to bypass the cache and re-fetch all remote
URLs immediately:
uv run welcomer --dry-run --force-refresh
The cache directory is created automatically. Each URL is stored as a separate <sha256-of-url>.ics
file. Local file paths and --test-config are never cached.
Multi-property reservations
When the same guest (identical name, provider, check-in, and check-out) appears across multiple
properties, welcomer merges them into a single Multi entry and sends one email. The property
column shows Multi and overlapping reservations from other providers are still detected correctly.
Overlap detection
welcomer warns when two reservations for the same property have overlapping dates. Warnings appear
above the table regardless of the --days filter. Affected rows are highlighted in red.
Recipient extraction
Recipients are extracted from calendar events in this order:
ATTENDEEentriesORGANIZERif no attendeesSUMMARY(name) +Descriptionfield (email viaEmail:, phone viaTelefon:) as last resort
Phone and email parsed from Description are available in all three cases.
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file welcomer-0.4.1.tar.gz.
File metadata
- Download URL: welcomer-0.4.1.tar.gz
- Upload date:
- Size: 50.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10da8fe8f8b20ccb653af5d13594a8265bcec7020ca8c80a1ba34c14c4ef70bc
|
|
| MD5 |
8922d50b4d3444468c5aa51656ef58f6
|
|
| BLAKE2b-256 |
839da45c66320c6a087e09dd4ebd37bef716499f1e0a5a4109acaa71c4fe0e6f
|
Provenance
The following attestation bundles were made for welcomer-0.4.1.tar.gz:
Publisher:
publish.yml on pdostal/welcomer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
welcomer-0.4.1.tar.gz -
Subject digest:
10da8fe8f8b20ccb653af5d13594a8265bcec7020ca8c80a1ba34c14c4ef70bc - Sigstore transparency entry: 1242551171
- Sigstore integration time:
-
Permalink:
pdostal/welcomer@6a97e5ad96c5c2c19a801e38ae84f46ba99aaef9 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/pdostal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6a97e5ad96c5c2c19a801e38ae84f46ba99aaef9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file welcomer-0.4.1-py3-none-any.whl.
File metadata
- Download URL: welcomer-0.4.1-py3-none-any.whl
- Upload date:
- Size: 19.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
181c6a8d82b3514bd19b90117eb01a87f774d810f5907cfe30507e320e326666
|
|
| MD5 |
7142e9c09f72fb27c6e60319872fe8da
|
|
| BLAKE2b-256 |
f4ff92a2a94d0a61040118167691d9694f86a8e03c006b4fa2db91354defdf1f
|
Provenance
The following attestation bundles were made for welcomer-0.4.1-py3-none-any.whl:
Publisher:
publish.yml on pdostal/welcomer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
welcomer-0.4.1-py3-none-any.whl -
Subject digest:
181c6a8d82b3514bd19b90117eb01a87f774d810f5907cfe30507e320e326666 - Sigstore transparency entry: 1242551185
- Sigstore integration time:
-
Permalink:
pdostal/welcomer@6a97e5ad96c5c2c19a801e38ae84f46ba99aaef9 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/pdostal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6a97e5ad96c5c2c19a801e38ae84f46ba99aaef9 -
Trigger Event:
push
-
Statement type: