Alexander 3bc25a2bdb Add per-recipient relationship labels in newsletter
Each featured person now carries a parenthetical label relative
to the recipient: "Jane Doe (your mother) — 45th birthday",
"Karl Müller (your 4th great-grandfather) — death". Labels are
italic, muted, and only appear when a path can be computed.

- New RelationshipPathFinder service mirrors webtrees'
  RelationshipService::getCloseRelationship BFS but with a
  configurable depth (default 14 hops ≈ 7 generations) so it
  reaches great-great-grandparents and beyond. Results are
  memoised per (recipient xref, target xref) within one
  dispatch run.
- nameFromPath() formatting is delegated to webtrees so the
  label honours the configured UI language (German, English,
  etc.) and gendered/inflected forms.
- The recipient's tree-bound Individual is looked up via
  Tree::getUserPreference(user, PREF_TREE_ACCOUNT_XREF). External
  admin-added recipients (no webtrees account, no linked record)
  silently get no labels — names render plain.
- Trade-off: the view now renders once per recipient (instead of
  once per language group), because the relationship map is
  personalised. For typical subscriber counts the extra string-
  concat cost is negligible compared to the SMTP send itself.
2026-05-15 12:53:22 +02:00

webtrees Email Newsletter

A webtrees 2.2+ custom module that sends recurring email newsletters with:

  • Upcoming birthdays of still-living individuals.
  • Upcoming marriage anniversaries of intact couples (optional — admin toggle, per tree). Marriages with a divorce or annulment fact are excluded automatically.
  • Once-per-month historical section: births and deaths of deceased individuals whose anniversary falls in the upcoming window.

The decision to actually send is made by comparing a stored "last sent" timestamp to the configured frequency, so the dispatch run is idempotent — calling the trigger more often than the frequency simply does nothing extra.

Requirements

  • webtrees ≥ 2.2.0
  • PHP ≥ 8.2
  • A working SMTP / sendmail configuration in webtrees → Control panel → Sending email (this module reuses webtrees' standard mailer).
  • An external scheduler on the host: system cron, a systemd timer, a Kubernetes CronJob, or anything else that can fire an HTTP request at a fixed interval. Newsletter dispatch never runs on visitor page loads — it only runs when the scheduler triggers it.

Installation

  1. Copy this directory into the webtrees modules_v4/ folder, renaming it to email_newsletter (the folder name determines the internal module identifier — the registered name will be _email_newsletter_).

    cp -r webtrees_email_newsletter /var/www/webtrees/modules_v4/email_newsletter
    
  2. In the webtrees control panel, go to Modules → All modules and enable Email Newsletter.

  3. Open Control panel → Modules → Email Newsletter → Preferences and:

    • Enable newsletter dispatch per tree.
    • Pick a frequency (default: 14 days).
    • Optionally toggle marriage anniversaries and add any extra external email addresses.
    • Copy the Cron URL at the bottom — this is the secret-token URL your scheduler must hit.

Setting up the scheduler

Why no built-in scheduler? PHP has no daemon, and frameworks like Laravel rely on a once-per-minute system cron to fire their internal scheduler. This module follows the same convention: the host OS owns the timer, the module owns the "is it actually due?" decision.

System cron

# Run every 15 minutes. The module itself decides whether sending is due.
*/15 * * * *  curl -fsS --max-time 60 'https://example.com/module/_email_newsletter_/Cron?token=YOUR_TOKEN' > /dev/null

systemd timer

/etc/systemd/system/webtrees-newsletter.service:

[Unit]
Description=webtrees newsletter trigger

[Service]
Type=oneshot
ExecStart=/usr/bin/curl -fsS --max-time 60 "https://example.com/module/_email_newsletter_/Cron?token=YOUR_TOKEN"

/etc/systemd/system/webtrees-newsletter.timer:

[Unit]
Description=Trigger webtrees newsletter dispatch

[Timer]
OnCalendar=*-*-* *:00/15
Persistent=true

[Install]
WantedBy=timers.target

Then systemctl enable --now webtrees-newsletter.timer.

Forcing a one-off send

The admin Preferences page has a Send now button for testing. For an unattended one-off send, append &force=1 to the cron URL — that bypasses the "is it due?" check.

Subscribers

Two sources, combined:

  1. Logged-in webtrees users who opt in via the per-tree Newsletter subscription menu entry (visible only to logged-in users on trees where the module is enabled). Only approved and email-verified accounts will receive the newsletter.
  2. External addresses the tree administrator lists in the Extra recipient email addresses textarea (one per line).

Privacy

The dispatch service does not impersonate a webtrees user, so it sees the tree from the visitor access level. Records and facts that your tree settings hide from visitors will be omitted from the newsletter even if a recipient has higher in-app access. This is the safest default for an outbound email — if you need to expose more information, relax the tree's visitor-access settings or hand-curate the Extra recipient list.

License

AGPL-3.0-or-later. See LICENSE for the full text.

S
Description
An email newsletter plugin for upcoming birthdays and marriage anniversaries of living tree members as well as birth and death days for deceased.
Readme 257 KiB
Languages
PHP 50.8%
HTML 49.2%