Ejemplo n.º 1
0
void
main(int argc, char **argv)
{
	int i, ok, rcvrs;
	char *addr, *rv, *trv, *host, *domain;
	char **errs;
	char hellodomain[256];
	String *from, *fromm, *sender;

	alarmscale = 60*1000;	/* minutes */
	quotefmtinstall();
	fmtinstall('[', encodefmt);
	errs = malloc(argc*sizeof(char*));
	reply = s_new();
	host = 0;
	ARGBEGIN{
	case 'a':
		tryauth = 1;
		if(trysecure == 0)
			trysecure = 1;
		break;
	case 'A':	/* autistic: won't talk to us until we talk (Verizon) */
		autistic = 1;
		break;
	case 'b':
		if (bustedmx >= Maxbustedmx)
			sysfatal("more than %d busted mxs given", Maxbustedmx);
		bustedmxs[bustedmx++] = EARGF(usage());
		break;
	case 'd':
		debug = 1;
		break;
	case 'f':
		filter = 1;
		break;
	case 'g':
		gdomain = EARGF(usage());
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 'i':
		insecure = 1;
		break;
	case 'p':
		alarmscale = 10*1000;	/* tens of seconds */
		ping = 1;
		break;
	case 's':
		if(trysecure == 0)
			trysecure = 1;
		break;
	case 't':
		trysecure = 2;
		break;
	case 'u':
		user = EARGF(usage());
		break;
	default:
		usage();
		break;
	}ARGEND;

	Binit(&berr, 2, OWRITE);
	Binit(&bfile, 0, OREAD);

	/*
	 *  get domain and add to host name
	 */
	if(*argv && **argv=='.') {
		domain = *argv;
		argv++; argc--;
	} else
		domain = domainname_read();
	if(host == 0)
		host = sysname_read();
	strcpy(hostdomain, domainify(host, domain));
	strcpy(hellodomain, domainify(sysname_read(), domain));

	/*
	 *  get destination address
	 */
	if(*argv == 0)
		usage();
	addr = *argv++; argc--;
	farend = addr;

	/*
	 *  get sender's machine.
	 *  get sender in internet style.  domainify if necessary.
	 */
	if(*argv == 0)
		usage();
	sender = unescapespecial(s_copy(*argv++));
	argc--;
	fromm = s_clone(sender);
	rv = strrchr(s_to_c(fromm), '!');
	if(rv)
		*rv = 0;
	else
		*s_to_c(fromm) = 0;
	from = bangtoat(s_to_c(sender));

	/*
	 *  send the mail
	 */
	if(filter){
		Binit(&bout, 1, OWRITE);
		rv = data(from, &bfile);
		if(rv != 0)
			goto error;
		exits(0);
	}

	/* mxdial uses its own timeout handler */
	if((rv = connect(addr)) != 0)
		exits(rv);

	/* 10 minutes to get through the initial handshake */
	atnotify(timeout, 1);
	alarm(10*alarmscale);
	if((rv = hello(hellodomain, 0)) != 0)
		goto error;
	alarm(10*alarmscale);
	if((rv = mailfrom(s_to_c(from))) != 0)
		goto error;

	ok = 0;
	rcvrs = 0;
	/* if any rcvrs are ok, we try to send the message */
	for(i = 0; i < argc; i++){
		if((trv = rcptto(argv[i])) != 0){
			/* remember worst error */
			if(rv != Giveup)
				rv = trv;
			errs[rcvrs] = strdup(s_to_c(reply));
			removenewline(errs[rcvrs]);
		} else {
			ok++;
			errs[rcvrs] = 0;
		}
		rcvrs++;
	}

	/* if no ok rcvrs or worst error is retry, give up */
	if(ok == 0 || rv == Retry)
		goto error;

	if(ping){
		quit(0);
		exits(0);
	}

	rv = data(from, &bfile);
	if(rv != 0)
		goto error;
	quit(0);
	if(rcvrs == ok)
		exits(0);

	/*
	 *  here when some but not all rcvrs failed
	 */
	fprint(2, "%s connect to %s:\n", thedate(), addr);
	for(i = 0; i < rcvrs; i++){
		if(errs[i]){
			syslog(0, "smtp.fail", "delivery to %s at %s failed: %s", argv[i], addr, errs[i]);
			fprint(2, "  mail to %s failed: %s", argv[i], errs[i]);
		}
	}
	exits(Giveup);

	/*
	 *  here when all rcvrs failed
	 */
error:
	removenewline(s_to_c(reply));
	syslog(0, "smtp.fail", "%s to %s failed: %s",
		ping ? "ping" : "delivery",
		addr, s_to_c(reply));
	fprint(2, "%s connect to %s:\n%s\n", thedate(), addr, s_to_c(reply));
	if(!filter)
		quit(rv);
	exits(rv);
}
Ejemplo n.º 2
0
void
main(int argc, char **argv)
{
	char *netdir;
	char buf[1024];

	netdir = nil;
	quotefmtinstall();
	fmtinstall('I', eipfmt);
	starttime = time(0);
	ARGBEGIN{
	case 'a':
		authenticate = 1;
		break;
	case 'c':
		tlscert = EARGF(usage());
		break;
	case 'D':
		Dflag++;
		break;
	case 'd':
		debug++;
		break;
	case 'f':				/* disallow relaying */
		fflag = 1;
		break;
	case 'g':
		gflag = 1;
		break;
	case 'h':				/* default domain name */
		dom = EARGF(usage());
		break;
	case 'k':				/* prohibited ip address */
		addbadguy(EARGF(usage()));
		break;
	case 'm':				/* set mail command */
		mailer = mailerpath(EARGF(usage()));
		break;
	case 'n':				/* log peer ip address */
		netdir = EARGF(usage());
		break;
	case 'p':
		passwordinclear = 1;
		break;
	case 'r':
		rflag = 1;			/* verify sender's domain */
		break;
	case 's':				/* save blocked messages */
		sflag = 1;
		break;
	case 't':
		fprint(2, "%s: the -t option is no longer supported, see -c\n",
			argv0);
		tlscert = "/sys/lib/ssl/smtpd-cert.pem";
		break;
	default:
		usage();
	}ARGEND;

	nci = getnetconninfo(netdir, 0);
	if(nci == nil)
		sysfatal("can't get remote system's address: %r");
	parseip(rsysip, nci->rsys);

	if(mailer == nil)
		mailer = mailerpath("send");

	if(debug){
		snprint(buf, sizeof buf, "%s/smtpdb/%ld", UPASLOG, time(0));
		close(2);
		if (create(buf, OWRITE | OEXCL, 0662) >= 0) {
			seek(2, 0, 2);
			fprint(2, "%d smtpd %s\n", getpid(), thedate());
		} else
			debug = 0;
	}
	getconf();
	if (isbadguy())
		exits("banned");
	Binit(&bin, 0, OREAD);

	if (chdir(UPASLOG) < 0)
		syslog(0, "smtpd", "no %s: %r", UPASLOG);
	me = sysname_read();
	if(dom == 0 || dom[0] == 0)
		dom = domainname_read();
	if(dom == 0 || dom[0] == 0)
		dom = me;
	parseinit();
	sayhi();

	/* allow 45 minutes to parse the header */
	atnotify(catchalarm, 1);
	alarm(45*60*1000);
	zzparse();
	exits(0);
}