|
|
1.1 ! root 1: /* ! 2: * smtp -- client, send mail to remote smtp server ! 3: * TODO: ! 4: * allow partial delivery to multiple recipients when only some ! 5: * fail (maybe) ! 6: * send stuff from cmds.h instead of hard-coded here ! 7: */ ! 8: ! 9: #define USAGE "usage: %s [-u] [-H helohost] [-d domain] [-a addr] [-f] [-D] [-L loglevel] sender targethost recip1 recip2 ...\n" ! 10: ! 11: #include <stdio.h> ! 12: #include <ctype.h> ! 13: #include <sysexits.h> ! 14: #include "addrformat.h" ! 15: #include "smtp.h" ! 16: #include "string.h" ! 17: #include "aux.h" ! 18: #include "sys.h" ! 19: ! 20: #ifndef DIALER ! 21: #define DIALER "tcp" ! 22: #endif ! 23: ! 24: #ifndef SERVNAME ! 25: #define SERVNAME "smtp" /* service we wanna talk to */ ! 26: #endif ! 27: ! 28: char *progname; ! 29: int debug; ! 30: char *helohost; ! 31: int kludgepause = 0; ! 32: ! 33: char *strcat(), *strcpy(); ! 34: extern char *convertaddr(); ! 35: extern int ipcdebug; ! 36: extern char *ipcpath(); ! 37: ! 38: static int errno; ! 39: static char errstr[128]; ! 40: ! 41: char *convertto(); ! 42: ! 43: /* ! 44: * main - parse arguments and handle options ! 45: */ ! 46: main(argc, argv) ! 47: int argc; ! 48: char *argv[]; ! 49: { ! 50: register int c; ! 51: int errflg = 0; ! 52: int unixformat = 0; ! 53: int filter = 0; ! 54: char *domain = 0; ! 55: char *sender = 0; ! 56: char *host = 0; ! 57: char *addr = 0; ! 58: namelist *recips, *newname(), *appendname(); ! 59: FILE *sfi, *sfo; ! 60: string *replyaddr=s_new(); ! 61: string *hh; ! 62: ! 63: extern int optind; ! 64: extern char *optarg; ! 65: ! 66: umask(2); ! 67: ! 68: progname = argv[0]; ! 69: Openlog("smtp", LOG_PID, LOG_SMTP); ! 70: setlogmask(LOG_UPTO(DEFAULT_LOG_LEVEL)); ! 71: while ((c = getopt(argc, argv, "ga:uDd:H:fL:K")) != EOF) ! 72: switch (c) { ! 73: case 'a': addr = optarg; break; ! 74: case 'u': unixformat++; break; ! 75: case 'D': debug++; ipcdebug++; break; ! 76: case 'd': domain = optarg; break; ! 77: case 'H': helohost = optarg; break; ! 78: case 'f': filter++; break; ! 79: case 'K': kludgepause++; break; ! 80: case 'L': setloglevel(optarg); break; ! 81: case '?': ! 82: default: ! 83: errflg++; ! 84: break; ! 85: } ! 86: if (errflg || (argc - optind) < 3) { ! 87: (void) fprintf(stderr, USAGE, progname); ! 88: Syslog(LOG_WARNING, "SMTP illegal usage."); ! 89: bomb(EX_USAGE); ! 90: } ! 91: ! 92: /* ! 93: * figure out what to call ourselves ! 94: */ ! 95: if (helohost==NULL) ! 96: helohost=s_to_c(s_copy(sysname_read())); ! 97: ! 98: /* ! 99: * if there is no domain in the helo host name ! 100: * and we the -d option is specified, domainify ! 101: * the helo host ! 102: */ ! 103: if(strchr(helohost, '.')==0 && domain){ ! 104: hh = s_copy(helohost); ! 105: s_append(hh, domain); ! 106: helohost = s_to_c(hh); ! 107: } ! 108: ! 109: /* ! 110: * put our address onto the reply address ! 111: */ ! 112: if(strchr(argv[optind], '!')==0 || !domain){ ! 113: s_append(replyaddr, helohost); ! 114: s_append(replyaddr, "!"); ! 115: s_append(replyaddr, argv[optind]); ! 116: } else { ! 117: s_append(replyaddr, argv[optind]); ! 118: } ! 119: optind++; ! 120: ! 121: /* ! 122: * convert the arguments to 822 form ! 123: */ ! 124: sender = convertaddr(s_to_c(replyaddr), domain, SOURCEROUTE); ! 125: host = argv[optind++]; ! 126: recips = newname(convertto(argv[optind++], unixformat, host)); ! 127: for (; optind < argc; optind++) ! 128: recips = appendname(recips, convertto(argv[optind], unixformat, host)); ! 129: ! 130: /* ! 131: * run as a filter ! 132: */ ! 133: if ( filter ) { ! 134: do_data(unixformat, stdin, stdout, sender, recips, domain); ! 135: exit(0); ! 136: } ! 137: ! 138: /* ! 139: * open connection ! 140: */ ! 141: setup(addr ? addr : host, &sfi, &sfo); ! 142: ! 143: /* ! 144: * hold the conversation ! 145: */ ! 146: converse(unixformat, sender, recips, domain, sfi, sfo, stdin); ! 147: /* converse terminates with the appropriate exit code */ ! 148: } ! 149: ! 150: namelist * ! 151: newname(s) ! 152: char *s; ! 153: { ! 154: namelist *np; ! 155: ! 156: np = (namelist *)malloc(sizeof(namelist)); ! 157: if (np == NULL) { ! 158: Syslog(LOG_WARNING, "could not alloc (newname)"); ! 159: bomb(1); ! 160: } ! 161: np->name = s; ! 162: np->next = NULL; ! 163: return np; ! 164: } ! 165: ! 166: /* could add at beginning, but let's maintain original order */ ! 167: namelist * ! 168: appendname(nl, s) ! 169: char *s; ! 170: namelist *nl; ! 171: { ! 172: register namelist *tl; ! 173: ! 174: if (nl == NULL) ! 175: bomb(1); /* shouldn't happen */ ! 176: for (tl=nl; tl->next!=NULL; tl=tl->next) ! 177: ; ! 178: tl->next = newname(s); ! 179: return nl; ! 180: } ! 181: ! 182: /* ! 183: * convert a destination address to outgoing format ! 184: * ! 185: * if unixformat, just leave it alone ! 186: * ! 187: * if not add the destination host name. ! 188: */ ! 189: char * ! 190: convertto(recip, unixformat, desthost) ! 191: char *recip; ! 192: char *desthost; ! 193: { ! 194: static string *buf; ! 195: ! 196: if(unixformat) ! 197: return recip; ! 198: ! 199: buf = s_reset(buf); ! 200: s_append(buf, desthost); ! 201: s_append(buf, "!"); ! 202: s_append(buf, recip); ! 203: return convertaddr(s_to_c(buf), 0, SOURCEROUTE); ! 204: } ! 205: ! 206: ! 207: /* ! 208: * setup -- setup tcp/ip connection to/from server ! 209: */ ! 210: setup(host, sfip, sfop) ! 211: char *host; ! 212: FILE **sfip, **sfop; ! 213: { ! 214: int s; ! 215: char *path; ! 216: int localerr; ! 217: ! 218: path = ipcpath(host, DIALER, SERVNAME); ! 219: Syslog(LOG_DEBUG, "Opening connection to %s\n", path); ! 220: if ((s = ipcopen(path, "")) < 0) { ! 221: extern int ipcerrno; ! 222: extern char syserrstr[]; ! 223: ! 224: char errbuf[256]; ! 225: sprintf(errbuf, "SMTP connect error to %s", host); ! 226: ipcperror(errbuf); ! 227: Syslog(LOG_INFO, "%s: %s\n", errbuf, syserrstr); ! 228: bomb(ipcerrno); ! 229: } ! 230: ! 231: if (((*sfip = fdopen(s, "r")) == (FILE *) NULL) || ! 232: ((*sfop = fdopen(s, "w")) == (FILE *) NULL)) { ! 233: perror("setup - fdopen"); ! 234: Syslog(LOG_INFO, "setup - fdopen"); ! 235: bomb(EX_IOERR); ! 236: } ! 237: } ! 238: ! 239: ! 240: /* ! 241: * bomb(code) - exit program, map smtp error code into mailsystem code ! 242: * Codes with EX_ are from <sysexits.h> ! 243: * Lines with FOO are placeholders until we decrypt more appropriate codes. ! 244: */ ! 245: bomb(code) ! 246: int code; ! 247: { ! 248: switch(code) { ! 249: case 451: /* some temporary error */ ! 250: exit(EX_TEMPFAIL); /* try later */ ! 251: /*NOTREACHED*/ ! 252: case 554: /* syntax error in address */ ! 253: case 501: /* data format error */ ! 254: exit(EX_DATAERR); ! 255: /*NOTREACHED*/ ! 256: case 550: /* no such user */ ! 257: exit(EX_NOUSER); ! 258: /*NOTREACHED*/ ! 259: case EX_USAGE: ! 260: case EX_DATAERR: ! 261: case EX_NOINPUT: ! 262: case EX_NOUSER: ! 263: case EX_NOHOST: ! 264: case EX_UNAVAILABLE: ! 265: case EX_SOFTWARE: ! 266: case EX_OSERR: ! 267: case EX_OSFILE: ! 268: case EX_CANTCREAT: ! 269: case EX_IOERR: ! 270: case EX_TEMPFAIL: ! 271: case EX_PROTOCOL: ! 272: case EX_NOPERM: ! 273: exit(code); ! 274: /*NOTREACHED*/ ! 275: default: /* can't happen? */ ! 276: if ((code >= 400) && (code <= 499)) ! 277: exit(EX_TEMPFAIL); ! 278: else { ! 279: Syslog(LOG_WARNING, "SMTP protocol error %d\n", code); ! 280: exit(EX_PROTOCOL); /* unknown error */ ! 281: } ! 282: } ! 283: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.