#! /bin/bash # Save incoming mail as comment # Usage: # Step1. Add script into forward(5) for MDA # # echo '|" --output_dir "' >>~/.forward # # Step2. Insert related html file into target page, the following example use element # * Please replace for your target page, relative to value of --output_dir # * Set for mail address which can achive MDA # * Change in data attribute of based on routing if necessary # # #
# [Comment on this page] # # #
# # 0. Work as CGI {{{ # Print this script as HTTP Response if [ -n "$REQUEST_METHOD" ]; then <<-RESPONSE cat Status: 200 Content-Type: text/plain $(cat $0) RESPONSE exit 0 fi # }}} # 1. Check mail is for comment {{{ # Restore mail into variables MAIL="$(tr -d '\r')" # join multi-line field value into one line header="$(<<<"$MAIL" sed '/^$/ q; :a; N; s/\n\s\+//; ta')" body="$(<<<"$MAIL" sed -n '/^$/,$ p' | sed '1d')" # determine mail is for comment by pattern pattern='^Subject: .*[cC]omment on page:? +(https?://[^/]+)?(/?[^ ]+).*$' <<<"$header" grep -E "$pattern" >/dev/null || exit 0 # }}} # 2. Get necessary variables from arguments {{{ while [[ "$1" =~ ^-- && ! "$1" == "--" ]]; do case $1 in --output_dir ) shift; output_dir=$1 ;; --markdown_bin ) shift; markdown_bin=$1 ;; *) shift ;; esac shift done export PATH=/bin:/usr/bin:/usr/local/bin:~/.local/bin output_dir=${output_dir:-$(dirname $0)} markdown_bin=${markdown_bin:-$(which markdown 2>/dev/null)} [ -x "$markdown_bin" ] || markdown_bin=cat # }}} # 3. Read header fields {{{ # enable execute last command in pipe under current shell shopt -s lastpipe; set +m; # save each field of header into variables echo "$header" | \ while read field value; do echo "$field" "$value" >>/tmp/header declare field=$(<<<$field tr [:lower:] [:upper:] | tr '-' '_' | tr -d ':') declare $field="${value}" done DATE=${DATE:+$(date --rfc-3339 seconds --date "$DATE")} # }}} # 4. Get path of output file {{{ path=$(<<<"$header" sed -En "\\|${pattern}| {s//\\2/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 # get output path [[ "$path" =~ /$ ]] && path+=index path=${path#/} path=${path/.html} output=$output_dir/${path}.comment.html umask 022; mkdir -p $(dirname $output) # }}} # 5. Get comment from mail body {{{ printTextPart() { boundary=$1 beginPat="\\|^--${boundary}\$|" endPat="\\|^--${boundary}(--)?\$|" sed -En "${beginPat},${endPat} { \@^Content-Type: text/plain@,$ {1,/^$/d; ${beginPat}d; p} }" } # check mail includes multiple part boundary="$(<<<"$CONTENT_TYPE" sed -En 's/^.*boundary="?([^"]+)"?.*$/\1/p')" if [ -n "${boundary}" ]; then # print mail part in MIME: text/plain body="$(<<<"$body" printTextPart ${boundary})" fi # }}} # 6. Write comment to output file {{{ # set STDOUT to $output, with readable permission for everyone umask 133 # add basic html layout for output file if necessary {{{ if [ ! -f $output ] || ! xmllint --html --nofixup-base-uris $output &>/dev/null; then <<-LAYOUT cat >$output
LAYOUT 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 {{{ # FIXME prevent pattern shown in
 block
<<-COMMENT sed -i "${line:-/
    /}r /dev/stdin" $output
  • [reply]
    $(<<<"${body}" ${markdown_bin})
    replies
  • COMMENT # }}} # }}} # vim:fdm=marker fdl=0