Shell Script: Pipe to Email with PayloadRelay
Use a Bash script to send command output or text to a PayloadRelay endpoint.
2 min read
Build a shell utility that sends text to email through PayloadRelay. Pipe command output, send a short message, or forward a log extract from the terminal.
Purpose#
Use this guide to:
- Create a
pr-emailscript that sends standard input or arguments to a PayloadRelay endpoint. - Pipe command output to email.
- Set the subject, the format, and the recipient options.
- Install the script for general use.
Before you start#
- Create a PayloadRelay endpoint that accepts
POSTwith theJSONorPlain textpayload format. - Attach a confirmed email target to the endpoint.
- Install
curlandjqon the system. - Use Bash 4 or later. Bash is included in most Linux distributions and is available with Homebrew on macOS.
Procedure#
1. Create the endpoint#
- Open
Endpointsand selectCreate endpoint. - Set the accepted method to
POST. - Set the payload format to
JSON. - In
Outputs, attach your confirmed email target. - Save and copy the endpoint URL.
2. Basic script#
Create a file with the name pr-email:
#!/bin/bash
set -euo pipefail
# Configuration
PAYLOADRELAY_ENDPOINT="${PAYLOADRELAY_ENDPOINT:-https://api.payloadrelay.com/relay/YOUR_ENDPOINT_ID}"
usage() {
cat <<EOF
Usage: pr-email [OPTIONS] "Subject line"
command | pr-email "Subject line"
Send text to email via PayloadRelay.
Options:
-e ENDPOINT Override the PayloadRelay endpoint URL
-b BODY Pass body as argument instead of stdin
-h Show this help message
Environment:
PAYLOADRELAY_ENDPOINT Default endpoint URL
Examples:
echo "Hello" | pr-email "Test Message"
pr-email -b "Server rebooted" "Server Alert"
df -h | pr-email "Disk Report"
EOF
exit 0
}
BODY=""
while getopts "e:b:h" opt; do
case $opt in
e) PAYLOADRELAY_ENDPOINT="$OPTARG" ;;
b) BODY="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
SUBJECT="${1:-Notification from pr-email}"
# Read from stdin if no body argument and stdin is not a terminal
if [ -z "$BODY" ] && [ ! -t 0 ]; then
BODY=$(cat)
fi
if [ -z "$BODY" ]; then
echo "Error: No body provided. Pipe input or use -b flag." >&2
exit 1
fi
# Send to PayloadRelay
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$PAYLOADRELAY_ENDPOINT" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg subject "$SUBJECT" --arg body "$BODY" \
'{subject: $subject, body: $body}')")
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
RESPONSE_BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo "✓ Sent: $SUBJECT"
else
echo "✗ Failed (HTTP $HTTP_CODE): $RESPONSE_BODY" >&2
exit 1
fi3. Usage examples#
# Disk usage report
df -h | pr-email "Disk Report"
# System info
uname -a | pr-email "System Info"
# Docker container status
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | pr-email "Container Status"
# Git log
git log --oneline -10 | pr-email "Recent Commits"
# Tail logs
tail -50 /var/log/app.log | pr-email "Recent App Logs"# Quick message
pr-email -b "Deployment complete for v2.4.0" "Deploy Notification"
# Multi-line body
pr-email -b "Server: web-01
Status: rebooted
Time: $(date -u)" "Server Alert"echo "Alert content" | pr-email -e "https://api.payloadrelay.com/relay/OTHER_ENDPOINT_ID" "Custom Alert"4. Extended script with more options#
This extended version adds timestamps, the host name, and format options:
#!/bin/bash
set -euo pipefail
PAYLOADRELAY_ENDPOINT="${PAYLOADRELAY_ENDPOINT:-https://api.payloadrelay.com/relay/YOUR_ENDPOINT_ID}"
PAYLOADRELAY_TOKEN="${PAYLOADRELAY_TOKEN:-}"
usage() {
cat <<EOF
Usage: pr-email [OPTIONS] "Subject line"
command | pr-email [OPTIONS] "Subject line"
Send text to email via PayloadRelay.
Options:
-e ENDPOINT Override the PayloadRelay endpoint URL
-t TOKEN Bearer token for authenticated endpoints
-b BODY Pass body as argument instead of stdin
-m Include machine metadata (hostname, timestamp)
-q Quiet mode (no output on success)
-h Show this help message
Environment:
PAYLOADRELAY_ENDPOINT Default endpoint URL
PAYLOADRELAY_TOKEN Default Bearer token
Examples:
echo "Hello" | pr-email "Test Message"
pr-email -b "Server rebooted" "Server Alert"
df -h | pr-email -m "Disk Report"
cat report.txt | pr-email -t mytoken "Weekly Report"
EOF
exit 0
}
BODY=""
INCLUDE_META=false
QUIET=false
while getopts "e:t:b:mqh" opt; do
case $opt in
e) PAYLOADRELAY_ENDPOINT="$OPTARG" ;;
t) PAYLOADRELAY_TOKEN="$OPTARG" ;;
b) BODY="$OPTARG" ;;
m) INCLUDE_META=true ;;
q) QUIET=true ;;
h) usage ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
SUBJECT="${1:-Notification from pr-email}"
# Read from stdin if no body argument and stdin is not a terminal
if [ -z "$BODY" ] && [ ! -t 0 ]; then
BODY=$(cat)
fi
if [ -z "$BODY" ]; then
echo "Error: No body provided. Pipe input or use -b flag." >&2
exit 1
fi
# Build JSON payload
JSON_ARGS=(--arg subject "$SUBJECT" --arg body "$BODY")
JSON_TEMPLATE='{subject: $subject, body: $body}'
if [ "$INCLUDE_META" = true ]; then
JSON_ARGS+=(
--arg hostname "$(hostname)"
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
--arg user "$(whoami)"
)
JSON_TEMPLATE='{subject: $subject, body: $body, hostname: $hostname, timestamp: $timestamp, user: $user}'
fi
PAYLOAD=$(jq -n "${JSON_ARGS[@]}" "$JSON_TEMPLATE")
# Build curl arguments
CURL_ARGS=(-s -w "\n%{http_code}" -X POST "$PAYLOADRELAY_ENDPOINT"
-H "Content-Type: application/json"
-d "$PAYLOAD")
if [ -n "$PAYLOADRELAY_TOKEN" ]; then
CURL_ARGS+=(-H "Authorization: Bearer $PAYLOADRELAY_TOKEN")
fi
# Send
RESPONSE=$(curl "${CURL_ARGS[@]}")
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
if [ "$QUIET" != true ]; then
echo "✓ Sent: $SUBJECT"
fi
else
RESPONSE_BODY=$(echo "$RESPONSE" | sed '$d')
echo "✗ Failed (HTTP $HTTP_CODE): $RESPONSE_BODY" >&2
exit 1
fi5. Installation#
# Make executable
chmod +x pr-email
# Option A: copy to a directory already in PATH
sudo cp pr-email /usr/local/bin/
# Option B: add the script's directory to PATH
echo 'export PATH="$PATH:/path/to/scripts"' >> ~/.bashrc
source ~/.bashrcAdd the export to ~/.bashrc or ~/.zshrc:
export PAYLOADRELAY_ENDPOINT="https://api.payloadrelay.com/relay/YOUR_ENDPOINT_ID"
# Optional: if your endpoint requires auth
export PAYLOADRELAY_TOKEN="your-bearer-token"echo "Installation test" | pr-email "pr-email Test"6. Practical recipes#
# In crontab (crontab -e):
0 9 * * 1 df -h | pr-email "Weekly Disk Report"
0 8 * * * docker ps -a --format "table {{.Names}}\t{{.Status}}" | pr-email "Daily Container Status"# Notify when a build finishes
make all 2>&1 | pr-email "Build Output"
# Notify when a backup completes
pg_dump mydb | gzip > backup.gz && pr-email -b "Backup completed: $(ls -lh backup.gz | awk '{print $5}')" "Backup Done"#!/bin/bash
set -euo pipefail
trap 'echo "Script failed at line $LINENO" | pr-email "Script Failure: $(basename $0)"' ERR
# Rest of your script...
process_data
generate_report# Send filtered logs
grep "ERROR" /var/log/app.log | tail -20 | pr-email "Recent Errors"
# Send a formatted table
ps aux --sort=-%mem | head -11 | pr-email "Top Memory Processes"
# Send JSON-formatted data
curl -s https://api.example.com/status | jq . | pr-email "API Status"Expected result#
pr-emailis executable and available in PATH.echo "test" | pr-email "Test"sends an email and prints✓ Sent: Test.- The piped command output arrives in the email body.
- A request appears in PayloadRelay
Request activityasCompleted(ACCEPTED).
Common issues#
command not found: pr-email: Make sure that the script is executable and that its location is inPATH.Error: No body provided: Pipe input to the script, or use the-bflag to give a body.jq: command not found: Installjq, for example withbrew install jqon macOS orapt install jqon Ubuntu.Failed (HTTP 401): SetPAYLOADRELAY_TOKEN, or use-tfor an authenticated endpoint.- The email contains only part of a large output: PayloadRelay limits the payload size for each plan. Pipe the output through
headortailto make it smaller.