#!/bin/sh

#*
#* Copyright (C) 2004 Perolo Silantico <per.sil@gmx.it> and
#*                    Pawel Foremski <pjf@gna.org>, et al.
#*
#* 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 2 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, write to the Free Software Foundation,
#* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#*
#***
#*
#* $Id: vpopmail_check_recipient.sh,v 1.6 2007/06/11 14:00:59 werner Exp $
#* (C)opyRight Werner Maier <werner@maiers.de>
#*
#* extensions:
#* - check for .qmail-default in $HOMEPATH (catchall). 
#*   I know: catchall is very stupid, but possible.
#* - check for .qmail-ezmlmlist-command for use with ezmlm
#*   e.g. newsletter-subscribe-mail=domain.net@domain.net
#* - check for .qmail-extensions, e.g. $HOMEPATH/$USER/.qmail-ext
#*   should not be possible with qmail-admin, but who knows...
#* - checks if the needed tools are executable and suid.
#* - correct check of aliases from alias-domains
#* - added support for more ezmlm-commands like sc. tc. uc. vc. 
#*   and allow-deny-reject
#*
#*
#* additional requirements
#* needs VPOPLS - a copy of /bin/ls to $VPOPMAIL_BINDIR/, 
#* needs VGREP - a copy of /bin/grep to $VPOPMAIL_BINDIR/, 
#* each with owner set to vpopmail and rights set to u+s.
#*   
#* Known shortcomings: only the shortest "-ext" will be used.
#* USER-list-bla will not be checked. 
#* 

# checks an email address provided as parameter with vpopmail or 
# if called as a qmail-spp plugin using ${SMTPRCPTTO}
# returns
#   0   ... in case the email exists
#   1   ... in case this email does not exists

VERSION=2.0

# path to vpopmail directory
VPOPMAIL_BINDIR=/var/vpopmail/bin
VPOPLS=${VPOPMAIL_BINDIR}/vpopls
VGREP=${VPOPMAIL_BINDIR}/vgrep
VDOMAININFO=${VPOPMAIL_BINDIR}/vdominfo
VALIAS=${VPOPMAIL_BINDIR}/valias
VUSERINFO="${VPOPMAIL_BINDIR}/vuserinfo -n"

# the recipient to check is the only parameter on the command line - if any present
RECIPIENT="$1"

## --- LOG settings
# trigger log messages
LOG_USE=1
LOG_PREFIX="qmail-spp (`basename $0`) [$$]: "


## --- qmail-spp settings
MSG_ERROR="E511 Sorry, no mailbox here by that name (#5.1.1)"
MSG_OK=""


# check all important progs to: executable
STOP=""
set $VUSERINFO
VUSERI=$1
for FILE in ${VPOPLS} ${VDOMAININFO} ${VALIAS} ${VUSERI} ${VGREP}
do
  [ -x ${FILE} ] 	|| STOP="ERROR: ${FILE}: not executable."
  [ -u ${FILE} ] 	|| STOP="ERROR: ${FILE}: set-user-id bit not set."
  [ -g ${FILE} ] 	|| STOP="ERROR: ${FILE}: set-group-id bit not set."
done 
# check all important progs to: suid-flag set.
if [ "$STOP" != "" ]
then
	# allways log error:
  	echo "${LOG_PREFIX} ${STOP}" 1>&2
	# default: give no error and accept everything (better safe than sorry)
	# comment this out to create a temporary error instead of accepting
	# echo "E451 Temporary problem (vpopmail_check_recipient)."
	exit 0
fi

# if this is a qmail-spp plugin. recipient is passed via environement
if [ ! -z "${SMTPRCPTTO}" ]; then
  RECIPIENT="${SMTPRCPTTO}"
  SPP=1
else
  SPP=0
fi


