Blog 2026-07-23
Email Heartbeat Monitoring: Cron Check-ins Without HTTP
Monitor cron jobs and air-gapped systems with email heartbeats — unique @ping.seiri.app addresses when outbound HTTP is blocked.
Outbound HTTPS is blocked. There is no curl in the base image. The backup host sits behind a mail relay that is allowed to speak SMTP and almost nothing else.
You still need to know: Did it run?
Email heartbeat monitoring is heartbeat monitoring over SMTP instead of HTTP. The job sends mail to a unique address such as YOUR_REF@ping.seiri.app. Receiving that message is the check-in. If mail stops past the grace period, Seiri alerts — a dead man’s switch that works when push-over-HTTP cannot.
Seiri is push-based. It is not uptime monitoring and not APM. Email is just another transport for the same “job must check in” contract. Prefer HTTP when egress is allowed; use email when it is not.
The problem: monitoring without egress HTTP
Common environments:
- PCI / regulated segments that allow SMTP to an internal MTA only
- Legacy Unix boxes with
mail/sendmailbut no modern TLS client you trust - “Air-gapped” relative to the public internet (still able to reach an internal relay that eventually delivers outbound mail)
- Batch windows on mainframes or appliances that only expose email notifications
- Cron hosts where installing curl/openssl is a change-control fight, but mail already works
HTTP ping remains the default for most cloud VMs:
curl -fsS -m 10 --retry 3 \
https://ping.seiri.app/webhook/YOUR_ORG:YOUR_REFWhen that path is impossible, email is the escape hatch — not a second product category.
Why jobs still fail silently without email (or HTTP) heartbeats
Without any check-in:
- Crontab lines vanish after host rebuilds.
- Scripts exit 0 after skipped uploads.
- Processes hang; cron never starts the next instance the way you expect.
- Ops only discovers the gap during restore or month-end.
Error trackers need an exception. Disk “file exists” checks need someone to look. Email heartbeats (like HTTP) turn absence into the signal. See also cron job failed silently and backup failed silently.
Common approaches when HTTP is blocked
| Approach | Works when | Weakness |
|---|---|---|
| Open a temporary firewall hole for HTTPS | Security allows it | Often rejected; temporary becomes permanent debt |
| Sidecar / jump host that can HTTP ping | You can run a second process | Extra moving part; still need a success signal from the real job |
| Write a flag file; another net polls it | Shared filesystem | Poller is another failure domain |
| Email the on-call human | SMTP works | Noise; no schedule/grace automation; humans miss mail |
| Email heartbeat to Seiri | SMTP (direct or relay) works | Depends on mail delivery latency; spoofing if unconstrained |
Email-to-Seiri keeps the dead-man’s-switch semantics: expected cadence, grace, automated alert. Humans stay on Slack/PagerDuty, not on raw cron mail.
Implementation
Address format
Each Seiri monitor that accepts email check-ins uses a unique local part:
YOUR_REF@ping.seiri.appUse one address per monitor / job. Sharing one inbox across unrelated cron entries makes a healthy job mask a dead one.
HTTP equivalent (when you can use it later):
https://ping.seiri.app/webhook/YOUR_ORG:YOUR_REF
https://ping.seiri.app/webhook/YOUR_ORG:YOUR_REF/success
https://ping.seiri.app/webhook/YOUR_ORG:YOUR_REF/failCreate the monitor in cloud.seiri.app (free forever), set schedule + grace, then copy the email address from the monitor settings.
Minimal cron example
Only send mail after success:
0 2 * * * /usr/local/bin/backup.sh && \
echo "backup ok $(date -u +%Y-%m-%dT%H:%M:%SZ)" | \
mail -s "nightly-backup" YOUR_REF@ping.seiri.appIf backup.sh exits non-zero, && skips mail. No check-in → Seiri alerts after grace.
Explicit success vs failure mail (optional pattern)
Some teams send on both paths with different subjects for humans reading the relay logs — Seiri still keys off receiving a check-in for that monitor unless you use separate monitors. Prefer one monitor and only mail on success; use a separate alert path (log aggregator, exit code to a wrapper) for hard failures if you need immediate fail signals. Silence remains the missed-run signal.
0 2 * * * /usr/local/bin/run-with-mail.sh#!/usr/bin/env bash
set -euo pipefail
if /usr/local/bin/backup.sh; then
printf 'ok %s\n' "$(date -u +%FT%TZ)" | \
mail -s "backup-ok" YOUR_REF@ping.seiri.app
else
# optional: page via existing tools; do NOT ping success
exit 1
fisendmail / mailx / msmtp
Whatever client you use, requirements are the same:
- Message accepted by your MTA for delivery toward
ping.seiri.app(or your smart host that can reach it). - Sent only after the job’s success criteria.
- Stable From domain if you use allowlists.
Example with msmtp (common on locked-down hosts that talk to an internal relay):
#!/usr/bin/env bash
set -euo pipefail
/usr/local/bin/backup.sh
msmtp --account=relay YOUR_REF@ping.seiri.app <<EOF
Subject: nightly-backup
From: cron@$(hostname -f)
backup ok $(date -u +%FT%TZ)
EOFPython / Ruby / PHP when libraries exist but HTTPS does not
If the language can speak SMTP to an internal relay:
import smtplib
from email.message import EmailMessage
def email_heartbeat(ref: str, subject: str, body: str) -> None:
msg = EmailMessage()
msg["Subject"] = subject
msg["From"] = "cron@internal.example"
msg["To"] = f"{ref}@ping.seiri.app"
msg.set_content(body)
with smtplib.SMTP("smtp.internal.example", 25, timeout=30) as smtp:
smtp.send_message(msg)
# after successful work:
email_heartbeat("YOUR_REF", "etl-ok", "ok")Same rule as HTTP: call this after the side effect that defines done.
Laravel / Sidekiq / Celery
Framework jobs can use email when Http:: / Net::HTTP / requests cannot reach the public internet:
- Laravel:
Mail::raw('ok', fn ($m) => $m->to('YOUR_REF@ping.seiri.app')->subject('backup'));after success - Sidekiq: deliver via Action Mailer / raw Net::SMTP after the worker finishes
- Celery: SMTP after the task body succeeds
See Laravel scheduler, Sidekiq, Celery for HTTP variants — swap transport, keep the heartbeat placement.
Delivery latency and grace
Email is slower and jitterier than an HTTP GET. Set grace periods with relay delay in mind (minutes, not seconds). If your MTA queues outbound mail for long periods, fix the relay or you will get false missed-check-in alerts — or false confidence if mail is delayed past when you needed to know.
Spoofing and allowlists
Anyone who can send mail claiming your From address might try to fake a check-in. Mitigations:
- Prefer submission authenticated to your relay (SMTP AUTH) from the job host only
- Use monitor allowlists / expected senders when Seiri offers them for your plan
- Keep
YOUR_REFunguessable (treat like a webhook secret) - Do not publish full addresses in public repos; use config / secrets
Example: air-gapped backup host
- Backup host runs
pg_dump, encrypts, copies to tape or internal object store. - Host cannot reach
ping.seiri.appover HTTPS. - Host can
mailviasmtp.corp.example. - Corp relay is allowed to deliver to external MX for
ping.seiri.app. - Seiri monitor: daily + 90-minute grace (dump + copy + mail delay).
- Script mails
YOUR_REF@ping.seiri.apponly after the copy verifies (size / checksum). - Alert → PagerDuty. On-call does not rely on reading the backup log “sometime Monday.”
This is the same operational story as HTTP scheduled job monitoring — different wire protocol.
Comparing HTTP vs email heartbeats
| HTTP ping | Email heartbeat | |
|---|---|---|
| URL / address | https://ping.seiri.app/webhook/YOUR_ORG:YOUR_REF | YOUR_REF@ping.seiri.app |
| Latency | Usually seconds | Relay-dependent; minutes possible |
| Dependencies | Outbound HTTPS, DNS, TLS | Local MTA or smart host path to Seiri MX |
| Failure mode | curl/timeout errors in job logs | Silent mail queue / greylist delays |
| Best for | Cloud VMs, K8s with egress | Locked-down / legacy / SMTP-only segments |
Same product question either way: did the job check in on schedule? Same alert routing in Seiri. Choose transport from network policy, not preference.
Debugging “we mailed but Seiri still alerts”
- Send a manual message from the same host and account the cron uses — not from your laptop.
- Check relay logs for accept, deferral, bounce.
- Confirm the local part matches the monitor (
YOUR_REF) — typo = mail to nowhere useful. - Confirm schedule/grace — first production run after create may still be inside “waiting for first check-in” depending on product UX; send an intentional test.
- Clock skew on the host vs expected cron window — less common with heartbeats than with pure wall-clock checks, but mis-set schedules still confuse operators.
- Duplicate monitors — job mails address A; you watch address B in the UI.
# manual proof from the job host
printf 'manual test %s\n' "$(date -u +%FT%TZ)" | \
mail -s "manual-heartbeat-test" YOUR_REF@ping.seiri.appIf manual mail marks the monitor healthy but cron mail does not, compare From, envelope sender, and whether cron’s mail binary uses a different sendmail path.
Security notes specific to email
Webhook URLs are bearer secrets in practice. Email addresses are too — anyone who can deliver to that address may check in.
- Do not commit
YOUR_REF@ping.seiri.appto public repos; inject via config. - Prefer authenticated submission to your corporate relay.
- Restrict which hosts can use the relay account that is allowed to send toward
ping.seiri.app. - If a ref leaks, rotate the monitor / address in Seiri and update the job.
SPF/DKIM on your sending domain helps deliverability to Seiri’s MX; broken SPF can look like “email heartbeats are flaky” when mail never lands.
Migrating from email to HTTP later
When a segment finally allows HTTPS egress:
- Add
curl(or language HTTP) ping alongside mail for one schedule window. - Confirm HTTP check-ins appear.
- Remove the mail line; keep the same monitor if the product maps both transports to one check-in, or create a fresh HTTP monitor and retire the email one deliberately.
- Do not run forever with dual check-ins “just in case” without documenting which signal is authoritative.
Best practices
- One address per job/monitor — never share across unrelated schedules.
- Mail only on success for the missed-run switch; do not celebrate failures with a check-in.
- Prove the path — send a manual test message; confirm Seiri marks healthy before relying on it.
- Size grace for SMTP delay, not only job runtime.
- Authenticate to the relay; avoid open forwarders.
- Keep subjects boring and stable — machine-readable, low PII.
- Prefer HTTP (
https://ping.seiri.app/webhook/YOUR_ORG:YOUR_REF) when policy allows — simpler, lower latency. - Kubernetes — if the cluster can egress HTTPS, use HTTP heartbeats or seiri-kube-agent (product page); use email only when NetworkPolicy blocks HTTPS but allows SMTP.
- Fix SPF/DKIM on the sending domain if delivery is unreliable.
- Rotate leaked refs the same way you rotate webhook URLs.
Conclusion
Email heartbeat monitoring is cron / job check-in for environments that can send mail but cannot open outbound HTTPS. Same Seiri question — Did it run? — answered by delivery to YOUR_REF@ping.seiri.app instead of a webhook GET.
Start free at cloud.seiri.app. Related: email heartbeat monitoring (product), cron job monitoring complete guide, heartbeat monitoring explained, Kubernetes CronJob monitoring.
Transform Your Monitoring
Get started with Seiri
Heartbeat monitoring for cron jobs, workers, and Kubernetes — know when scheduled work goes silent.
Start free- Free forever
- No credit card required
- Cancel anytime
Would you know if this job stopped running?
Seiri watches your cron jobs, workers, and Kubernetes CronJobs, and alerts you the moment one goes silent. Free forever, no credit card.
Start free