AS_INIT[]m4_divert_push([HEADER-COPYRIGHT])dnl # @configure_input@ # mailnotify (GNU @PACKAGE@) version 1.0 # Written by Gary V. Vaughan # Copyright (C) 2004, 2006, 2010 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # Mailnotify is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Mailnotify is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with mailnotify; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTIONS]... # # -x --debug enable verbose shell tracing # --dry-run don't actually post the mime message # -f FILE --filename=FILE content of this part # -h FILE --headers=FILE read additional headers from FILE # -m TYPE --mime-type=TYPE mime-type of this part # -o FILE --output-file=FILE output to FILE instead of sending # -v --verbose run in verbose mode # --version print version information # -? --help print short or long help message # Assemble a (possibly multi-part) mime message and hand it to the local # sendmail for onward delivery. MUAs tend to mangle patch attachments in # various ways: not setting the mime-type correctly, line wrapping the # patch itself, escaping certain values, etc. This script is designed to # make it easier to send a patch as a MIME attachment, though it is general # enough that it might be useful otherwise. # For example to send a patch as an attachment, assuming the patch itself # is in PATCHFILE: # # echo 'From: me@example.org' > headers # echo 'To: patch-list@foo.org' >> headers # echo 'Subject: FYI: PATCHFILE' >> headers # echo 'Cc: someone@example.org' >> headers # echo 'Applied this patch to HEAD' > body # $progname -h headers -f body -m text/plain -f PATCHFILE -m text/x-patch # # There is no set order or requirement for mail headers in the headers # file, though you will obviously need someone's address in 'To:', and # it's not polite to omit the 'Subject:' header... # You will probably find using this script in conjunction with clcommit # saves you a lot of typing. # Report bugs to : ${HOST=`hostname`} : ${SENDMAIL=sendmail} PROGRAM=mailnotify m4_divert_pop m4_include([getopt.m4sh]) M4SH_VERBATIM([[ sed_mail_address='s,^.*<\(.*\)>.*$,\1,' ]]) dnl SHORT LONG DEFAULT INIT dnl ---------------------------------------------------------------------- dnl There are several options supported below for backwards compatibility, dnl but which are not mentioned in the help. M4SH_GETOPTS( [C^!], [--carbon-copy], [], [], [F^!], [--from], [], [], [f@+], [--filename], [], [], [h@!], [--headers], [], [], [m+!], [--mime-type], [], [ case [$]1 in text/*) ;; */*) func_error "\`[$]1': only text/* mime-types supported" ;; *) func_error "invalid mime-type, \`[$]1'" exit_cmd=exit ;; esac], [n], [], [], [], [o!], [--output-file], [], [], [s^!], [--subject], [], [], [v], [--verbose], [], [], [], [--dry-run|--dryrun], [], [], [ # ensure destination address(es) available test [$]# -gt 0 || grep '^\(To\|Cc\|Bcc\): ' "${opt_headers-nosuchfile}" >/dev/null 2>&1 || func_fatal_help "no destination address" # validate headers test "$opt_headers" && { test -n "$opt_carbon_copy" && grep "^Cc: *" "$opt_headers" >/dev/null 2>&1 && { func_error "specify \`Cc:' in either \`$opt_headers' or with \`--carbon-copy'." exit_cmd=exit } test -n "$opt_from" && grep "^From: *" "$opt_headers" >/dev/null 2>&1 && { func_error "specify \`From:' in either \`$opt_headers' or with \`--from'." exit_cmd=exit } test -n "$opt_subject" && grep "^Subject: *" "$opt_headers" >/dev/null 2>&1 && { func_error "specify \`Subject:' in either \`$opt_headers' or with \`--subject'." exit_cmd=exit } } # validate mime parts if test "${opt_mime_type_num-0}" -ne "${opt_filename_num-0}"; then func_fatal_error "One part is incomplete -- each part needs a filename and a mime-type" fi if test -z "$opt_output_file"; then test -f "$opt_headers" || if test -z "$opt_subject" || eval test -z \"\$opt_mime_type_$opt_mime_type_num\" || eval test -z \"\$opt_filename_$opt_filename_num\"; then func_fatal_error "if output is not directed to a file -s, -f, and -m are all required" fi else eval test -n \"\$opt_filename_$opt_filename_num\" || func_fatal_error "-f is required." eval test -n \"\$opt_mime_type_$opt_mime_type_num\" || func_fatal_error "with output directed to a file, -m is required" fi # validate $opt_dry_run $opt_dry_run && SENDMAIL="echo $SENDMAIL" ]) M4SH_VERBATIM([[ # Bail out on command errors! set -e # func_headers outfile destination # Generate common headers to OUTFILE, where DESTINATION is a comma # separated list of fully qualified destination addresses. func_headers () { $opt_debug my_outfile="$1" my_destination="$2" my_sed_version_no=' /^# '$PROGRAM' (GNU / { s/^# .*version // p } d' $opt_dry_run || { echo "User-Agent: $PROGRAM/`$SED \"$my_sed_version_no\" < $progpath`" echo "MIME-Version: 1.0" # Deprecated command line options take precedence at the moment my_elide="Bcc" test -n "$opt_from" && my_elide="${my_elide+$my_elide\|}From" && eval echo From: $opt_from test -n "$my_destination" && my_elide="${my_elide+$my_elide\|}To" && eval echo To: $my_destination test -n "$opt_carbon_copy" && my_elide="${my_elide+$my_elide\|}Cc" && eval echo CC: $opt_carbon_copy test -n "$opt_subject" && my_elide="${my_elide+$my_elide\|}Subject" && eval echo Subject: $opt_subject # Plus any additional headers test -n "$opt_headers" && $SED "/^\($my_elide\): */d" "$opt_headers" } > "$my_outfile" : } # func_single_content outfile # Send the only message part as a single mime mail part. func_single_content () { $opt_debug my_outfile="$1" $opt_dry_run || cat >> "$my_outfile" <> "$my_outfile" Content-Type: multipart/mixed; boundary="$boundary" This is a multimedia message in MIME format. If you are reading this prefix, your mail reader does not understand MIME. You may wish to look into upgrading to a mime-aware mail reader. EOF i=0 while test $i -lt $opt_filename_num do i=`expr 1 + $i` eval file=\"\$opt_filename_$i\" name=`echo "$file" | $SED $basename` { echo "" echo "--$boundary" if test $i -gt 1; then eval echo \"Content-Type: \$opt_mime_type_$i\;\" echo " name=\"$name\"" else eval echo \"Content-Type: \$opt_mime_type_$i\" fi echo "Content-Transfer-Encoding: 7bit" echo "" cat "$file" } >> "$my_outfile" done { echo "" echo "--${boundary}--" echo "" } >> "$my_outfile" } : } # func_sendmail infile destination [from] # Send the message in INFILE to the space delimited list of destination # addresses in DESTINATION. If FROM is given, it is the address the # mail purports to be from. # BEWARE: Many MTAs will refuse mail where FROM does not match the actual # sending domain. func_sendmail () { $opt_debug my_infile="$1" my_destination="$2" my_from="$3" $opt_dry_run && my_infile=/dev/null from_name=`eval echo "X$my_from" | $Xsed -e 's, *<.*> *$,,'` from_addr=`eval echo "X$my_from" | $Xsed -e "$sed_mail_address"` save_PATH="$PATH" PATH="/usr/lib:/usr/sbin:$PATH" $opt_dry_run || { save_IFS="$IFS" IFS=':' for try_sendmail_dir in $PATH; do IFS="$save_IFS" PATH="$save_PATH" if test -x "$try_sendmail_dir/$SENDMAIL"; then SENDMAIL="$try_sendmail_dir/$SENDMAIL" break fi done IFS="$save_IFS" PATH="$save_PATH" test -x "$SENDMAIL" || func_fatal_error "sendmail executable not found" } func_verbose "Delivering mail, please wait..." if test -n "$from_name"; then $SENDMAIL -F "$from_name" -f "$from_addr" $my_destination < "$my_infile" elif test -n "$from_addr"; then $SENDMAIL -f "$from_addr" $my_destination < "$my_infile" else $SENDMAIL $my_destination < "$my_infile" fi if test $? -eq 0; then func_verbose "...succeeded." $opt_dry_run || $RM $my_infile else func_fatal_error "Mail delivery failed, draft mail is in $my_infile" fi } # func_extract_email_from_header re_header headerfile func_extract_email () { $opt_debug my_re_header="$1" my_headerfile="$2" $as_unset func_extract_email_result save_IFS="$IFS" IFS=' ' for to in : `grep "$my_re_header" "$my_headerfile" 2>/dev/null`; do IFS="$save_IFS" test "X$to" = X: && continue line=`echo "$to" | $SED "s,$my_re_header,,"` IFS=, for addr in $line; do IFS="$save_IFS" func_quote_for_eval "$addr" to_addr=`echo "$func_quote_for_eval_result" | $SED "$sed_mail_address"` test -n "$to_addr" || to_addr="$func_quote_for_eval_result" func_extract_email_result="${func_extract_email_result+$func_extract_email_result }$to_addr" done done IFS="$save_IFS" } ## ----- ## ## main. ## ## ----- ## { tmp_dir="`func_mktempdir`" headers="$tmp_dir/headers" fname="$tmp_dir/mail" trap '$RM -r "$tmp_dir"; exit $EXIT_FAILURE' 1 2 15 # Generate a comma separated list of destination addresses for the # mail headers: $as_unset destination for to in : ${1+"$@"} do test "X$to" = X: && continue func_quote_for_eval "$to" destination="${destination+$destination, }$func_quote_for_eval_result" done func_headers "$fname" "$destination" if test $opt_filename_num -gt 1; then func_multipart_content "$fname" else func_single_content "$fname" fi # Generate a list of destination addresses for sendmail: if test -z "$opt_output_file"; then $as_unset destination for to in : ${1+"$@"} do test "X$to" = X: && continue func_quote_for_eval "$to" to_addr=`echo "$func_quote_for_eval_result" | $SED "$sed_mail_address"` test -n "$to_addr" || to_addr="$func_quote_for_eval_result" destination="${destination+$destination }$to_addr" done func_extract_email '^To: *' "$opt_headers" destination="${destination+$destination }$func_extract_email_result" func_extract_email '^Cc: *' "$opt_headers" destination="${destination+$destination }$func_extract_email_result" func_extract_email '^Bcc: *' "$opt_headers" destination="${destination+$destination }$func_extract_email_result" test -n "$opt_from" || { func_extract_email '^From: *' "$opt_headers" opt_from="$func_extract_email_result" } func_sendmail "$fname" "$destination" "$opt_from" else mv $fname $opt_output_file || exit $EXIT_FAILURE fi $RM -r "$tmp_dir" } exit $EXIT_SUCCESS # Local Variables: # mode:shell-script # sh-indentation:2 # End: ]])