[comp.sources.misc] v06i064: mverify - Mail alias/user verification

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (03/21/89)

Posting-number: Volume 6, Issue 64
Submitted-by: jeff@quark.wv.tek.com (Jeff Beadles)
Archive-name: mverify

This program opens a connection to SMTP sendmail on a target host.  It then
attempts to verify that an alias/user exists in the eyes of the sendmail.

I use it to verify users on remote hosts without waiting for mail to bounce.

	-Jeff Beadles

--
Jeff Beadles
jeff@quark.WV.TEK.COM


#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--  1 jeff         1647 Mar  7 20:32 README
# -rw-r--r--  1 jeff         4049 Mar  6 10:47 mverify.c
#
echo 'x - README'
if test -f README; then echo 'shar: not overwriting README'; else
sed 's/^X//' << '________This_Is_The_END________' > README
X
XRequirements:	SMTP sendmail on the receiving (target) host, and an OS that
X		supports sockets.
X
XTo compile:	"make mverify"	(Yes that's right, there's no makefile.)
X	   (or) cc -O -o mverify mverify.c
X
XTo execute:	"mverify user@host"
X
X---------------------------------------------------------------------------
Xmverify.c	Copyright 1989, Jeff Beadles jeff@quark.WV.TEK.COM
X
XPermission is granted to freely copy this program without charge.
XIf you distribute a binary to someone, you must also provide the source
Xupon request.
X
XThis started out as a little tool, and a learning experience for sockets &
Xthe like.  If you find it useful, then good for you.  If not, then read rm(1).
XWhat it does is fairly simple. It opens a connection to SMTP sendmail on a
Xtarget host.  It then attempts to verify that the user exists in the eyes
Xof the sendmail.  For example:  Let's say that I want to know who the
Xuser/alias 'postmaster@quark' expanded to.  Mverify would be invoked as:
X
X% mverify postmaster@quark
X
XJeff Beadles  jeff 
X
XWith the /usr/lib/sendmail -bv command/option, it would only tell you that
Xthe mail was 'deliverable' if the target was on another host.
X
XMost all of the error messages should be self explainatory.
X
XAs long as the local host can find the target host DIRECTLY, it
Xshould work.  This program has no concept of mail domains.
XIf it is given a domain-style host, it truncates everything up to
Xincluding the first '.'  IE:  jeff@quark.WV.TEK.COM = jeff@quark
X
XIf you think of something useful to add, please send it to me, and
XI'll see about adding it.
X
XJeff Beadles
Xjeff@quark.WV.TEK.COM
X...!uunet!tektronix.TEK.COM!quark.WV!jeff
________This_Is_The_END________
if test `wc -l < README` -ne 43; then
	echo 'shar: README was damaged during transit (should have been 43 lines)'
