Skip to main content

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:

  1. config.toml in the current directory
  2. ~/.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:

  1. ATTENDEE entries
  2. ORGANIZER if no attendees
  3. SUMMARY (name) + Description field (email via Email:, phone via Telefon:) as last resort

Phone and email parsed from Description are available in all three cases.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

welcomer-0.4.1.tar.gz (50.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

welcomer-0.4.1-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

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

Hashes for welcomer-0.4.1.tar.gz
Algorithm Hash digest
SHA256 10da8fe8f8b20ccb653af5d13594a8265bcec7020ca8c80a1ba34c14c4ef70bc
MD5 8922d50b4d3444468c5aa51656ef58f6
BLAKE2b-256 839da45c66320c6a087e09dd4ebd37bef716499f1e0a5a4109acaa71c4fe0e6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for welcomer-0.4.1.tar.gz:

Publisher: publish.yml on pdostal/welcomer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for welcomer-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 181c6a8d82b3514bd19b90117eb01a87f774d810f5907cfe30507e320e326666
MD5 7142e9c09f72fb27c6e60319872fe8da
BLAKE2b-256 f4ff92a2a94d0a61040118167691d9694f86a8e03c006b4fa2db91354defdf1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for welcomer-0.4.1-py3-none-any.whl:

Publisher: publish.yml on pdostal/welcomer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page