# These functions are used by the smtpserver to do synchronous address checking.

quadprint (quad) {

#| This is a prettyprinter for address quads.  What it prints is what someone
#| doing a VRFY or EXPN query to the SMTP server will see.

	local text

	case $(channel $quad) in
	local)	sift "$(user $quad)" in
		[|/].*	text="local delivery for"
			;;
		.*	text=$(login2uid $(user $quad))	# ignore return value
			if text="$(fullname $(user $quad))"; then
				text="$text"
			else
				if text="$(fullname $(recase -l $(user $quad)))"; then
					text="$text"
				else
					text="550 no such user:"
				fi
			fi
			;;
		tfis
		;;
	usenet)	text="newsgroup:" ;;
	*)	text="$(channel $quad) delivery"
		case "$(host $quad)" in
		-|'')	text="$text for" ;;
		*)	text="$text to $(host $quad) for" ;;
		esac
		;;
	esac
	echo "$text <$(user $quad)>"
}

server (key) {

#| The smtpserver program starts the router in interactive mode and runs this
#| function to interface with the rest of the configuration code.  The key
#| specifies the semantics of the additional arguments provided by the
#| smtpserver.  The key values are: init, to, from, verify, and expand.

	local a A B

	A=$(newattribute default_attributes type sender)
	B=$(newattribute default_attributes type expandsender)

#| In doing a VRFY operation, it is not desired to do any alias expansion.
#| This can be avoided by modifying the attributes of default_attributes to
#| shortcircuit alias expansion.  It is assumed that default_attributes is
#| otherwise proper for the purpose.  The value specified for the privilege
#| level should be appropriate.

	case $key in
	to|from|verify|expand)
		a="$1"
		sift "$a" in
		<(.+)>	a="\1" ;;
		tfis
		if rfc822syntax "$a"; then ; else
			echo "501 illegal address syntax: <$a>"
			return
		fi
		;;
	esac

	case $key in
	init)	# If you want to log incoming connections, it can be done here
		#echo server "$@" >> /tmp/server
		# turn off fliename globbing
		set -f
		# redefine the log function
		log () {
		}
		;;
	hello)
		rejected=
		accepted=
		set none $@ ; shift
		# $1=rhostname $2=ihostaddr
		if [ $(getattrib rejectnet "$2") = "+" -o \
		     $(getattrib rejectnet "$1") = "+" ]; then
			rejected=true
			echo "501 5.7.1 You are not authorized to send mail."
			return
		fi
		if [ $(getattrib relaycustnet "$2") = "+" -o \
		     $(getattrib relaycustnet "$1") = "+" ]; then
			accepted=true
			echo "250 We accept your mails."
			return
		fi
		echo "250 Seems to be"
		;;
	to|from)
		a="$(router "$1" default_attributes)"
		for i in $(elements $a)
		do
			for j in $(elements $i)
			do
				case $(channel $j) in
				error)	echo "550 unresolvable address: <$1>"
					return ;;
				esac

#| If any of the addresses in the expansion gave errors, we reject the
#| original address.  The lack of distinction between different kinds of errors
#| may be inadequate in some situations.

			done
		done

		domain=
		tsift "$1" in
		.*@([^@]*)
			domain="\1"
			break ;;
		.*
			echo "250 Ok"
			return
			;;
		tfist

		case $key in
		from)
			if [ X"$rejected" = Xtrue -o \
			    $(getattrib rejectsource $domain) = "+" ]; then
				rejected=true
				echo "501 5.7.1 You are not authorized to send mail."
				return
			fi
			if [ X"$accepted" = Xtrue -o \
			    $(getattrib relaycustomer $domain) = "+" ]; then
				accepted=true
				echo "250 2.7.1 Sender accepted."
				return
			fi
			;;
		to)
			if [ X"$rejected" = Xtrue ]; then
				echo "501 5.7.1 You are not authorized to send mail."
				return
			fi
			if [ $(getattrib relaytarget $domain) = "+" -o \
			    X"$accepted" = Xtrue ]; then
				echo "250 2.7.1 Recipent accepted."
				return
			else
				echo "501 5.7.1 This host is not relaying for '$domain'. Recipient rejected."
				return
			fi
			;;
		esac

		echo "250 Ok (verified)"
		;;
	verify)
		a="$(router "$1" $A)"
#| Invoke the router function with alias expansion turned off.
		for i in $(elements $a)
		do
			for j in $(elements $i)
			do
				quadprint $j
			done
		done
		;;
	expand)
		a="$(router "$1" $B)"

#| Invoke the router function with alias expansion enabled.

		for i in $(elements $a)
		do
			for j in $(elements $i)
			do
				quadprint $j
			done
		done
		;;
	esac
}

# initializing policy database
if [ -f $MAILSHARE/db/policy.dir ]; then
	relation -lt ndbm -d longestmatch -f $MAILSHARE/db/policy policy
else
	policy () { return 1 }
fi

getattrib (attrib,object) {
	if [ X"$object" = X ]; then
		echo 'empty_object'
		return 1
	fi
	for loopcnt in 0 1 2 3 4 5 6 7 8 9 	# to prevent endless =tag loops
	do
		attributelist=$(list $(policy "$object") )
		value=$(get attributelist "$attrib")
		if [ X$value != X ]; then
			echo $value		# attribute specified
			return 0
		fi
		object=$(get attributelist =)	# "See at $object"
		if [ X$object = X ]; then
			echo .			# unspecified
			return 0
		fi
	done
	echo 'too_many_indirection'
	return 1
}
