14796Seric # include <ctype.h> 24684Seric # include <wellknown.h> 34684Seric # include <sysexits.h> 44684Seric # include <stdio.h> 54684Seric # include <useful.h> 64684Seric 7*4797Seric static char SccsId[] = "@(#)usersmtp.c 3.3 11/08/81"; 84684Seric 94684Seric /* 104684Seric ** TCP -- TCP/Ethernet/ARPAnet mailer 114684Seric ** 124684Seric ** This arranges to send a message over the TCP connection. 134684Seric */ 144684Seric 154684Seric # define MAXLINE 200 164684Seric 174684Seric char *MailCommand = "/usr/lib/sendmail"; 184684Seric char *MailUser = "network"; 194796Seric char *MailPassword = "mailhack"; 204796Seric FILE *InConnection; 214796Seric FILE *OutConnection; 224684Seric bool Verbose; 234796Seric bool Debug; 24*4797Seric int Status; /* exit status */ 254684Seric 264684Seric main(argc, argv) 274684Seric int argc; 284684Seric char **argv; 294684Seric { 304796Seric while (argc > 1 && argv[1][0] == '-') 314796Seric { 324796Seric register char *p = *++argv; 334796Seric 344796Seric argc--; 354796Seric switch (p[1]) 364796Seric { 374796Seric case 'v': 384796Seric Verbose = TRUE; 394796Seric break; 404796Seric 414796Seric case 'd': 424796Seric Debug = TRUE; 434796Seric break; 444796Seric } 454796Seric } 464796Seric 474684Seric if (argc < 4) 484796Seric { 494796Seric if (Debug) 504796Seric printf("Usage\n"); 514684Seric exit(EX_USAGE); 524796Seric } 534684Seric 544796Seric if (openconnection(argv[2]) < 0) 55*4797Seric exit(Status); 564684Seric 57*4797Seric Status = runsmtp(argv[1], &argv[3]); 584684Seric 59*4797Seric closeconnection(); 60*4797Seric 614796Seric if (Debug) 62*4797Seric printf("Finishing with stat %d\n", Status); 634796Seric 64*4797Seric exit(Status); 654684Seric } 664684Seric /* 674684Seric ** OPENCONNECTION -- open connection to SMTP socket 684684Seric ** 694684Seric ** Parameters: 70*4797Seric ** host -- the name of the host to connect to. This 71*4797Seric ** will be replaced by the canonical name of 72*4797Seric ** the host. 734684Seric ** 744684Seric ** Returns: 75*4797Seric ** File descriptor of connection. 76*4797Seric ** -1 on error. 774684Seric ** 784684Seric ** Side Effects: 79*4797Seric ** sets 'Status' to represent the problem on error. 804684Seric */ 814684Seric 824684Seric openconnection(host) 834684Seric char *host; 844684Seric { 854684Seric char cmdbuf[100]; 864796Seric register int fd; 874684Seric 884684Seric /* create the command name */ 894796Seric sprintf(cmdbuf, "%s -as%s%s", MailCommand, 904796Seric Verbose ? " -v" : "", 914796Seric Debug ? " -d" : ""); 924684Seric 934796Seric if (Debug) 944796Seric printf("Creating connection to \"%s\" on %s\n", cmdbuf, host); 954796Seric 96*4797Seric /* verify host name */ 97*4797Seric if (rhost(&host) < 0) 98*4797Seric { 99*4797Seric if (Debug) 100*4797Seric printf("Unknown host %s\n", host); 101*4797Seric Status = EX_NOHOST; 102*4797Seric return (-1); 103*4797Seric } 104*4797Seric 1054684Seric /* create connection (we hope) */ 1064796Seric fd = rexec(&host, SHELLSERVER, cmdbuf, MailUser, MailPassword); 1074796Seric if (fd < 0) 108*4797Seric { 109*4797Seric Status = EX_TEMPFAIL; 1104796Seric return (-1); 111*4797Seric } 1124796Seric InConnection = fdopen(fd, "r"); 1134796Seric OutConnection = fdopen(fd, "w"); 1144796Seric if (InConnection == NULL || OutConnection == NULL) 115*4797Seric { 116*4797Seric Status = EX_SOFTWARE; 1174796Seric return (-1); 118*4797Seric } 1194684Seric 1204796Seric if (Debug) 1214796Seric printf("Connection open to %s\n", host); 1224796Seric 1234796Seric return (0); 1244684Seric } 1254684Seric /* 126*4797Seric ** CLOSECONNECTION -- close the connection to the SMTP server. 127*4797Seric ** 128*4797Seric ** This routine also sends a handshake. 129*4797Seric ** 130*4797Seric ** Parameters: 131*4797Seric ** none. 132*4797Seric ** 133*4797Seric ** Returns: 134*4797Seric ** none. 135*4797Seric ** 136*4797Seric ** Side Effects: 137*4797Seric ** Closes the connection. 138*4797Seric */ 139*4797Seric 140*4797Seric closeconnection() 141*4797Seric { 142*4797Seric register int r; 143*4797Seric 144*4797Seric message("QUIT"); 145*4797Seric r = reply(); 146*4797Seric 147*4797Seric if (Debug) 148*4797Seric printf("Closing connection, reply = %d\n", r); 149*4797Seric } 150*4797Seric /* 1514684Seric ** RUNSMTP -- run the SMTP protocol over connection. 1524684Seric ** 1534684Seric ** Parameters: 1544684Seric ** fr -- from person. 1554684Seric ** tolist -- list of recipients. 1564684Seric ** 1574684Seric ** Returns: 1584684Seric ** none. 1594684Seric ** 1604684Seric ** Side Effects: 1614684Seric ** Sends the mail via SMTP. 1624684Seric */ 1634684Seric 164*4797Seric # define REPLYTYPE(r) ((r) / 100) 165*4797Seric 1664796Seric runsmtp(fr, tolist) 1674684Seric char *fr; 1684684Seric char **tolist; 1694684Seric { 1704684Seric register int r; 1714684Seric register char **t; 1724684Seric char buf[MAXLINE]; 1734684Seric 174*4797Seric /* 175*4797Seric ** Get the greeting message. 176*4797Seric ** This should appear spontaneously. 177*4797Seric */ 178*4797Seric 1794796Seric r = reply(); 180*4797Seric if (REPLYTYPE(r) != 2) 1814684Seric return (EX_TEMPFAIL); 1824684Seric 183*4797Seric /* 184*4797Seric ** Send the MAIL command. 185*4797Seric ** Designates the sender. 186*4797Seric */ 187*4797Seric 188*4797Seric message("MAIL From:<%s>", fr); 1894796Seric r = reply(); 190*4797Seric if (REPLYTYPE(r) == 4) 191*4797Seric return (EX_TEMPFAIL); 1924684Seric if (r != 250) 1934684Seric return (EX_SOFTWARE); 1944684Seric 195*4797Seric /* 196*4797Seric ** Send the recipients. 197*4797Seric */ 198*4797Seric 1994684Seric for (t = tolist; *t != NULL; t++) 2004684Seric { 201*4797Seric message("MRCP To:<%s>", *t); 2024796Seric r = reply(); 203*4797Seric if (REPLYTYPE(r) == 4) 204*4797Seric return (EX_TEMPFAIL); 2054684Seric if (r != 250) 2064684Seric return (EX_NOUSER); 2074684Seric } 2084684Seric 209*4797Seric /* 210*4797Seric ** Send the data. 211*4797Seric ** Dot hiding is done here. 212*4797Seric */ 213*4797Seric 214*4797Seric message("DATA"); 2154796Seric r = reply(); 216*4797Seric if (REPLYTYPE(r) == 4) 217*4797Seric return (EX_TEMPFAIL); 2184684Seric if (r != 354) 2194684Seric return (EX_SOFTWARE); 2204684Seric while (fgets(buf, sizeof buf, stdin) != NULL) 2214684Seric { 2224684Seric /* change trailing newline to crlf */ 2234684Seric register char *p = index(buf, '\n'); 2244684Seric 2254684Seric if (p != NULL) 2264684Seric *p = '\0'; 227*4797Seric message("%s%s", buf[0] == '.' ? "." : "", buf); 2284684Seric } 229*4797Seric message("."); 2304796Seric r = reply(); 231*4797Seric if (REPLYTYPE(r) == 4) 232*4797Seric return (EX_TEMPFAIL); 2334684Seric if (r != 250) 2344684Seric return (EX_SOFTWARE); 2354684Seric 236*4797Seric /* 237*4797Seric ** Make the actual delivery happen. 238*4797Seric */ 239*4797Seric 240*4797Seric message("DOIT"); 2414796Seric r = reply(); 2424684Seric if (r != 250) 2434684Seric return (EX_TEMPFAIL); 2444684Seric 2454684Seric return (EX_OK); 2464684Seric } 2474684Seric /* 2484684Seric ** REPLY -- read arpanet reply 2494684Seric ** 2504684Seric ** Parameters: 2514796Seric ** none. 2524684Seric ** 2534684Seric ** Returns: 2544684Seric ** reply code it reads. 2554684Seric ** 2564684Seric ** Side Effects: 2574684Seric ** flushes the mail file. 2584684Seric */ 2594684Seric 2604796Seric reply() 2614684Seric { 2624796Seric fflush(OutConnection); 2634684Seric 2644796Seric if (Debug) 2654796Seric printf("reply\n"); 2664796Seric 2674684Seric /* read the input line */ 2684684Seric for (;;) 2694684Seric { 2704684Seric char buf[MAXLINE]; 2714684Seric register int r; 2724684Seric 2734796Seric if (fgets(buf, sizeof buf, InConnection) == NULL) 2744684Seric return (-1); 2754684Seric if (Verbose) 2764684Seric fputs(buf, stdout); 2774796Seric if (buf[3] == '-' || !isdigit(buf[0])) 2784684Seric continue; 2794684Seric r = atoi(buf); 2804684Seric if (r < 100) 2814684Seric continue; 2824684Seric return (r); 2834684Seric } 2844684Seric } 2854796Seric /* 2864796Seric ** MESSAGE -- send message to server 2874796Seric ** 2884796Seric ** Parameters: 2894796Seric ** f -- format 2904796Seric ** a, b, c -- parameters 2914796Seric ** 2924796Seric ** Returns: 2934796Seric ** none. 2944796Seric ** 2954796Seric ** Side Effects: 2964796Seric ** writes message to OutChannel. 2974796Seric */ 2984796Seric 2994796Seric message(f, a, b, c) 3004796Seric char *f; 3014796Seric { 3024796Seric char buf[100]; 3034796Seric 3044796Seric sprintf(buf, f, a, b, c); 305*4797Seric strcat(buf, "\r\n"); 3064796Seric if (Debug) 3074796Seric fputs(buf, stdout); 3084796Seric fputs(buf, OutConnection); 3094796Seric } 310