# if the recipient is empty it does not exist :)
if [ -z "${RECIPIENT}" ]; then
  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}invalid empty recipient" 1>&2
  [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"
  exit 1 
fi


# get the domain name of the recipient
# ${var##pattern} remove longest pattern from left
DOMAIN=${RECIPIENT##*@}

# get the user-name
# ${var%%pattern} remove longest pattern from right
BOX=${RECIPIENT%%@*}

# check if the box name contains invalid characters
if [ ! -z "`/bin/echo ${RECIPIENT} | /bin/grep '[^-0-9A-Za-z\.@_=]'`" ]; then
  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}invalid characters in recipient name: ${RECIPIENT}" 1>&2
  [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"
  exit 1
fi

# check if the domain exists. If the domain is not on this host, this is
# an relay-attempt
if [ "`${VDOMAININFO} ${DOMAIN} > /dev/null; echo $?`" != "0" ]; then
  # if RELAYCLIENT is set, then the user has authenticated before
  # relaying is allowed
  if [ "`set | /bin/grep RELAYCLIENT > /dev/null; echo $?`" == "0" -o ! -z "${SMTPAUTHUSER}" ]; then
    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}relaying email to: ${RECIPIENT}"  1>&2
    [ "${SPP}" == "1" ] && echo "${MSG_OK}"
    exit 0
  else
    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}no such domain: ${DOMAIN}"  1>&2
    [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"
    exit 1
  fi
else 
  # domain found. but is it the correct domain or is it an alias domain?
  DOM=`${VDOMAININFO} ${DOMAIN} | $VGREP -e "^domain: " | cut -f 2 -d " "`
  if [ "$DOM" != "$DOMAIN" ]
  then
    DOMAIN=$DOM
    RECIPIENT=$BOX@$DOM
  fi
fi

# check the existence of the user
if [ "`${VUSERINFO} ${RECIPIENT} > /dev/null; echo $?`" == "0" ] 
then 
  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (vuserinfo)." 1>&2
  exit 0
fi

# check with valias if an alias or an e-mail address of that name exists
if [ ! -z "`${VALIAS} -s ${RECIPIENT} | /bin/grep ^${RECIPIENT}`" ]; then 
  [ "${SPP}" == "1" ] && echo "${MSG_OK}"
  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (valias)." 1>&2
  exit 0
fi


# no alias for that recipient email address has been recorded
# and no such user exists.


### get the home directory for that domain and check the existence of 
### a .qmail-${BOX} file
HOMEPATH="`${VDOMAININFO} ${DOMAIN} | /bin/grep dir | /bin/sed -e 's#dir: *##'`"

# if a .qmail-${BOX} file exists, then delivery is possible
if [ ! -z "`${VPOPLS} ${HOMEPATH}/.qmail-${BOX} 2> /dev/null`" ]; then
  [ "${SPP}" == "1" ] && echo "${MSG_OK}"
  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (.qmail-${BOX})." 1>&2
  exit 0
fi

# if a .qmail-default file exists, then delivery is possible
# catchall is very bad, but possible
if [ ! -z "`${VPOPLS} ${HOMEPATH}/.qmail-default 2> /dev/null`" ]; then
  # now check, if not vdelivermail '' bounce-no-mailbox
  RESULT=`${VGREP} vdelivermail ${HOMEPATH}/.qmail-default | /bin/grep delete > /dev/null; echo $?`
  RESULT2=`${VGREP} vdelivermail ${HOMEPATH}/.qmail-default | /bin/grep bounce-no-mailbox > /dev/null; echo $?`
  if [ "$[${RESULT}+${RESULT2}]" == "2" ]
  then
    [ "${SPP}" == "1" ] && echo "${MSG_OK}"
    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (.qmail-default)." 1>&2
    exit 0
  fi
fi

# ezmlm-list? remove things like -1176124408.5270.menbhdjbcdifngjljjgh
# ${var%pattern} remove shortest pattern from right
LIST=${BOX%-*}
# ezmlm-list moderation? remove -accept and -reject 
LIST=${LIST%-accept}
LIST=${LIST%-reject}
if [ "$LIST" != "$BOX" ]
then
  # if a .qmail-${LIST}-default file exists, then delivery is possible (ezmlm: list-subscribe...)
  if [ ! -z "`${VPOPLS} ${HOMEPATH}/.qmail-${LIST}-default 2> /dev/null`" ]; then
    [ "${SPP}" == "1" ] && echo "${MSG_OK}"
    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (.qmail-${LIST}-default)." 1>&2
    exit 0
  fi

  # no ezmlm-list. now check for DIR/.qmail-ext
  # ${var##pattern} remove longest pattern from left
  EXT=${BOX##*-}
  if [ ! -z "`${VPOPLS} ${HOMEPATH}/${LIST}/.qmail-${EXT} 2> /dev/null`" ]; then
    [ "${SPP}" == "1" ] && echo "${MSG_OK}"
    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (${LIST}/.qmail--${EXT})." 1>&2
    exit 0
  fi
fi

# special: ezmlm-list with listname-subscribe-email-or-more=domain.tld@domain.tld
# ${var%pattern} remove shortest pattern from right
LIST=${BOX%-subscribe-*=*.*}
LIST=${LIST%-unsubscribe-*=*.*}
LIST=${LIST%-accept-*=*.*}
LIST=${LIST%-allow-tc.*=*.*}
LIST=${LIST%-reject-*=*.*}
LIST=${LIST%-deny-*=*.*}
LIST=${LIST%-sc.*=*.*}
LIST=${LIST%-tc.*=*.*}
LIST=${LIST%-uc.*=*.*}
LIST=${LIST%-vc.*=*.*}
if [ "$LIST" != "$BOX" ]
then
  # if a .qmail-${LIST}-default file exists, then delivery is possible (ezmlm: list-subscribe...)
  if [ ! -z "`${VPOPLS} ${HOMEPATH}/.qmail-${LIST}-default 2> /dev/null`" ]; then
    [ "${SPP}" == "1" ] && echo "${MSG_OK}"
    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX} ${RECIPIENT} exists (.qmail-${LIST}-default)." 1>&2
    exit 0
  fi
fi


# no other checks have prooven the existence of this email address
[ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}no such recipient: ${RECIPIENT}" 1>&2
[ "${SPP}" == "1" ] && echo "${MSG_ERROR}"
exit 1
