Files

207 lines
7.1 KiB
Bash

#!/bin/bash
# Morning Email Rollup - Important emails from the last 24 hours
# Temporarily disable strict mode for debugging
# set -uo pipefail
GOG_ACCOUNT="${GOG_ACCOUNT:-your[email protected]}"
MAX_EMAILS="${MAX_EMAILS:-10}" # Default to 10, can be overridden via environment variable
WORKSPACE="${BOT_WORKSPACE:-$HOME/bot}"
LOG_FILE="${WORKSPACE}/morning-email-rollup-log.md"
# Initialize log
mkdir -p "$(dirname "$LOG_FILE")"
# Log with timestamp
log() {
echo "- [$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
echo "📧 **Morning Email Rollup** - $(date '+%A, %B %d, %Y')"
echo ""
log "🔄 Starting morning email rollup"
# Check for calendar events (gog) - graceful fallback if not installed
if command -v gog &> /dev/null; then
TODAY=$(date '+%Y-%m-%d')
TOMORROW=$(date -d "$TODAY + 1 day" '+%Y-%m-%d')
CALENDAR_EVENTS=$(gog calendar events primary --from "$TODAY" --to "$TOMORROW" --account "$GOG_ACCOUNT" 2>/dev/null)
# Check if there are events (more than just the header line)
EVENT_COUNT=$(echo "$CALENDAR_EVENTS" | tail -n +2 | grep -c . 2>/dev/null || echo "0")
# Ensure EVENT_COUNT is a clean number
EVENT_COUNT=$(echo "$EVENT_COUNT" | tr -cd '0-9')
if [[ "$EVENT_COUNT" -gt 0 ]]; then
echo "📅 **$EVENT_COUNT calendar event(s) today**"
# Parse and format events (skip header line)
echo "$CALENDAR_EVENTS" | tail -n +2 | while IFS= read -r line; do
[[ -z "$line" ]] && continue
# Parse gog output: ID START END SUMMARY
start_full=$(echo "$line" | awk '{print $2}')
end_full=$(echo "$line" | awk '{print $3}')
title=$(echo "$line" | awk '{$1=$2=$3=""; print $0}' | sed 's/^[[:space:]]*//')
# Extract time from ISO format (e.g., 2026-01-15T05:00:00-07:00)
start_time=$(echo "$start_full" | cut -d'T' -f2 | cut -d'-' -f1 | cut -d'+' -f1 | cut -d':' -f1-2)
end_time=$(echo "$end_full" | cut -d'T' -f2 | cut -d'-' -f1 | cut -d'+' -f1 | cut -d':' -f1-2)
# Convert to 12-hour format
start_12h=$(date -d "$start_time" '+%I:%M %p' 2>/dev/null | sed 's/^0//' | sed 's/:00//')
end_12h=$(date -d "$end_time" '+%I:%M %p' 2>/dev/null | sed 's/^0//' | sed 's/:00//')
echo "• $title - $start_12h to $end_12h"
done
echo ""
log "📅 Calendar events listed ($EVENT_COUNT events)"
fi
fi
echo ""
# Search for important/starred emails from last 24 hours
IMPORTANT_EMAILS=$(gog gmail search 'is:important OR is:starred newer_than:1d' --max 20 --account "$GOG_ACCOUNT" --json 2>/dev/null)
if [[ -z "$IMPORTANT_EMAILS" ]] || [[ "$IMPORTANT_EMAILS" == "null" ]]; then
echo "✅ No important emails in the last 24 hours."
log "✅ No important emails found"
exit 0
fi
# Count emails
EMAIL_COUNT=$(echo "$IMPORTANT_EMAILS" | jq -r '.threads | length' 2>/dev/null || echo "0")
if [[ "$EMAIL_COUNT" -eq 0 ]]; then
echo "✅ No important emails in the last 24 hours."
log "✅ No important emails found"
exit 0
fi
echo "📧 **$EMAIL_COUNT important email(s) from last 24 hours**"
if [[ $EMAIL_COUNT -gt $MAX_EMAILS ]]; then
echo "(Showing top $MAX_EMAILS)"
fi
echo ""
# Function to summarize email using gemini
summarize_email() {
local body="$1"
# Check if gemini is available
if ! command -v gemini &> /dev/null; then
# Fallback: clean and return first readable sentence if gemini not available
echo "$body" | sed 's/<[^>]*>//g' | sed 's/&[a-z]*;//g' | tr -s ' ' | sed 's/^ *//' | sed 's/\./.\n/g' | head -1 | head -c 150
return
fi
# Use gemini to get a 1-sentence summary
# Pass body as part of the prompt (piping doesn't work with prompts)
# IMPORTANT: Redirect stdin to /dev/null to prevent consuming the while loop's input
local summary
summary=$(gemini --model gemini-2.0-flash "Summarize this email in exactly 1 sentence of natural language. Make it medium to long length. Don't use quotes:
$body" </dev/null 2>&1 | grep -v "Loaded cached" | tail -1)
# Clean up the summary (remove any quotes, newlines, extra spaces)
summary=$(echo "$summary" | sed 's/^["'\'']//' | sed 's/["'\'']$//' | tr -s ' ' | sed 's/^ *//' | sed 's/ *$//' | head -1)
# If gemini failed or returned empty, return cleaned body snippet
if [[ -z "$summary" ]] || [[ ${#summary} -lt 10 ]]; then
echo "$body" | sed 's/<[^>]*>//g' | sed 's/&[a-z]*;//g' | tr -s ' ' | sed 's/^ *//' | head -c 200
else
echo "$summary"
fi
}
# Process up to MAX_EMAILS
email_counter=0
# Use a temporary file for the thread IDs to avoid subshell issues
THREAD_IDS=$(echo "$IMPORTANT_EMAILS" | jq -r '.threads[] | "\(.id)"')
# Use a temp file to avoid <<< issues
TEMP_THREAD_IDS=$(mktemp)
echo "$THREAD_IDS" > "$TEMP_THREAD_IDS"
while IFS= read -r thread_id; do
[[ -z "$thread_id" ]] && continue
# Limit to MAX_EMAILS
if [[ $email_counter -ge $MAX_EMAILS ]]; then
break
fi
email_counter=$((email_counter + 1))
# Skip thread_id if it's not an actual ID (jq output validation)
if [[ "$thread_id" =~ ^[a-f0-9]{12,}$ ]]; then
# Continue processing
:
else
continue
fi
# Get email details
email_data=$(gog gmail get "$thread_id" --account "$GOG_ACCOUNT" 2>/dev/null) || true
if [[ -z "$email_data" ]]; then
echo "DEBUG: No email data for thread_id=$thread_id" >&2
continue
fi
# Extract fields
from=$(echo "$email_data" | grep "^from" | cut -f2-)
subject=$(echo "$email_data" | grep "^subject" | cut -f2-)
# Clean subject - remove extra quotes and trim whitespace
subject=$(echo "$subject" | sed 's/^["'\'']//' | sed 's/["'\'']$//' | sed 's/^ *//' | sed 's/ *$//')
# Get sender name only (strip email address)
sender_name=$(echo "$from" | sed 's/<.*>//' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
if [[ -z "$sender_name" ]]; then
sender_name="$from"
fi
# Get email body (after headers)
body=$(echo "$email_data" | awk 'BEGIN{body=0} /^$/{body=1; next} body{print}')
# Clean body - remove HTML/CSS and convert to plain text
cleaned_body=$(echo "$body" | \
sed 's/<[^>]*>//g' | \
sed 's/&nbsp;/ /g' | \
sed 's/&amp;/\&/g' | \
sed 's/&lt;/</g' | \
sed 's/&gt;/>/g' | \
sed 's/@media[^}]*}//g' | \
sed 's/{[^}]*}//g' | \
sed 's/\[[^]]*\]//g' | \
tr '\n' ' ' | \
sed 's/\\n/ /g' | \
sed 's/ */ /g' | \
sed 's/^ *//' | \
head -c 5000)
# Get AI summary
summary=$(summarize_email "$cleaned_body") || true
# Check read/unread status
labels=$(echo "$email_data" | grep "^label_ids" | cut -f2-)
if [[ "$labels" == *"UNREAD"* ]]; then
read_marker="🔴 "
else
read_marker="🟢 "
fi
echo "${read_marker}**${sender_name}: ${subject}**"
echo " $summary"
echo ""
done < "$TEMP_THREAD_IDS"
# Clean up temp file
rm -f "$TEMP_THREAD_IDS"
log "✅ Rollup complete: $EMAIL_COUNT emails"
echo ""
echo "---"
echo "💡 **Need more details?** Ask me to read or search specific emails."