From 2ef7db0d4cc14267db389ac209f8d3753d14fe99 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 5 Dec 2024 12:18:42 +0800 Subject: improve comment.sh --- bin/mail/comment.sh | 90 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/bin/mail/comment.sh b/bin/mail/comment.sh index 807bcb2..d096ee8 100755 --- a/bin/mail/comment.sh +++ b/bin/mail/comment.sh @@ -1,41 +1,95 @@ #! /bin/bash +# Save incoming mail as comment +# Usage: +# echo '|' >>~/.forward + +mailto=${mailto:-$(whoami)@${HOSTNAME:?HOSTNAME is not specified}} output_dir=${output_dir:-/srv/http} +# Check mail is for comment {{{ + # Restore mail into variable MAIL="$(tr -d '\r')" -headers="$(<<<"$MAIL" sed '/^$/ q')" -contents="$(<<<"$MAIL" sed -n '/^$/,$ p' | sed '1d')" +header="$(<<<"$MAIL" sed '/^$/ q')" +body="$(<<<"$MAIL" sed -n '/^$/,$ p' | sed '1d')" + +# determine mail is for comment by pattern +pattern='^Subject: .*comment on (https?://)?([^/]+)?/([^ ]+)$' +<<<"$header" grep -E "$pattern" >/dev/null || exit 0 + +# }}} +# Process header fields {{{ # enable execute last command in pipe under current shell shopt -s lastpipe; set +m; -# get route (target page of comment) and id -<<<"$MAIL" sed -En '/^To: comment+/ {s/^To: comment\+([^+]+)\+?(.*)@.*$/\1 \2/p; q}; /^$/q' \ -| read route id +# save each field of header into variables +<<<"$header" grep '^[a-zA-Z]' \ +| while read field value; do + declare field=$(<<<$field tr [:lower:] [:upper:] | tr '-' '_' | tr -d ':') + declare $field="${value}" +done +DATE=${DATE:+$(date --rfc-3339 seconds --date "$DATE")} -# sender want comment on some page, but find no route for this -if [ $route = "" ]; then - echo 'rcpt "comment+" not matched' >&2 +# }}} +# Get path of output file {{{ + +path=$(<<<"$header" sed -En "\\|${pattern}| {s//\\3/p; q}") + +# sender want comment on some page, but find no path for this +if [ $path = "" ]; then + echo 'Cannot get target of comment from mail' >&2 exit 1 fi -output=$output_dir/${route#/}.comment -exec 1>>$output +# get output path +[[ "$path" =~ '/$' ]] && path+=index +path=${path#/} +path=${path/.html} +output=$output_dir/${path}.comment.html + +# }}} +# Get comment from mail body {{{ # check mail includes multiple part -<<<"$headers" grep '^Content-Type:.*mixed' >/dev/null -if [ $? -eq 0 ]; then - boundary="$(<<<"$headers" sed -En 's/^Content-Type:.*boundary="(.*)".*$/\1/p')" +if [[ "$CONTENT_TYPE" =~ mixed ]]; then + boundary="$(<<<"$CONTENT_TYPE" sed -En 's/^.*boundary="(.*)".*$/\1/p')" if [ $boundary = "" ]; then echo 'cannot get boundary from mail header' >&2 exit 1 fi # print content of first mail part - pattern="\\@^--${boundary}\$@" - <<<"$contents" sed -n "${pattern},${pattern} p" | sed -n "1,4d; ${pattern} q; p" -else - # print content - <<<"$contents" sed '/^$/,$ p' + boundaryPat="\\|^--${boundary}\$|" + <<<"$body" sed -n "${boundaryPat},${boundaryPat} p" | sed -n "1,4d; ${boundaryPat} q; p" \ + | read body fi + +# }}} +# Write comment to output file {{{ + +# add basic html layout for output file if necessary +if [ ! -f $output ] || ! xmllint --html --nofixup-base-uris $output &>/dev/null; then + echo -e '
    \n
' >$output +fi +# get line of insert position by header field "In-Reply-To" +if [ -n "${IN_REPLY_TO}" ]; then + line=$(grep -n "^$" $output | cut -d':' -f1) +fi + +# insert comment into output file +<<-COMMENT sed -i "${line:-1}r /dev/stdin" $output +
  • + + [reply] + + $(<<<"${body}" markdown) + +
      + +
    +
  • +COMMENT + +# }}} -- cgit v1.2.3-70-g09d2