fi
fi		; : end of overwriting check
echo 'x - mverify.c'
if test -f mverify.c; then echo 'shar: not overwriting mverify.c'; else
sed 's/^X//' << '________This_Is_The_END________' > mverify.c
X/*
X * mverify.c	Copyright 1989, Jeff Beadles
X *				jeff@quark.WV.TEK.COM
X *
X *	Permission is granted to freely copy this program without charge.
X *	There are a couple of lines of autobounce.c by Pete Shipley
X *	shipley@berkley.edu.
X *
X *	To compile, cc -o mverify mverify  : To use, mverify user@host
X *
X *	Note:  This program has no concept of mail domains.
X *	If it is given a domain-style host, it truncates everything up to
X *	including the '.'  IE:  jeff@quark.WV.TEK.COM = jeff@quark
X *
X *	This started out as a little tool.  If you find it useful, then
X *	good for you.  If not, then read rm(1).
X *
X *	If you think of something useful to add, please send it to me, and
X *	I'll see about adding it.
X *
X *	Jeff Beadles
X *	jeff@quark.WV.TEK.COM
X *
X */
X
X/* #define index strchr   /* */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netdb.h> 
X#include <netinet/in.h>
X#include <stdio.h>
X#include <strings.h>
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	FILE	*fin;
X	FILE	*fout;
X	char	*retval,
X		*fgets(),
X		*index(),
X		buffer[2048],
X		targetuser[1024],
X		targethost[1024];
X
X	int	s;
X	struct	servent  *sp;
X	struct	hostent *hp, *gethostbyname();
X	struct	sockaddr_in server;
X
X	if ( argc != 2) {
X		(void)fprintf(stderr,"Usage: %s user@host\n",argv[0]);
X		exit(1);
X	}
X	strcpy(targetuser,argv[1]);
X	if( (retval=index(targetuser,'@')) == 0) {
X		(void)fprintf(stdout,"Usage: %s user@host\n",argv[0]);
X		exit(1);
X	}
X	*retval='\0';
X	retval++;
X	strcpy(targethost,retval);
X	if ( (retval=index(targethost,'.')) != 0) {
X	       fprintf(stderr,"\nWarning: I do not know about mail domains.\n");
X	       fprintf(stderr,"Converting %s to ",targethost);
X	       *retval='\0';
X	       fprintf(stderr,"%s\n\n",targethost);
X	}
X
X/*
X *	One socket please...
X */
X	if ( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
X		perror("opening stream socket");
X		exit(1);
X	}
X/*
X *	Now get the information for the @host part of the address.
X */
X	server.sin_family = AF_INET;
X	if ( (hp = gethostbyname(targethost)) == 0) {
X		(void) fprintf(stderr, "%s: unknown host\n", targethost);
X		exit(2);
X	}
X
X
X/*
X *	Now get the smtp port using tcp.
X */
X	bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
X	sp = getservbyname("smtp", "tcp"); 
X	server.sin_port = sp->s_port;
X	if(server.sin_port == htons(0)) {
X		(void)fprintf(stderr,"Unknown service: smtp/tcp\n");
X		exit(1);
X	}
X
X/*
X *	Connecting to the socket might make things go a little easier...  :-)
X */
X	if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
X		perror("connecting stream socket");
X		exit(1);
X	}
X
X/*
X *	Change the to streams 'cause I like'em better.
X */
X	fout = fdopen(s,"w");
X	fin  = fdopen(s,"r");
X
X/*
X *	Wait for the smtp mailer to answer.  It will greet us with:
X * 220 quark.WV.TEK.COM Sendmail 5.17/6.24 ready at Thu, 2 Mar 89 23:52:29 PST
X */
X	while( (retval=fgets(buffer,sizeof(buffer) - 1,fin)) != NULL) {
X		if ( !strncmp(buffer,"220 ",4))
X			break;
X	}
X
X/*
X *	Now that we have the mailers attention, tell it to 'verify' the user.
X */
X	fprintf(fout,"\nVRFY %s\n",targetuser);
X	fflush(fout);
X
X/*
X *	Now just go into a loop reading responces from the mailer.
X */
X	while( (retval=fgets(buffer,sizeof(buffer) -1,fin)) != NULL) {
X/*
X *	Zap ^M < > from the lines.
X */
X		if ( (retval=index(buffer,'\r')) != 0)
X			*retval='\0';
X		if ( (retval=index(buffer,'<')) != 0)
X			*retval=' ';
X		if ( (retval=index(buffer,'>')) != 0)
X			*retval=' ';
X/*
X *	250 = valid data follows.  If true, then this is a valid line.
X *	The +4 skips the '250-'
X */
X		if ( !strncmp(buffer,"250",3)) {
X			puts( buffer + 4);
X		}
X/*
X * 	550 is 'Command unrecognized.  Tell the user and exit.
X *	The +4 skips the '550-'
X */
X		if ( !strncmp(buffer,"550",3)) {
X			puts( buffer + 4);
X			break;
X		}
X/*
X * If "250 " then this was the last line of data.  
X * (Note the space.  a '-' means that there's still more to come.)
X */
X		if ( !strncmp(buffer,"250 ", 4))
X			break;
X	}
X/*
X *	Close the SMTP connection.
X */
X	fputs("\n\nQUIT\n", fout);
X	fflush(fout);
X	fclose(fout);
X	fclose(fin);
X/*
X *	And leave this nice program.
X */
X	exit(0);
X}
X
________This_Is_The_END________
if test `wc -l < mverify.c` -ne 176; then
	echo 'shar: mverify.c was damaged during transit (should have been 176 lines)'
fi
fi		; : end of overwriting check
exit 0