[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[msmtp-users] sendmail wrapper with /etc/aliases support



Hi, in the attachment you can find a simple sendmail wrapper for msmtp
with aliases support.

it gets activated by symlinking /usr/sbin/sendmail and /usr/lib/sendmail to it.

it translates recipients without @ in the arguments list to the
address specified for it in /etc/aliases or appending @example.org if
not.

if the -t argument is passed, it also translates the To: lines in the mail
read from stdin.

msmtp_aliases has four known weaknesses:
1) As it rewrites the arguments list it needs to know all the short
options in msmtp that need a value.
2) the DOMAIN and LOGFILE is hardcoded in the script
3) this version doesn't do any effort in escaping the arguments, so
spaces or quotes are not supported, and a semi colon could be used to
execute code.
4) And if the script is interrupted a /tmp/msmtp.$$ file will be left abandoned.

I believe it's a good candidate to replace the naive find_alias script
because this one doesn't assume sendmail callers only pass one
argument, it mangles all the recipients instead of only the first, and
it doesn't truncate the msmtp call to 5 arguments.

Naturally it more elegant solution would be written in C as part of
mstmp itself, but time is limited and writing the wrapper was easier
;-)

Any comment or suggestion is highly welcomed

Best regards,
Alejandro Mery
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 92c19a7..cc62e3a 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -7,6 +7,8 @@ EXTRA_DIST = \
 	msmtpqueue/msmtp-enqueue.sh		\
 	msmtpqueue/msmtp-listqueue.sh		\
 	msmtpqueue/msmtp-runqueue.sh		\
+	msmtp_aliases/README			\
+	msmtp_aliases/msmtp_aliases.sh		\
 	set_sendmail/set_sendmail.conf		\
 	set_sendmail/set_sendmail.sh		\
 	vim/README				\
diff --git a/scripts/msmtp_aliases/README b/scripts/msmtp_aliases/README
new file mode 100644
index 0000000..9bdc0e8
--- /dev/null
+++ b/scripts/msmtp_aliases/README
@@ -0,0 +1,23 @@
+sendmail wrapper for msmtp with aliases support
+
+it gets activated by symlinking /usr/sbin/sendmail and /usr/lib/sendmail to it.
+
+for x in sbin lib; do
+  ln -snvf /usr/bin/msmtp_aliases /usr/$x/sendmail
+done
+
+it translates recipients without @ in the arguments list to the address specified 
+for it in /etc/aliases or appending @example.org if not.
+
+if the -t argument is passed, it also translates the To: lines in the mail
+read from stdin.
+
+== weaknesses ==
+
+msmtp_aliases rewrites the arguments list so it needs to know all the short
+options in msmtp that need a value.
+
+this version doesn't do any effort in escaping the arguments, so spaces or
+quotes are not supported, and a semi colon could be used to execute code.
+
+And if the script is interrupted a /tmp/msmtp.$$ file will be left abandoned.
diff --git a/scripts/msmtp_aliases/msmtp_aliases.sh b/scripts/msmtp_aliases/msmtp_aliases.sh
new file mode 100644
index 0000000..34289d4
--- /dev/null
+++ b/scripts/msmtp_aliases/msmtp_aliases.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# This file is part of msmtp, an SMTP client.
+#
+# Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+# Martin Lambers <marlam@marlam.de>
+#
+#   This program 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 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+DOMAIN=example.org
+TMPFILE="/tmp/msmtp.$$"
+LOGFILE="/var/log/msmtp.log"
+
+MSMTP=$(which msmtp || echo "/usr/local/bin/msmtp")
+
+log() {
+	echo "$*" >> "$LOGFILE"
+}
+
+log "[$$]  $0 $*"
+
+cat > $TMPFILE # email content
+ARGS= mangled= read_recipients=
+
+while [ $# -gt 0 ]; do
+	case "$1" in
+	-f|-O|-ox|-X|-C|-a|-N|-R|-L)
+		ARGS="$ARGS $1 $2"; shift ;;
+	-t)	ARGS="$ARGS $1" read_recipients=yes ;;
+	--)	ARGS="$ARGS --"; break ;;
+	-*)	ARGS="$ARGS $1" ;;
+	*)	break;
+	esac
+	shift
+done
+
+alias_of() {
+	local x="$1" alias=
+	alias=$(awk -- "/^$x:/ { print \$2;}" "/etc/aliases" 2> /dev/null)
+	echo "${alias:-$x@$DOMAIN}"
+}
+
+for x; do
+	case "$x" in
+	*@*)	ARGS="$ARGS $x" ;;
+	*)	ARGS="$ARGS $(alias_of $x)"
+		mangled=true
+		;;
+	esac
+done
+
+if [ -n "$read_recipients" ]; then
+	for x in $(sed -n -e 's,^To: .*<\([^@]\+\)>$,\1,p' "$TMPFILE"); do
+		y="$(alias_of $x)"
+		log "[$$]  To: <$x> -> <$y>"
+		sed -i "s,^To: \(.*\)<$x>$,To: \1<$y>," "$TMPFILE"
+	done
+fi
+
+eval "set -- $ARGS"
+[ -z "$mangled" ] || log "[$$]+ $0 $@"
+
+"$MSMTP" "$@" < "$TMPFILE"
+errno=$?
+rm -f "$TMPFILE"
+exit $errno