aerc-claude-correct
1 #!/usr/bin/env bash 2 # Correct email content using Claude while preserving email encoding 3 # Use --draft flag to save as draft instead of outputting to stdout 4 5 set -euo pipefail 6 7 SAVE_AS_DRAFT=false 8 if [[ "${1:-}" == "--draft" ]]; then 9 SAVE_AS_DRAFT=true 10 fi 11 12 if ! command -v claude &> /dev/null; then 13 echo "Error: claude command not found" >&2 14 exit 1 15 fi 16 17 TMPDIR=$(mktemp -d) 18 trap 'rm -rf "$TMPDIR"' EXIT 19 20 cat > "$TMPDIR/email.raw" 21 22 if ! command -v mshow &> /dev/null; then 23 echo "Error: mshow (from mblaze) not found" >&2 24 cat "$TMPDIR/email.raw" 25 exit 1 26 fi 27 28 # Extract headers (everything before first empty line) 29 sed '/^$/q' "$TMPDIR/email.raw" > "$TMPDIR/headers" 30 31 content_type=$(grep -i "^Content-Type:" "$TMPDIR/headers" | head -1 || echo "") 32 33 if echo "$content_type" | grep -qi "multipart"; then 34 echo "Error: Multipart emails not yet supported" >&2 35 cat "$TMPDIR/email.raw" 36 exit 1 37 fi 38 39 # Extract body (everything after first empty line) 40 sed '1,/^$/d' "$TMPDIR/email.raw" > "$TMPDIR/body.raw" 41 42 encoding=$(grep -i "^Content-Transfer-Encoding:" "$TMPDIR/headers" | head -1 | cut -d: -f2 | tr -d ' \r' || echo "") 43 44 # Decode body based on encoding 45 case "$encoding" in 46 "quoted-printable") 47 perl -pe 's/=([0-9A-Fa-f]{2})/chr(hex($1))/eg; s/=\r?\n//g' < "$TMPDIR/body.raw" > "$TMPDIR/body.decoded" 48 ;; 49 "base64") 50 base64 -d < "$TMPDIR/body.raw" > "$TMPDIR/body.decoded" 2>/dev/null || cp "$TMPDIR/body.raw" "$TMPDIR/body.decoded" 51 ;; 52 *) 53 cp "$TMPDIR/body.raw" "$TMPDIR/body.decoded" 54 ;; 55 esac 56 57 prompt="Correct grammar and spelling errors. Output ONLY the corrected text - no explanations, no preamble, just the raw corrected content." 58 59 if ! claude "$prompt" < "$TMPDIR/body.decoded" > "$TMPDIR/body.corrected" 2>&1; then 60 echo "Error: Claude correction failed" >&2 61 cat "$TMPDIR/email.raw" 62 exit 1 63 fi 64 65 { 66 cat "$TMPDIR/headers" 67 echo "" 68 case "$encoding" in 69 "quoted-printable") 70 perl -pe 's/([^\x20-\x7E])/sprintf("=%02X", ord($1))/eg' < "$TMPDIR/body.corrected" 71 ;; 72 "base64") 73 base64 < "$TMPDIR/body.corrected" 74 ;; 75 *) 76 cat "$TMPDIR/body.corrected" 77 ;; 78 esac 79 } > "$TMPDIR/final.eml" 80 81 if [[ "$SAVE_AS_DRAFT" == "true" ]]; then 82 if command -v aerc-save-draft &> /dev/null; then 83 cat "$TMPDIR/final.eml" | aerc-save-draft >&2 84 echo "Corrected email saved as draft" >&2 85 cat "$TMPDIR/final.eml" 86 else 87 echo "Error: aerc-save-draft not found" >&2 88 cat "$TMPDIR/final.eml" 89 exit 1 90 fi 91 else 92 cat "$TMPDIR/final.eml" 93 fi