/* * report a recipient to remote */ char * rcptto(char *to) { String *s; s = unescapespecial(bangtoat(to)); if(toline == 0) toline = s_new(); else s_append(toline, ", "); s_append(toline, s_to_c(s)); if(strchr(s_to_c(s), '@')) dBprint("RCPT TO:<%s>\r\n", s_to_c(s)); else { s_append(toline, "@"); s_append(toline, ddomain); dBprint("RCPT TO:<%s@%s>\r\n", s_to_c(s), ddomain); } alarm(10*alarmscale); switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } return 0; }
/* dispose of local addresses */ int cat_mail(dest *dp, message *mp) { Biobuf *fp; char *rcvr, *cp; Mlock *l; String *tmp, *s; int i, n; s = unescapespecial(s_clone(dp->repl1)); if (nflg) { if(!xflg) print("cat >> %s\n", s_to_c(s)); else print("%s\n", s_to_c(dp->addr)); s_free(s); return 0; } for(i = 0;; i++){ l = syslock(s_to_c(s)); if(l == 0) return refuse(dp, mp, "can't lock mail file", 0, 0); fp = sysopen(s_to_c(s), "al", MBOXMODE); if(fp) break; tmp = s_append(0, s_to_c(s)); s_append(tmp, ".tmp"); fp = sysopen(s_to_c(tmp), "al", MBOXMODE); if(fp){ syslog(0, "mail", "error: used %s", s_to_c(tmp)); s_free(tmp); break; } s_free(tmp); sysunlock(l); if(i >= 5) return refuse(dp, mp, "mail file cannot be opened", 0, 0); sleep(1000); } s_free(s); n = m_print(mp, fp, (char *)0, 1); if (Bprint(fp, "\n") < 0 || Bflush(fp) < 0 || n < 0){ sysclose(fp); sysunlock(l); return refuse(dp, mp, "error writing mail file", 0, 0); } sysclose(fp); sysunlock(l); rcvr = s_to_c(dp->addr); if(cp = strrchr(rcvr, '!')) rcvr = cp+1; logdelivery(dp, rcvr, mp); return 0; }
/* output a message */ extern int m_print(message *mp, Biobuf *fp, char *remote, int mbox) { String *date, *sender; char *f[6]; int n; sender = unescapespecial(s_clone(mp->sender)); if (remote != 0){ if(print_remote_header(fp,s_to_c(sender),s_to_c(mp->date),remote) < 0){ s_free(sender); return -1; } } else { if(print_header(fp, s_to_c(sender), s_to_c(mp->date)) < 0){ s_free(sender); return -1; } } s_free(sender); if(!rmail && !mp->havedate){ /* add a date: line Date: Sun, 19 Apr 1998 12:27:52 -0400 */ date = s_copy(s_to_c(mp->date)); n = getfields(s_to_c(date), f, 6, 1, " \t"); if(n == 6) Bprint(fp, "Date: %s, %s %s %s %s %s\n", f[0], f[2], f[1], f[5], f[3], rewritezone(f[4])); } if(!rmail && !mp->havemime && isutf8(mp->body)) printutf8mime(fp); if(mp->to){ /* add the to: line */ if (Bprint(fp, "%s\n", s_to_c(mp->to)) < 0) return -1; /* add the from: line */ if (!mp->havefrom && printfrom(mp, fp) < 0) return -1; if(!mp->rfc822headers && *s_to_c(mp->body) != '\n') if (Bprint(fp, "\n") < 0) return -1; } else if(!rmail){ /* add the from: line */ if (!mp->havefrom && printfrom(mp, fp) < 0) return -1; if(!mp->rfc822headers && *s_to_c(mp->body) != '\n') if (Bprint(fp, "\n") < 0) return -1; } if (!mbox) return m_noescape(mp, fp); return m_escape(mp, fp); }
int matcher(char *action, Pattern *p, char *message, Resub *m) { char *cp; String *s; for(cp = message; matchpat(p, cp, m); cp = m->ep) { switch(p->action) { case SaveLine: if(vflag) xprint(2, action, m); saveline(linefile, sender, m); break; case HoldHeader: case Hold: if(nflag) continue; if(vflag) xprint(2, action, m); *qdir = holdqueue; if(hflag && qname) { cp = strchr(sender, '!'); if(cp) { *cp = 0; *qname = strdup(sender); *cp = '!'; } else *qname = strdup(sender); } return 1; case Dump: if(vflag) xprint(2, action, m); *(m->ep) = 0; if(!tflag) { s = s_new(); s_append(s, sender); s = unescapespecial(s); syslog(0, "smtpd", "Dumped %s [%s] to %s", s_to_c(s), m->sp, s_to_c(s_restart(recips))); s_free(s); } tflag = 1; if(sflag) cout = opendump(sender); return 1; default: break; } } return 0; }
static int printfrom(message *mp, Biobuf *fp) { String *s; int rv; if(!returnable(s_to_c(mp->sender))) return Bprint(fp, "From: Postmaster\n"); s = username(mp->sender); if(s) { s_append(s, " <"); s_append(s, s_to_c(mp->sender)); s_append(s, ">"); } else { s = s_copy(s_to_c(mp->sender)); } s = unescapespecial(s); rv = Bprint(fp, "From: %s\n", s_to_c(s)); s_free(s); return rv; }
/* * send back the mail with an error message * * return 0 if successful */ int returnmail(char **av, char *name, char *msg) { int pfd[2]; Waitmsg *wm; int fd; char buf[256]; char attachment[256]; int i; long n; String *s; char *sender; if(av[1] == 0 || av[2] == 0){ logit("runq - dumping bad file", name, av); return 0; } s = unescapespecial(s_copy(av[2])); sender = s_to_c(s); if(!returnable(sender) || strcmp(sender, "postmaster") == 0) { logit("runq - dumping p to p mail", name, av); return 0; } if(pipe(pfd) < 0){ logit("runq - pipe failed", name, av); return -1; } switch(rfork(RFFDG|RFPROC|RFENVG)){ case -1: logit("runq - fork failed", name, av); return -1; case 0: logit("returning", name, av); close(pfd[1]); close(0); dup(pfd[0], 0); close(pfd[0]); putenv("upasname", "/dev/null"); snprint(buf, sizeof(buf), "%s/marshal", UPASBIN); snprint(attachment, sizeof(attachment), "%s", file(name, 'D')); execl(buf, "send", "-A", attachment, "-s", "permanent failure", sender, nil); error("can't exec", 0); break; default: break; } close(pfd[0]); fprint(pfd[1], "\n"); /* get out of headers */ if(av[1]){ fprint(pfd[1], "Your request ``%.20s ", av[1]); for(n = 3; av[n]; n++) fprint(pfd[1], "%s ", av[n]); } fprint(pfd[1], "'' failed (code %s).\nThe symptom was:\n\n", msg); fd = open(file(name, 'E'), OREAD); if(fd >= 0){ for(;;){ n = read(fd, buf, sizeof(buf)); if(n <= 0) break; if(write(pfd[1], buf, n) != n){ close(fd); goto out; } } close(fd); } close(pfd[1]); out: wm = wait(); if(wm == nil){ syslog(0, "runq", "wait: %r"); logit("wait failed", name, av); return -1; } i = 0; if(wm->msg[0]){ i = -1; syslog(0, "runq", "returnmail child: %s", wm->msg); logit("returnmail child failed", name, av); } free(wm); return i; }
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); }
/* loop through the names to be translated */ void main(int argc, char *argv[]) { String *s; String *alias; /* the alias for the name */ char **names; /* names of this system */ String *files; /* list of files to search */ int i, rv; char *p; ARGBEGIN { case 'd': debug = 1; break; case 'f': from = 1; break; case 'n': namefiles = ARGF(); break; } ARGEND if (chdir(UPASLIB) < 0) { perror("translate(chdir):"); exit(1); } /* get environmental info */ names = sysnames_read(); files = getdbfiles(); alias = s_new(); /* loop through the names to be translated (from standard input) */ for(i=0; i<argc; i++) { s = unescapespecial(s_copy(mklower(argv[i]))); if(strchr(s_to_c(s), '!') == 0) rv = translate(s_to_c(s), names, files, alias); else rv = -1; if(from){ if (rv >= 0 && *s_to_c(alias) != '\0'){ p = strchr(s_to_c(alias), '\n'); if(p) *p = 0; p = strchr(s_to_c(alias), '!'); if(p) { *p = 0; print("%s", s_to_c(alias)); } else { p = strchr(s_to_c(alias), '@'); if(p) print("%s", p+1); else print("%s", s_to_c(alias)); } } } else { if (rv < 0 || *s_to_c(alias) == '\0') print("local!%s\n", s_to_c(s)); else { /* this must be a write, not a print */ write(1, s_to_c(alias), strlen(s_to_c(alias))); } } s_free(s); } exits(0); }