|
|
1.1 root 1: /* mailsrvr.c */
2:
3: /* Synchronet Mail (SMTP/POP3) server and sendmail threads */
4:
5: /* $Id: mailsrvr.c,v 1.45 2000/12/20 18:47:18 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: /* Platform-specific headers */
39: #ifdef _WIN32
40:
41: #include <io.h> /* open/close */
42: #include <share.h> /* share open flags */
43: #include <process.h> /* _beginthread */
44: #include <windows.h> /* required for mmsystem.h */
45: #include <mmsystem.h> /* SND_ASYNC */
46:
47: #elif defined(__unix__)
48:
49: #include <signal.h> /* signal/SIGPIPE */
50:
51: #endif
52:
53:
54: /* ANSI C Library headers */
55: #include <stdio.h>
56: #include <stdlib.h> /* ltoa in GNU C lib */
57: #include <stdarg.h> /* va_list */
58: #include <string.h> /* strrchr */
59: #include <ctype.h> /* isdigit */
60: #include <fcntl.h> /* Open flags */
61: #include <errno.h> /* errno */
62:
63: /* Synchronet-specific headers */
64: #include "sbbs.h"
65: #include "mailsrvr.h"
66: #include "crc32.h"
67:
68: /* Constants */
69: #define MAIL_VERSION "1.10"
70:
71: int dns_getmx(char* name, char* mx, char* mx2, DWORD intf, DWORD ip_addr, BOOL use_tcp);
72:
73: #define SMTP_OK "250 OK"
74: #define SMTP_BADSEQ "503 Bad sequence of commands"
75:
76: #define TIMEOUT_THREAD_WAIT 60 /* Seconds */
77:
78: #define STATUS_WFC "Listening"
79:
80: static const char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
81: static const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
82: ,"Jul","Aug","Sep","Oct","Nov","Dec"};
83:
84: static mail_startup_t* startup=NULL;
85: static scfg_t scfg;
86: static SOCKET server_socket=INVALID_SOCKET;
87: static SOCKET pop3_socket=INVALID_SOCKET;
88: static int active_clients=0;
89: static int active_sendmail=0;
90: static BOOL sendmail_running=FALSE;
91: static DWORD sockets=0;
92:
93: typedef struct {
94: SOCKET socket;
95: SOCKADDR_IN client_addr;
96: } smtp_t,pop3_t;
97:
98: static int lprintf(char *fmt, ...)
99: {
100: va_list argptr;
101: char sbuf[1024];
102:
103: if(startup==NULL || startup->lputs==NULL)
104: return(0);
105:
106: va_start(argptr,fmt);
107: vsprintf(sbuf,fmt,argptr);
108: va_end(argptr);
109: return(startup->lputs(sbuf));
110: }
111:
112: #ifdef _WINSOCKAPI_
113:
114: static WSADATA WSAData;
115: static BOOL WSAInitialized=FALSE;
116:
117: static BOOL winsock_startup(void)
118: {
119: int status; /* Status Code */
120:
121: if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0) {
122: lprintf("%s %s",WSAData.szDescription, WSAData.szSystemStatus);
123: WSAInitialized=TRUE;
124: return (TRUE);
125: }
126:
127: lprintf("!WinSock startup ERROR %d", status);
128: return (FALSE);
129: }
130:
131: #else /* No WINSOCK */
132:
133: #define winsock_startup() (TRUE)
134:
135: #endif
136:
137: static void update_clients(void)
138: {
139: if(startup!=NULL && startup->clients!=NULL)
140: startup->clients(active_clients+active_sendmail);
141: }
142:
143: static void client_on(SOCKET sock, client_t* client)
144: {
145: if(startup!=NULL && startup->client_on!=NULL)
146: startup->client_on(TRUE,sock,client);
147: }
148:
149: static void client_off(SOCKET sock)
150: {
151: if(startup!=NULL && startup->client_on!=NULL)
152: startup->client_on(FALSE,sock,NULL);
153: }
154:
155: static void thread_up(void)
156: {
157: if(startup!=NULL && startup->thread_up!=NULL)
158: startup->thread_up(TRUE);
159: }
160:
161: static void thread_down(void)
162: {
163: if(startup!=NULL && startup->thread_up!=NULL)
164: startup->thread_up(FALSE);
165: }
166:
167: SOCKET mail_open_socket(int type)
168: {
169: SOCKET sock;
170:
171: sock=socket(AF_INET, type, IPPROTO_IP);
172: if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL)
173: startup->socket_open(TRUE);
174: if(sock!=INVALID_SOCKET) {
175: sockets++;
176: #if 0 /*def _DEBUG */
177: lprintf("%04d Socket opened (%d sockets in use)",sock,sockets);
178: #endif
179: }
180: return(sock);
181: }
182:
183: int mail_close_socket(SOCKET sock)
184: {
185: int result;
186:
187: shutdown(sock,SHUT_RDWR); /* required on Unix */
188: result=closesocket(sock);
189: if(/* result==0 && */ startup!=NULL && startup->socket_open!=NULL)
190: startup->socket_open(FALSE);
191: sockets--;
192: if(result!=0)
193: lprintf("%04d !ERROR %d closing socket",sock, ERROR_VALUE);
194: else {
195: #if 0 /*def _DEBUG */
196: lprintf("%04d Socket closed (%d sockets in use)",sock,sockets);
197: #endif
198: }
199:
200: return(result);
201: }
202:
203: static void status(char* str)
204: {
205: if(startup!=NULL && startup->status!=NULL)
206: startup->status(str);
207: }
208:
209: static int sockprintf(SOCKET sock, char *fmt, ...)
210: {
211: int len;
212: int result;
213: va_list argptr;
214: char sbuf[1024];
215:
216: va_start(argptr,fmt);
217: len=vsprintf(sbuf,fmt,argptr);
218: if(startup->options&MAIL_OPT_DEBUG_TX)
219: lprintf("%04d TX: %s", sock, sbuf);
220: strcat(sbuf,"\r\n");
221: len+=2;
222: va_end(argptr);
223: while((result=send(sock,sbuf,len,0))!=len) {
224: if(result==SOCKET_ERROR) {
225: if(ERROR_VALUE==EWOULDBLOCK) {
226: mswait(1);
227: continue;
228: }
229: if(ERROR_VALUE==ECONNRESET)
230: lprintf("%04d Connection reset by peer on send",sock);
231: else if(ERROR_VALUE==ECONNABORTED)
232: lprintf("%04d Connection aborted by peer on send",sock);
233: else
234: lprintf("%04d !ERROR %d sending on socket",sock,ERROR_VALUE);
235: return(0);
236: }
237: lprintf("%04d !ERROR: short send on socket: %d instead of %d",sock,result,len);
238: }
239: return(len);
240: }
241:
242: static time_t checktime(void)
243: {
244: struct tm tm;
245:
246: memset(&tm,0,sizeof(tm));
247: tm.tm_year=94;
248: tm.tm_mday=1;
249: return(mktime(&tm)-0x2D24BD00L);
250: }
251:
252: static void recverror(SOCKET socket, int rd)
253: {
254: if(rd==0)
255: lprintf("%04d Socket closed by peer on receive",socket);
256: else if(rd==SOCKET_ERROR) {
257: if(ERROR_VALUE==ECONNRESET)
258: lprintf("%04d Connection reset by peer on receive",socket);
259: else if(ERROR_VALUE==ECONNABORTED)
260: lprintf("%04d Connection aborted by peer on receive",socket);
261: else
262: lprintf("%04d !Socket error %d on receive", socket, ERROR_VALUE);
263: } else
264: lprintf("%04d !recv on socket returned unexpected value: %d",socket,rd);
265: }
266:
267: static int sockreadline(SOCKET socket, char* buf, int len)
268: {
269: char ch;
270: int i,rd=0;
271: time_t start;
272:
273: start=time(NULL);
274:
275: while(rd<len-1) {
276: i= recv(socket, &ch, 1, 0);
277: if(i<1) {
278: if(ERROR_VALUE==EWOULDBLOCK) {
279: if((time(NULL)-start)>startup->max_inactivity) {
280: lprintf("%04d !Socket inactive",socket);
281: return(0);
282: }
283: mswait(1);
284: continue;
285: }
286: recverror(socket,i);
287: return(i);
288: }
289: if(ch=='\n' && rd>=1) {
290: break;
291: }
292: buf[rd++]=ch;
293: }
294: buf[rd-1]=0;
295:
296: return(rd);
297: }
298:
299: /************************************************/
300: /* Truncates white-space chars off end of 'str' */
301: /************************************************/
302: static void truncsp(char *str)
303: {
304: uint c;
305:
306: c=strlen(str);
307: while(c && (uchar)str[c-1]<=' ') c--;
308: str[c]=0;
309: }
310:
311:
312: static char* alias(char* name, char* alias)
313: {
314: int file;
315: char* p=name;
316: char* np;
317: char* tp;
318: char fname[MAX_PATH];
319: FILE* fp;
320:
321: sprintf(fname,"%salias.cfg",scfg.ctrl_dir);
322: if((file=sopen(fname,O_RDONLY|O_BINARY,SH_DENYNO))==-1)
323: return(name);
324:
325: if((fp=fdopen(file,"rb"))==NULL) {
326: close(file);
327: return(name);
328: }
329:
330: while(!feof(fp)) {
331: if(!fgets(alias,80,fp))
332: break;
333: np=alias;
334: while(*np && *np<=' ') np++;
335: if(*np==';')
336: continue;
337: tp=np;
338: while(*tp && *tp>' ') tp++;
339: if(*tp) *tp=0;
340: if(!stricmp(np,name)) {
341: np=tp+1;
342: while(*np && *np<=' ') np++;
343: p=np;
344: truncsp(p);
345: lprintf("0000 Alias: %s",p);
346: break;
347: }
348: }
349: fclose(fp);
350: return(p);
351: }
352:
353: static BOOL sockgetrsp(SOCKET socket, char* rsp, char *buf, int len)
354: {
355: int rd;
356:
357: while(1) {
358: rd = sockreadline(socket, buf, len);
359: if(rd<1)
360: return(FALSE);
361: if(buf[3]=='-') { /* Multi-line response */
362: if(startup->options&MAIL_OPT_DEBUG_RX_RSP)
363: lprintf("%04d RX: %s",socket,buf);
364: continue;
365: }
366: if(strnicmp(buf,rsp,strlen(rsp))) {
367: lprintf("%04d !INVALID RESPONSE: '%s' Expected: '%s'", socket, buf, rsp);
368: return(FALSE);
369: }
370: break;
371: }
372: if(startup->options&MAIL_OPT_DEBUG_RX_RSP)
373: lprintf("%04d RX: %s",socket,buf);
374: return(TRUE);
375: }
376:
377: static void usermailaddr(char* addr, char* name)
378: {
379: int i;
380:
381: if(strchr(name,'.')) /* unresolved exception here Nov-06-2000 */
382: sprintf(addr,"\"%s\"@",name);
383: else {
384: sprintf(addr,"%s@",name);
385: /* convert "first last@" to "first.last@" */
386: for(i=0;addr[i];i++)
387: if(addr[i]==' ' || addr[i]&0x80)
388: addr[i]='.';
389: strlwr(addr);
390: }
391: strcat(addr,scfg.sys_inetaddr);
392: }
393:
394: static char *msgdate(when_t when, char* buf)
395: {
396: struct tm tm;
397: struct tm* tm_p;
398:
399: tm_p=localtime((const time_t*)&when.time);
400: if(tm_p!=NULL)
401: tm=*tm_p;
402: else
403: memset(&tm,0,sizeof(tm));
404: sprintf(buf,"%s, %d %s %d %02d:%02d:%02d %s"
405: ,wday[tm.tm_wday]
406: ,tm.tm_mday
407: ,mon[tm.tm_mon]
408: ,1900+tm.tm_year
409: ,tm.tm_hour
410: ,tm.tm_min
411: ,tm.tm_sec
412: ,zonestr(when.zone)
413: );
414: return(buf);
415: }
416:
417: #define MAX_LINE_LEN 1000
418:
419: static void sockmsgtxt(SOCKET socket, smbmsg_t* msg, char* msgtxt, char* fromaddr
420: ,ulong maxlines)
421: {
422: char toaddr[256];
423: char date[64];
424: char* p;
425: char* tp;
426: int i;
427: ulong line;
428:
429: /* HEADERS */
430: sockprintf(socket,"Date: %s",msgdate(msg->hdr.when_written,date));
431: if(fromaddr[0]=='<')
432: sockprintf(socket,"From: \"%s\" %s",msg->from,fromaddr);
433: else
434: sockprintf(socket,"From: \"%s\" <%s>",msg->from,fromaddr);
435: sockprintf(socket,"Subject: %s",msg->subj);
436: if(msg->to_net.type==NET_INTERNET || msg->to_net.type==NET_QWK) {
437: if(*((char*)msg->to_net.addr)=='<')
438: sockprintf(socket,"To: \"%s\" %s",msg->to,(char*)msg->to_net.addr);
439: else
440: sockprintf(socket,"To: \"%s\" <%s>",msg->to,(char*)msg->to_net.addr);
441: } else {
442: usermailaddr(toaddr,msg->to);
443: sockprintf(socket,"To: \"%s\" <%s>",msg->to,toaddr);
444: }
445: if(msg->replyto_net.type==NET_INTERNET)
446: sockprintf(socket,"Reply-To: %s",msg->replyto_net.addr);
447: else
448: sockprintf(socket,"Reply-To: %s",fromaddr);
449: sockprintf(socket,"Message-ID: <%08lX.%lu@%s>"
450: ,msg->hdr.when_written.time,msg->idx.number,scfg.sys_inetaddr);
451: for(i=0;i<msg->total_hfields;i++)
452: if(msg->hfield[i].type==RFC822HEADER)
453: sockprintf(socket,"%s",(char*)msg->hfield_dat[i]);
454: sockprintf(socket,""); /* Header Terminator */
455: /* MESSAGE BODY */
456: line=0;
457: p=msgtxt;
458: while(*p && line<maxlines) {
459: tp=strchr(p,'\n');
460: if(tp) {
461: if(tp-p>MAX_LINE_LEN)
462: tp=p+MAX_LINE_LEN;
463: *tp=0;
464: }
465: truncsp(p); /* Takes care of '\r' or spaces */
466: if(*p=='.')
467: i=sockprintf(socket,".%.*s",MAX_LINE_LEN,p);
468: else
469: i=sockprintf(socket,"%.*s",MAX_LINE_LEN,p);
470: if(!i)
471: break;
472: if(tp==NULL)
473: break;
474: p=tp+1;
475: line++;
476: mswait(1);
477: }
478: sockprintf(socket,"."); /* End of text */
479: }
480:
481: static u_long resolve_ip(char *addr)
482: {
483: HOSTENT* host;
484:
485: if(isdigit(addr[0]) && strchr(addr,'.'))
486: return(inet_addr(addr));
487: if ((host=gethostbyname(addr))==NULL) {
488: lprintf("0000 !ERROR resolving host name: %s",addr);
489: return(0);
490: }
491: return(*((ulong*)host->h_addr_list[0]));
492: }
493:
494:
495: static void pop3_thread(void* arg)
496: {
497: char* p;
498: char str[128];
499: char buf[512];
500: char host_name[128];
501: char host_ip[64];
502: char username[LEN_ALIAS+1];
503: char password[LEN_PASS+1];
504: char fromaddr[256];
505: char* msgtxt;
506: int i;
507: int rd;
508: ulong l;
509: ulong lines;
510: ulong msgs,bytes,msgnum,msgbytes;
511: SOCKET socket;
512: HOSTENT* host;
513: smb_t smb;
514: smbmsg_t msg;
515: user_t user;
516: client_t client;
517: mail_t* mail;
518: pop3_t pop3=*(pop3_t*)arg;
519:
520: thread_up();
521:
522: free(arg);
523:
524: socket=pop3.socket;
525:
526: if(startup->options&MAIL_OPT_DEBUG_POP3)
527: lprintf("%04d POP3 session thread started", socket);
528:
529: #ifdef _WIN32
530: if(startup->pop3_sound[0] && !(startup->options&MAIL_OPT_MUTE))
531: PlaySound(startup->pop3_sound, NULL, SND_ASYNC|SND_FILENAME);
532: #endif
533:
534: strcpy(host_ip,inet_ntoa(pop3.client_addr.sin_addr));
535:
536: if(startup->options&MAIL_OPT_DEBUG_POP3)
537: lprintf("%04d POP3 connection accepted from: %s"
538: ,socket, host_ip);
539:
540: if(startup->options&MAIL_OPT_NO_HOST_LOOKUP)
541: host=NULL;
542: else
543: host=gethostbyaddr((char *)&pop3.client_addr.sin_addr
544: ,sizeof(pop3.client_addr.sin_addr),AF_INET);
545:
546: if(host!=NULL && host->h_name!=NULL)
547: sprintf(host_name,"%.*s",(int)sizeof(host_name)-1,host->h_name);
548: else
549: strcpy(host_name,"<no name>");
550:
551: if(startup->options&MAIL_OPT_DEBUG_POP3)
552: lprintf("%04d POP3 client name: %s", socket, host_name);
553:
554: if(trashcan(&scfg,host_ip,"ip")) {
555: lprintf("%04d !POP3 client blocked in ip.can: %s"
556: ,socket, host_ip);
557: sockprintf(socket,"-ERR Access denied.");
558: mail_close_socket(socket);
559: thread_down();
560: return;
561: }
562:
563: if(trashcan(&scfg,host_name,"host")) {
564: lprintf("%04d !POP3 client blocked in host.can: %s"
565: ,socket, host_name);
566: sockprintf(socket,"-ERR Access denied.");
567: mail_close_socket(socket);
568: thread_down();
569: return;
570: }
571:
572: active_clients++;
573: update_clients();
574:
575: /* Initialize client display */
576: client.size=sizeof(client);
577: client.time=time(NULL);
578: sprintf(client.addr,"%.*s",(int)sizeof(client.addr)-1,host_ip);
579: sprintf(client.host,"%.*s",(int)sizeof(client.host)-1,host_name);
580: client.port=ntohs(pop3.client_addr.sin_port);
581: client.protocol="POP3";
582: client.user="<unknown>";
583: client_on(socket,&client);
584:
585: sprintf(str,"POP3: %s", host_ip);
586: status(str);
587:
588: mail=NULL;
589:
590: do {
591: memset(&smb,0,sizeof(smb));
592: memset(&msg,0,sizeof(msg));
593:
594: sprintf(smb.file,"%smail",scfg.data_dir);
595: if((i=smb_open(&smb))!=0) {
596: lprintf("%04d !Error %d (%s) opening %s",socket,i,smb.last_error,smb.file);
597: sockprintf(socket,"-ERR %d opening %s",i,smb.file);
598: break;
599: }
600:
601: sockprintf(socket,"+OK Synchronet POP3 Server for %s v%s Ready"
602: ,PLATFORM_DESC,MAIL_VERSION);
603:
604: if(!sockgetrsp(socket,"USER ",buf,sizeof(buf))) {
605: sockprintf(socket,"-ERR USER command expected");
606: break;
607: }
608: p=buf+5;
609: while(*p && *p<=' ') p++;
610: sprintf(username,"%.*s",(int)sizeof(username)-1,p);
611: sockprintf(socket,"+OK");
612: if(!sockgetrsp(socket,"PASS ",buf,sizeof(buf))) {
613: sockprintf(socket,"-ERR PASS command expected");
614: break;
615: }
616: p=buf+5;
617: while(*p && *p<=' ') p++;
618: sprintf(password,"%.*s",(int)sizeof(password)-1,p);
619: user.number=matchuser(&scfg,username);
620: if(!user.number) {
621: lprintf("%04d !POP3 UNKNOWN USER: %s (password: %s)"
622: , socket, username, password);
623: sockprintf(socket,"-ERR");
624: break;
625: }
626: if((i=getuserdat(&scfg, &user))!=0) {
627: lprintf("%04d !POP3 ERROR %d getting data on user #%u (%s)"
628: ,socket, i, user.number, username);
629: sockprintf(socket, "-ERR");
630: break;
631: }
632: if(user.misc&(DELETED|INACTIVE)) {
633: lprintf("%04d !POP3 DELETED or INACTIVE user #%u (%s)"
634: ,socket, user.number, username);
635: sockprintf(socket, "-ERR");
636: break;
637: }
638: if(stricmp(password,user.pass)) {
639: lprintf("%04d !POP3 WRONG PASSWORD for user %s: '%s' expected '%s'"
640: ,socket, username, password, user.pass);
641: sockprintf(socket, "-ERR");
642: break;
643: }
644:
645: /* Update client display */
646: client.user=user.alias;
647: client_on(socket,&client);
648:
649: if(startup->options&MAIL_OPT_DEBUG_POP3)
650: lprintf("%04d POP3 %s logged in", socket, user.alias);
651: sprintf(str,"POP3: %s",user.alias);
652: status(str);
653:
654: sockprintf(socket,"+OK User verified");
655:
656: mail=loadmail(&smb,&msgs,user.number,MAIL_YOUR,0);
657:
658: for(l=bytes=0;l<msgs;l++) {
659: msg.hdr.number=mail[l].number;
660: if((i=smb_getmsgidx(&smb,&msg))!=0) {
661: lprintf("%04d !POP3 ERROR %d getting message index"
662: ,socket ,i);
663: break;
664: }
665: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
666: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
667: ,socket ,i ,msg.hdr.number);
668: break;
669: }
670: i=smb_getmsghdr(&smb,&msg);
671: smb_unlockmsghdr(&smb,&msg);
672: if(i!=0) {
673: lprintf("%04d !POP3 ERROR %d getting message header #%lu"
674: ,socket, i, msg.hdr.number);
675: break;
676: }
677: for(i=0;i<msg.hdr.total_dfields;i++)
678: if(msg.dfield[i].type==TEXT_BODY || msg.dfield[i].type==TEXT_TAIL)
679: bytes+=msg.dfield[i].length;
680: smb_freemsgmem(&msg);
681: }
682:
683: while(1) { /* TRANSACTION STATE */
684: rd = sockreadline(socket, buf, sizeof(buf));
685: if(rd<1)
686: break;
687: if(startup->options&MAIL_OPT_DEBUG_POP3)
688: lprintf("%04d POP3 RX: %s", socket, buf);
689: if(!stricmp(buf, "NOOP")) {
690: sockprintf(socket,"+OK");
691: continue;
692: }
693: if(!stricmp(buf, "QUIT")) {
694: sockprintf(socket,"+OK");
695: break;
696: }
697: if(!stricmp(buf, "STAT")) {
698: sockprintf(socket,"+OK %lu %lu",msgs,bytes);
699: continue;
700: }
701: if(!stricmp(buf, "RSET")) {
702: for(l=0;l<msgs;l++) {
703: msg.hdr.number=mail[l].number;
704: if((i=smb_getmsgidx(&smb,&msg))!=0) {
705: lprintf("%04d !POP3 ERROR %d getting message index"
706: ,socket, i);
707: break;
708: }
709: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
710: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
711: ,socket, i,msg.hdr.number);
712: break;
713: }
714: if((i=smb_getmsghdr(&smb,&msg))!=0) {
715: lprintf("%04d !POP3 ERROR %d getting message header #%lu"
716: ,socket, i, msg.hdr.number);
717: break;
718: }
719: msg.hdr.attr=mail[l].attr;
720: msg.idx.attr=msg.hdr.attr;
721: if((i=smb_putmsg(&smb,&msg))!=0)
722: lprintf("%04d !POP3 ERROR %d updating message index"
723: ,socket, i);
724: smb_unlockmsghdr(&smb,&msg);
725: smb_freemsgmem(&msg);
726: }
727: if(l<msgs)
728: sockprintf(socket,"-ERR %d messages reset (ERROR: %d)",l,i);
729: else
730: sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
731: continue;
732: }
733: if(!strnicmp(buf, "LIST",4) || !strnicmp(buf,"UIDL",4)) {
734: p=buf+4;
735: while(*p && *p<=' ') p++;
736: if(isdigit(*p)) {
737: msgnum=atol(p);
738: if(msgnum<1 || msgnum>msgs) {
739: lprintf("%04d !POP3 INVALID message #%ld"
740: ,socket, msgnum);
741: sockprintf(socket,"-ERR no such message");
742: continue;
743: }
744: msg.hdr.number=mail[msgnum-1].number;
745: if((i=smb_getmsgidx(&smb,&msg))!=0) {
746: lprintf("%04d !POP3 ERROR %d getting message index"
747: ,socket, i);
748: sockprintf(socket,"-ERR %d getting message index",i);
749: break;
750: }
751: if(msg.idx.attr&MSG_DELETE) {
752: lprintf("%04d !POP3 ATTEMPT to list deleted message"
753: ,socket);
754: sockprintf(socket,"-ERR message deleted");
755: continue;
756: }
757: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
758: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
759: ,socket, i, msg.hdr.number);
760: sockprintf(socket,"-ERR %d locking message header",i);
761: continue;
762: }
763: i=smb_getmsghdr(&smb,&msg);
764: smb_unlockmsghdr(&smb,&msg);
765: if(i!=0) {
766: smb_freemsgmem(&msg);
767: lprintf("%04d !POP3 ERROR %d getting message header #%lu"
768: ,socket, i,msg.hdr.number);
769: sockprintf(socket,"-ERR %d getting message header",i);
770: continue;
771: }
772: if(!strnicmp(buf, "LIST",4)) {
773: msgbytes=0;
774: for(i=0;i<msg.hdr.total_dfields;i++)
775: if(msg.dfield[i].type==TEXT_BODY || msg.dfield[i].type==TEXT_TAIL)
776: msgbytes+=msg.dfield[i].length;
777: sockprintf(socket,"+OK %lu %lu",msgnum,msgbytes);
778: } else /* UIDL */
779: sockprintf(socket,"+OK %lu %lu",msgnum,msg.hdr.number);
780:
781: smb_freemsgmem(&msg);
782: continue;
783: }
784: /* List ALL messages */
785: sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
786: for(l=0;l<msgs;l++) {
787: msg.hdr.number=mail[l].number;
788: if((i=smb_getmsgidx(&smb,&msg))!=0) {
789: lprintf("%04d !POP3 ERROR %d getting message index"
790: ,socket, i);
791: break;
792: }
793: if(msg.idx.attr&MSG_DELETE)
794: continue;
795: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
796: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
797: ,socket, i,msg.hdr.number);
798: break;
799: }
800: i=smb_getmsghdr(&smb,&msg);
801: smb_unlockmsghdr(&smb,&msg);
802: if(i!=0) {
803: smb_freemsgmem(&msg);
804: lprintf("%04d !POP3 ERROR %d getting message header #%lu"
805: ,socket, i,msg.hdr.number);
806: break;
807: }
808: if(!strnicmp(buf, "LIST",4)) {
809: msgbytes=0;
810: for(i=0;i<msg.hdr.total_dfields;i++)
811: if(msg.dfield[i].type==TEXT_BODY || msg.dfield[i].type==TEXT_TAIL)
812: msgbytes+=msg.dfield[i].length;
813: sockprintf(socket,"%lu %lu",l+1,msgbytes);
814: } else /* UIDL */
815: sockprintf(socket,"%lu %lu",l+1,msg.hdr.number);
816:
817: smb_freemsgmem(&msg);
818: }
819: sockprintf(socket,".");
820: continue;
821: }
822: if(!strnicmp(buf, "RETR ",5) || !strnicmp(buf,"TOP ",4)) {
823: sprintf(str,"POP3: %s", user.alias);
824: status(str);
825:
826: lines=-1;
827: p=buf+4;
828: while(*p && *p<=' ') p++;
829: msgnum=atol(p);
830:
831: if(!strnicmp(buf,"TOP ",4)) {
832: while(*p && isdigit(*p)) p++;
833: while(*p && *p<=' ') p++;
834: lines=atol(p);
835: }
836: if(msgnum<1 || msgnum>msgs) {
837: lprintf("%04d !POP3 %s ATTEMPTED to retrieve an INVALID message #%ld"
838: ,socket, user.alias, msgnum);
839: sockprintf(socket,"-ERR no such message");
840: continue;
841: }
842: msg.hdr.number=mail[msgnum-1].number;
843:
844: lprintf("%04d POP3 %s retrieving message #%ld"
845: ,socket, user.alias, msg.hdr.number);
846:
847: if((i=smb_getmsgidx(&smb,&msg))!=0) {
848: lprintf("%04d !POP3 ERROR %d getting message index"
849: ,socket, i);
850: sockprintf(socket,"-ERR %d getting message index",i);
851: continue;
852: }
853: if(msg.idx.attr&MSG_DELETE) {
854: lprintf("%04d !POP3 ATTEMPT to retrieve deleted message"
855: ,socket);
856: sockprintf(socket,"-ERR message deleted");
857: continue;
858: }
859: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
860: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
861: ,socket, i, msg.hdr.number);
862: sockprintf(socket,"-ERR %d locking message header",i);
863: continue;
864: }
865: if((i=smb_getmsghdr(&smb,&msg))!=0) {
866: smb_unlockmsghdr(&smb,&msg);
867: lprintf("%04d !POP3 ERROR %d getting message header #%lu"
868: ,socket, i, msg.hdr.number);
869: sockprintf(socket,"-ERR %d getting message header",i);
870: continue;
871: }
872: smb_unlockmsghdr(&smb,&msg);
873:
874: if((msgtxt=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))==NULL) {
875: smb_freemsgmem(&msg);
876: lprintf("%04d !POP3 ERROR retrieving message text for message #%lu"
877: ,socket, msg.hdr.number);
878: sockprintf(socket,"-ERR retrieving message text");
879: continue;
880: }
881:
882: sockprintf(socket,"+OK message follows");
883: if(msg.from_net.type==NET_INTERNET)
884: strcpy(fromaddr,msg.from_net.addr);
885: else if(msg.from_net.type==NET_QWK)
886: sprintf(fromaddr,"\"%s@%s\"@%s"
887: ,msg.from,(char*)msg.from_net.addr,scfg.sys_inetaddr);
888: else
889: usermailaddr(fromaddr,msg.from); /* unresolved exception here Nov-06-2000 */
890: lprintf("%04d POP3 sending message text (%u bytes)"
891: ,socket,strlen(msgtxt));
892: sockmsgtxt(socket,&msg,msgtxt,fromaddr,lines);
893: /* if(startup->options&MAIL_OPT_DEBUG_POP3) */
894: lprintf("%04d POP3 message transfer complete",socket);
895:
896: msg.hdr.attr|=MSG_READ;
897: msg.idx.attr=msg.hdr.attr;
898: msg.hdr.netattr|=MSG_SENT;
899:
900: if((i=smb_lockmsghdr(&smb,&msg))!=0)
901: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
902: ,socket, i, msg.hdr.number);
903: if((i=smb_putmsg(&smb,&msg))!=0)
904: lprintf("%04d !POP3 ERROR %d marking message #%lu as read"
905: ,socket, i, msg.hdr.number);
906: smb_unlockmsghdr(&smb,&msg);
907: smb_freemsgmem(&msg);
908: smb_freemsgtxt(msgtxt);
909: continue;
910: }
911: if(!strnicmp(buf, "DELE ",5)) {
912: p=buf+5;
913: while(*p && *p<=' ') p++;
914: msgnum=atol(p);
915:
916: if(msgnum<1 || msgnum>msgs) {
917: lprintf("%04d !POP3 %s ATTEMPTED to delete an INVALID message #%ld"
918: ,socket, user.alias, msgnum);
919: sockprintf(socket,"-ERR no such message");
920: continue;
921: }
922: msg.hdr.number=mail[msgnum-1].number;
923:
924: lprintf("%04d POP3 %s deleting message #%ld"
925: ,socket, user.alias, msg.hdr.number);
926:
927: if((i=smb_getmsgidx(&smb,&msg))!=0) {
928: lprintf("%04d !POP3 ERROR %d getting message index"
929: ,socket, i);
930: sockprintf(socket,"-ERR %d getting message index",i);
931: continue;
932: }
933: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
934: lprintf("%04d !POP3 ERROR %d locking message header #%lu"
935: ,socket, i,msg.hdr.number);
936: sockprintf(socket,"-ERR %d locking message header",i);
937: continue;
938: }
939: if((i=smb_getmsghdr(&smb,&msg))!=0) {
940: smb_unlockmsghdr(&smb,&msg);
941: lprintf("%04d !POP3 ERROR %d getting message header #%lu"
942: ,socket, i,msg.hdr.number);
943: sockprintf(socket,"-ERR %d getting message header",i);
944: continue;
945: }
946: msg.hdr.attr|=MSG_DELETE;
947: msg.idx.attr=msg.hdr.attr;
948: if((i=smb_putmsg(&smb,&msg))!=0) {
949: smb_unlockmsghdr(&smb,&msg);
950: smb_freemsgmem(&msg);
951: lprintf("%04d !POP3 ERROR %d marking message as read", socket, i);
952: sockprintf(socket,"-ERR %d marking message for deletion",i);
953: continue;
954: }
955: smb_unlockmsghdr(&smb,&msg);
956: smb_freemsgmem(&msg);
957: sockprintf(socket,"+OK");
958: if(startup->options&MAIL_OPT_DEBUG_POP3)
959: lprintf("%04d POP3 message deleted", socket);
960: continue;
961: }
962: lprintf("%04d !POP3 UNSUPPORTED COMMAND: %s", socket, buf);
963: sockprintf(socket,"-ERR UNSUPPORTED COMMAND: %s",buf);
964: }
965: if(user.number)
966: putuserrec(&scfg,user.number,U_LASTON,8,ultoa(time(NULL),str,16));
967:
968: } while(0);
969:
970: status(STATUS_WFC);
971:
972: /* Free up resources here */
973: mail_close_socket(socket);
974:
975: if(mail!=NULL)
976: freemail(mail);
977:
978: smb_freemsgmem(&msg);
979: smb_close(&smb);
980:
981: if(startup->options&MAIL_OPT_DEBUG_POP3)
982: lprintf("%04d POP3 session thread terminated", socket);
983:
984: active_clients--;
985: update_clients();
986: client_off(socket);
987:
988: thread_down();
989: }
990:
991: BOOL rblchk(DWORD mail_addr_n, char* rbl_addr)
992: {
993: char name[256];
994: DWORD mail_addr;
995:
996: mail_addr=ntohl(mail_addr_n);
997: sprintf(name,"%ld.%ld.%ld.%ld.%s"
998: ,mail_addr&0xff
999: ,(mail_addr>>8)&0xff
1000: ,(mail_addr>>16)&0xff
1001: ,(mail_addr>>24)&0xff
1002: ,rbl_addr
1003: );
1004:
1005: if(gethostbyname(name)==NULL)
1006: return(FALSE);
1007:
1008: return(TRUE);
1009: }
1010:
1011:
1012: static void smtp_thread(void* arg)
1013: {
1014: int i,j,x;
1015: int rd;
1016: char str[512];
1017: char buf[1024],*p,*tp;
1018: char hdrfield[512];
1019: char alias_buf[128];
1020: char reverse_path[128];
1021: char date[64];
1022: char month[16];
1023: char rcpt_name[128];
1024: char rcpt_addr[128];
1025: char sender[128]={0};
1026: char sender_addr[128]={0};
1027: char hello_name[128];
1028: char host_name[128];
1029: char host_ip[64];
1030: int addr_len;
1031: ushort xlat;
1032: ushort nettype=NET_NONE;
1033: uint usernum;
1034: ulong crc;
1035: ulong length;
1036: ulong offset;
1037: BOOL esmtp=FALSE;
1038: FILE* msgtxt=NULL;
1039: char msgtxt_fname[MAX_PATH];
1040: FILE* rcptlst;
1041: char rcptlst_fname[MAX_PATH];
1042: FILE* spy=NULL;
1043: SOCKET socket;
1044: HOSTENT* host;
1045: smb_t smb;
1046: smbmsg_t msg;
1047: smbmsg_t newmsg;
1048: user_t user;
1049: client_t client;
1050: struct tm tm;
1051: smtp_t smtp=*(smtp_t*)arg;
1052: SOCKADDR_IN server_addr;
1053: enum {
1054: SMTP_STATE_INITIAL
1055: ,SMTP_STATE_HELO
1056: ,SMTP_STATE_MAIL_FROM
1057: ,SMTP_STATE_RCPT_TO
1058: ,SMTP_STATE_DATA_HEADER
1059: ,SMTP_STATE_DATA_BODY
1060:
1061: } state = SMTP_STATE_INITIAL;
1062:
1063: thread_up();
1064:
1065: free(arg);
1066:
1067: socket=smtp.socket;
1068:
1069: lprintf("%04d SMTP RX Session thread started", socket);
1070:
1071: #ifdef _WIN32
1072: if(startup->inbound_sound[0] && !(startup->options&MAIL_OPT_MUTE))
1073: PlaySound(startup->inbound_sound, NULL, SND_ASYNC|SND_FILENAME);
1074: #endif
1075:
1076: addr_len=sizeof(server_addr);
1077: if((i=getsockname(socket, (struct sockaddr *)&server_addr,&addr_len))!=0) {
1078: lprintf("%04d !SMTP ERROR %d (%d) getting address/port"
1079: ,socket, i, ERROR_VALUE);
1080: return;
1081: }
1082:
1083: memset(&msg,0,sizeof(smbmsg_t));
1084:
1085: strcpy(host_ip,inet_ntoa(smtp.client_addr.sin_addr));
1086:
1087: lprintf("%04d SMTP connection accepted from: %s", socket, host_ip);
1088:
1089: if(startup->options&MAIL_OPT_NO_HOST_LOOKUP)
1090: host=NULL;
1091: else
1092: host=gethostbyaddr ((char *)&smtp.client_addr.sin_addr
1093: ,sizeof(smtp.client_addr.sin_addr),AF_INET);
1094:
1095: if(host!=NULL && host->h_name!=NULL)
1096: sprintf(host_name,"%.*s",(int)sizeof(host_name)-1,host->h_name);
1097: else
1098: strcpy(host_name,"<no name>");
1099:
1100: lprintf("%04d SMTP host name: %s", socket, host_name);
1101:
1102: strcpy(hello_name,host_name);
1103:
1104: if(trashcan(&scfg,host_ip,"ip")) {
1105: lprintf("%04d !SMTP server blocked in ip.can: %s"
1106: ,socket, host_ip);
1107: sockprintf(socket,"550 Access denied.");
1108: mail_close_socket(socket);
1109: thread_down();
1110: return;
1111: }
1112:
1113: if(trashcan(&scfg,host_name,"host")) {
1114: lprintf("%04d !SMTP server blocked in host.can: %s"
1115: ,socket, host_name);
1116: sockprintf(socket,"550 Access denied.");
1117: mail_close_socket(socket);
1118: thread_down();
1119: return;
1120: }
1121:
1122: /* SPAM Filters (maps.vix.com) */
1123: if(startup->options&MAIL_OPT_USE_RBL
1124: && rblchk(smtp.client_addr.sin_addr.s_addr
1125: ,"rbl.maps.vix.com"
1126: )==TRUE) {
1127: lprintf("%04d !SMTP SPAM server filtered (RBL): %s [%s]"
1128: ,socket, host_name,host_ip);
1129: sockprintf(socket
1130: ,"571 Mail from %s refused, see http://www.mail-abuse.org/rbl"
1131: ,host_ip);
1132: mail_close_socket(socket);
1133: thread_down();
1134: return;
1135: }
1136: if(startup->options&MAIL_OPT_USE_DUL
1137: && rblchk(smtp.client_addr.sin_addr.s_addr
1138: ,"dul.maps.vix.com"
1139: )==TRUE) {
1140: lprintf("%04d !SMTP SPAM server filtered (DUL): %s [%s]"
1141: ,socket, host_name,host_ip);
1142: sockprintf(socket
1143: ,"571 Mail from %s refused, see http://www.mail-abuse.org/dul"
1144: ,host_ip);
1145: mail_close_socket(socket);
1146: thread_down();
1147: return;
1148: }
1149: if(startup->options&MAIL_OPT_USE_RSS
1150: && rblchk(smtp.client_addr.sin_addr.s_addr
1151: ,"relays.mail-abuse.org"
1152: )==TRUE) {
1153: lprintf("%04d !SMTP SPAM server filtered (RSS): %s [%s]"
1154: ,socket, host_name,host_ip);
1155: sockprintf(socket
1156: ,"571 Mail from %s refused, see http://www.mail-abuse.org/rss"
1157: ,host_ip);
1158: mail_close_socket(socket);
1159: thread_down();
1160: return;
1161: }
1162:
1163: sprintf(rcptlst_fname,"%sSMTP%d.LST", scfg.data_dir, socket);
1164: rcptlst=fopen(rcptlst_fname,"w+");
1165: if(rcptlst==NULL) {
1166: lprintf("%04d !SMTP ERROR %d creating recipient list: %s"
1167: ,socket, errno, rcptlst_fname);
1168: sockprintf(socket,"421 System error");
1169: mail_close_socket(socket);
1170: thread_down();
1171: return;
1172: }
1173:
1174: if(trashcan(&scfg,host_name,"smtpspy")
1175: || trashcan(&scfg,host_ip,"smtpspy")) {
1176: sprintf(str,"%sSMTPSPY.TXT", scfg.data_dir);
1177: spy=fopen(str,"a");
1178: }
1179:
1180: active_clients++;
1181: update_clients();
1182:
1183: /* Initialize client display */
1184: client.size=sizeof(client);
1185: client.time=time(NULL);
1186: sprintf(client.addr,"%.*s",(int)sizeof(client.addr)-1,host_ip);
1187: sprintf(client.host,"%.*s",(int)sizeof(client.host)-1,host_name);
1188: client.port=ntohs(smtp.client_addr.sin_port);
1189: client.protocol="SMTP";
1190: client.user="<unknown>";
1191: client_on(socket,&client);
1192:
1193: sprintf(str,"SMTP: %s",host_ip);
1194: status(str);
1195:
1196: sockprintf(socket,"220 %s Synchronet SMTP Server for %s v%s Ready"
1197: ,scfg.sys_inetaddr,PLATFORM_DESC,MAIL_VERSION);
1198: while(1) {
1199: rd = sockreadline(socket, buf, sizeof(buf));
1200: if(rd<1)
1201: break;
1202: if(spy!=NULL)
1203: fprintf(spy,"%s\n",buf);
1204: if(state>=SMTP_STATE_DATA_HEADER) {
1205: if(!strcmp(buf,".")) {
1206: lprintf("%04d SMTP End of message (%lu bytes)", socket, ftell(msgtxt));
1207:
1208: if(sender[0]==0) {
1209: lprintf("%04d !SMTP Mail header missing 'FROM' field", socket);
1210: sockprintf(socket, "554 Mail header missing 'FROM' field");
1211: state=SMTP_STATE_HELO;
1212: continue;
1213: }
1214:
1215: if(msgtxt!=NULL) {
1216: rewind(msgtxt);
1217: sprintf(smb.file,"%smail", scfg.data_dir);
1218: smb.retry_time=scfg.smb_retry_time;
1219: if((i=smb_open(&smb))!=0) {
1220: lprintf("%04d !SMTP ERROR %d (%s) opening %s"
1221: ,socket, i, smb.last_error, smb.file);
1222: sockprintf(socket, "452 Insufficient system storage");
1223: continue;
1224: }
1225:
1226: if(smb_fgetlength(smb.shd_fp)<1) { /* Create it if it doesn't exist */
1227: smb.status.max_crcs=scfg.mail_maxcrcs;
1228: smb.status.max_age=scfg.mail_maxage;
1229: smb.status.max_msgs=MAX_SYSMAIL;
1230: smb.status.attr=SMB_EMAIL;
1231: if((i=smb_create(&smb))!=0) {
1232: smb_close(&smb);
1233: lprintf("%04d !SMTP ERROR %d creating %s"
1234: ,socket, i, smb.file);
1235: sockprintf(socket, "452 Insufficient system storage");
1236: continue;
1237: }
1238: }
1239:
1240: if((i=smb_locksmbhdr(&smb))!=0) {
1241: smb_close(&smb);
1242: lprintf("%04d !SMTP ERROR %d locking %s"
1243: ,socket, i, smb.file);
1244: sockprintf(socket, "452 Insufficient system storage");
1245: continue; }
1246:
1247: length=filelength(fileno(msgtxt))+2; /* +2 for translation string */
1248:
1249: if((i=smb_open_da(&smb))!=0) {
1250: smb_unlocksmbhdr(&smb);
1251: smb_close(&smb);
1252: lprintf("%04d !SMTP ERROR %d (%s) opening %s.sda"
1253: ,socket, i, smb.last_error, smb.file);
1254: sockprintf(socket, "452 Insufficient system storage");
1255: continue; }
1256:
1257: if(scfg.sys_misc&SM_FASTMAIL)
1258: offset=smb_fallocdat(&smb,length,1);
1259: else
1260: offset=smb_allocdat(&smb,length,1);
1261: smb_close_da(&smb);
1262:
1263: smb_fseek(smb.sdt_fp,offset,SEEK_SET);
1264: xlat=XLAT_NONE;
1265: smb_fwrite(&xlat,2,smb.sdt_fp);
1266: x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
1267: while(!feof(msgtxt)) {
1268: memset(buf,0,x);
1269: j=fread(buf,1,x,msgtxt);
1270: if(j<1)
1271: break;
1272: if((j!=x || feof(msgtxt)) && buf[j-1]=='\n' && buf[j-2]=='\r')
1273: buf[j-1]=buf[j-2]=0;
1274: if(scfg.mail_maxcrcs) {
1275: for(i=0;i<j;i++)
1276: crc=ucrc32(buf[i],crc);
1277: }
1278: smb_fwrite(buf,j,smb.sdt_fp);
1279: x=SDT_BLOCK_LEN;
1280: }
1281: smb_fflush(smb.sdt_fp);
1282: crc=~crc;
1283:
1284: if(scfg.mail_maxcrcs) {
1285: i=smb_addcrc(&smb,crc);
1286: if(i) {
1287: smb_freemsgdat(&smb,offset,length,1);
1288: smb_unlocksmbhdr(&smb);
1289: smb_close(&smb);
1290: lprintf("%04d !SMTP Duplicate message", socket);
1291: sockprintf(socket, "554 Duplicate Message");
1292: continue;
1293: }
1294: }
1295:
1296: msg.hdr.offset=offset;
1297:
1298: smb_dfield(&msg,TEXT_BODY,length);
1299:
1300: smb_unlocksmbhdr(&smb);
1301: if(msg.idx.subj==0) {
1302: p="";
1303: smb_hfield(&msg, SUBJECT, 0, p);
1304: msg.idx.subj=crc16(p);
1305: }
1306: rewind(rcptlst);
1307: while(!feof(rcptlst)) {
1308: if((i=smb_copymsgmem(&newmsg,&msg))!=0) {
1309: lprintf("%04d !SMTP ERROR %d copying message"
1310: ,socket, i);
1311: break;
1312: }
1313: if(fgets(str,sizeof(str)-1,rcptlst)==NULL)
1314: break;
1315: usernum=atoi(str);
1316: fgets(rcpt_name,sizeof(rcpt_name)-1,rcptlst);
1317: if(fgets(rcpt_addr,sizeof(rcpt_addr)-1,rcptlst)==NULL)
1318: break;
1319: truncsp(rcpt_name);
1320: truncsp(rcpt_addr);
1321:
1322: snprintf(hdrfield,sizeof(hdrfield),
1323: "Received: from %s (%s [%s])\r\n"
1324: " by %s [%s] (Synchronet Mail Server for %s v%s) with %s\r\n"
1325: " for %s; %s"
1326: ,host_name,hello_name,host_ip
1327: ,scfg.sys_inetaddr,inet_ntoa(server_addr.sin_addr)
1328: ,PLATFORM_DESC,MAIL_VERSION
1329: ,esmtp ? "ESMTP" : "SMTP"
1330: ,rcpt_addr,msgdate(msg.hdr.when_imported,date));
1331: smb_hfield(&newmsg, RFC822HEADER, (ushort)strlen(hdrfield), hdrfield);
1332:
1333: smb_hfield(&newmsg, RECIPIENT, (ushort)strlen(rcpt_name), rcpt_name);
1334:
1335: if(rcpt_addr[0]=='#') { /* Local destination */
1336: newmsg.idx.to=atoi(rcpt_addr+1);
1337: smb_hfield(&newmsg, RECIPIENTEXT
1338: ,(ushort)strlen(rcpt_addr+1), rcpt_addr+1);
1339: } else {
1340: newmsg.idx.to=0;
1341: nettype=NET_INTERNET;
1342: smb_hfield(&newmsg, RECIPIENTNETTYPE, nettype, &nettype);
1343: smb_hfield(&newmsg, RECIPIENTNETADDR
1344: ,(ushort)strlen(rcpt_addr), rcpt_addr);
1345: }
1346:
1347: i=smb_addmsghdr(&smb,&newmsg,SMB_SELFPACK);
1348: smb_freemsgmem(&newmsg);
1349: if(i!=0) {
1350: lprintf("%04d !SMTP ERROR %d adding message header"
1351: ,socket, i);
1352: break;
1353: }
1354: lprintf("%04d SMTP Created message #%ld from %s to %s <%s>"
1355: ,socket, newmsg.hdr.number, sender, rcpt_name, rcpt_addr);
1356: if(usernum) {
1357: sprintf(str,"\7\1n\1hOn %.24s\r\n\1m%s \1n\1msent you e-mail from: "
1358: "\1h%s\1n\r\n"
1359: ,ctime((const time_t*)&newmsg.hdr.when_imported.time)
1360: ,sender,sender_addr);
1361: if(!newmsg.idx.to) { /* Forwarding */
1362: strcat(str,"\1mand it was automatically forwaded to: \1h");
1363: strcat(str,user.netmail);
1364: strcat(str,"\1n\r\n");
1365: }
1366: putsmsg(&scfg, usernum, str);
1367: }
1368: }
1369: smb_close(&smb);
1370: if(i) {
1371: smb_freemsgdat(&smb,offset,length,1);
1372: sockprintf(socket, "452 Insufficient system storage");
1373: continue;
1374: }
1375: }
1376: sockprintf(socket,SMTP_OK);
1377: state=SMTP_STATE_HELO;
1378: continue;
1379: }
1380: if(buf[0]==0 && state==SMTP_STATE_DATA_HEADER) {
1381: state=SMTP_STATE_DATA_BODY; /* Null line separates header and body */
1382: continue;
1383: }
1384: if(state==SMTP_STATE_DATA_BODY) {
1385: p=buf;
1386: if(*p=='.') p++; /* Transparency (RFC821 4.5.2) */
1387: if(msgtxt!=NULL)
1388: fprintf(msgtxt, "%s\r\n", p);
1389: continue;
1390: }
1391: /* RFC822 Header parsing */
1392: if(startup->options&MAIL_OPT_DEBUG_RX_HEADER)
1393: lprintf("%04d SMTP %s",socket, buf);
1394:
1395: if(!strnicmp(buf, "SUBJECT:",8)) {
1396: p=buf+8;
1397: while(*p && *p<=' ') p++;
1398: smb_hfield(&msg, SUBJECT, (ushort)strlen(p), p);
1399: strlwr(p);
1400: msg.idx.subj=crc16(p);
1401: continue;
1402: }
1403: if(!strnicmp(buf, "TO:",3)) {
1404: p=buf+3;
1405: while(*p && *p<=' ') p++;
1406: if(*p=='<') {
1407: p++;
1408: tp=strrchr(p,'>');
1409: if(tp) *tp=0;
1410: }
1411: #if 0
1412: if(!nettype) {
1413: nettype=NET_INTERNET;
1414: smb_hfield(&msg, RECIPIENTNETTYPE, nettype, &nettype);
1415: smb_hfield(&msg, RECIPIENTNETADDR, (ushort)strlen(p), p);
1416: }
1417: #endif
1418: continue;
1419: }
1420: if(!strnicmp(buf, "REPLY-TO:",9)) {
1421: p=buf+9;
1422: while(*p && *p<=' ') p++;
1423: if(*p=='<') {
1424: p++;
1425: tp=strchr(p,'>');
1426: if(tp) *tp=0;
1427: }
1428: nettype=NET_INTERNET;
1429: smb_hfield(&msg, REPLYTONETTYPE, nettype, &nettype);
1430: smb_hfield(&msg, REPLYTONETADDR, (ushort)strlen(p), p);
1431: continue;
1432: }
1433: if(!strnicmp(buf, "FROM:",5)) {
1434: p=strchr(buf+5,'<');
1435: if(p) {
1436: p++;
1437: tp=strchr(p,'>');
1438: if(tp) *tp=0;
1439: sprintf(sender_addr,"%.*s",(int)sizeof(sender_addr)-1,p);
1440: } else {
1441: p=buf+5;
1442: while(*p && *p<=' ') p++;
1443: sprintf(sender_addr,"%.*s",(int)sizeof(sender_addr)-1,p);
1444: }
1445: nettype=NET_INTERNET;
1446: smb_hfield(&msg, SENDERNETTYPE, sizeof(nettype), &nettype);
1447: smb_hfield(&msg, SENDERNETADDR, (ushort)strlen(sender_addr), sender_addr);
1448:
1449: p=buf+5;
1450: while(*p && *p<=' ') p++;
1451: if(*p=='"') {
1452: p++;
1453: tp=strchr(p,'"');
1454: } else if(*p=='<') {
1455: p++;
1456: tp=strchr(p,'>');
1457: } else
1458: tp=strchr(p,'<');
1459: if(tp) *tp=0;
1460: truncsp(p);
1461: sprintf(sender,"%.*s",(int)sizeof(sender)-1,p);
1462: smb_hfield(&msg, SENDER, (ushort)strlen(sender), sender);
1463: continue;
1464: }
1465: if(!strnicmp(buf, "DATE:",5)) {
1466: p=buf+5;
1467: while(*p && *p<=' ') p++;
1468: /* lprintf("Sent: %s",p); */
1469: memset(&tm,0,sizeof(tm));
1470: while(*p && !isdigit(*p)) p++;
1471: /* DAY */
1472: tm.tm_mday=atoi(p);
1473: while(*p && isdigit(*p)) p++;
1474: /* MONTH */
1475: while(*p && *p<=' ') p++;
1476: sprintf(month,"%3.3s",p);
1477: if(!stricmp(month,"jan"))
1478: tm.tm_mon=0;
1479: else if(!stricmp(month,"feb"))
1480: tm.tm_mon=1;
1481: else if(!stricmp(month,"mar"))
1482: tm.tm_mon=2;
1483: else if(!stricmp(month,"apr"))
1484: tm.tm_mon=3;
1485: else if(!stricmp(month,"may"))
1486: tm.tm_mon=4;
1487: else if(!stricmp(month,"jun"))
1488: tm.tm_mon=5;
1489: else if(!stricmp(month,"jul"))
1490: tm.tm_mon=6;
1491: else if(!stricmp(month,"aug"))
1492: tm.tm_mon=7;
1493: else if(!stricmp(month,"sep"))
1494: tm.tm_mon=8;
1495: else if(!stricmp(month,"oct"))
1496: tm.tm_mon=9;
1497: else if(!stricmp(month,"nov"))
1498: tm.tm_mon=10;
1499: else
1500: tm.tm_mon=11;
1501: p+=4;
1502: /* YEAR */
1503: tm.tm_year=atoi(p);
1504: if(tm.tm_year>1900)
1505: tm.tm_year-=1900;
1506: while(*p && isdigit(*p)) p++;
1507: /* HOUR */
1508: while(*p && *p<=' ') p++;
1509: tm.tm_hour=atoi(p);
1510: while(*p && isdigit(*p)) p++;
1511: /* MINUTE */
1512: if(*p) p++;
1513: tm.tm_min=atoi(p);
1514: while(*p && isdigit(*p)) p++;
1515: /* SECONDS */
1516: if(*p) p++;
1517: tm.tm_sec=atoi(p);
1518: while(*p && isdigit(*p)) p++;
1519: /* TIME ZONE */
1520: while(*p && *p<=' ') p++;
1521: if(*p && (isdigit(*p) || *p=='-')) { /* HHMM or -HHMM format */
1522: sprintf(str,"%.*s",*p=='-'? 3:2,p);
1523: msg.hdr.when_written.zone=atoi(str)*60;
1524: p+=(*p=='-') ? 3:2;
1525: msg.hdr.when_written.zone+=atoi(p);
1526: }
1527: else if(!strnicmp(p,"PDT",3))
1528: msg.hdr.when_written.zone=(short)PDT;
1529: else if(!strnicmp(p,"MDT",3))
1530: msg.hdr.when_written.zone=(short)MDT;
1531: else if(!strnicmp(p,"CDT",3))
1532: msg.hdr.when_written.zone=(short)CDT;
1533: else if(!strnicmp(p,"EDT",3))
1534: msg.hdr.when_written.zone=(short)EDT;
1535: else if(!strnicmp(p,"PST",3))
1536: msg.hdr.when_written.zone=(short)PST;
1537: else if(!strnicmp(p,"MST",3))
1538: msg.hdr.when_written.zone=(short)MST;
1539: else if(!strnicmp(p,"CST",3))
1540: msg.hdr.when_written.zone=(short)CST;
1541: else if(!strnicmp(p,"EST",3))
1542: msg.hdr.when_written.zone=(short)EST;
1543: msg.hdr.when_written.time=mktime(&tm);
1544: continue;
1545: }
1546: if(!strnicmp(buf, "MESSAGE-ID:",11)) {
1547: p=buf+11;
1548: while(*p && *p<=' ') p++;
1549: smb_hfield(&msg, RFC822MSGID, (ushort)strlen(p), p);
1550: continue;
1551: }
1552: if(!strnicmp(buf, "IN-REPLY-TO:",12)) {
1553: p=buf+12;
1554: while(*p && *p<=' ') p++;
1555: smb_hfield(&msg, RFC822REPLYID, (ushort)strlen(p), p);
1556: continue;
1557: }
1558: /* Fall-through */
1559: smb_hfield(&msg, RFC822HEADER, (ushort)strlen(buf), buf);
1560: continue;
1561: }
1562: lprintf("%04d SMTP RX: %s", socket, buf);
1563: if(!strnicmp(buf,"HELO",4)) {
1564: p=buf+4;
1565: while(*p && *p<=' ') p++;
1566: sprintf(hello_name,"%.*s",(int)sizeof(hello_name)-1,p);
1567: sockprintf(socket,"250 %s",scfg.sys_inetaddr);
1568: esmtp=FALSE;
1569: state=SMTP_STATE_HELO;
1570: continue;
1571: }
1572: if(!strnicmp(buf,"EHLO",4)) {
1573: p=buf+4;
1574: while(*p && *p<=' ') p++;
1575: sprintf(hello_name,"%.*s",(int)sizeof(hello_name)-1,p);
1576: sockprintf(socket,"250 %s",scfg.sys_inetaddr);
1577: esmtp=TRUE;
1578: state=SMTP_STATE_HELO;
1579: continue;
1580: }
1581: if(!stricmp(buf,"QUIT")) {
1582: sockprintf(socket,"221 %s Service closing transmission channel",scfg.sys_inetaddr);
1583: break;
1584: }
1585: if(!stricmp(buf,"NOOP")) {
1586: sockprintf(socket, SMTP_OK);
1587: continue;
1588: }
1589: if(state<SMTP_STATE_HELO) {
1590: /* RFC 821 4.1.1 "The first command in a session must be the HELO command." */
1591: lprintf("%04d !SMTP Missing HELO command",socket);
1592: sockprintf(socket, SMTP_BADSEQ);
1593: continue;
1594: }
1595: if(!stricmp(buf,"TURN")) {
1596: sockprintf(socket,"502 command not supported");
1597: continue;
1598: }
1599: if(!stricmp(buf,"RSET")) {
1600: smb_freemsgmem(&msg);
1601: memset(&msg,0,sizeof(smbmsg_t)); /* Initialize message header */
1602: reverse_path[0]=0;
1603: sender[0]=0;
1604: sender_addr[0]=0;
1605: sockprintf(socket,SMTP_OK);
1606: rewind(rcptlst);
1607: chsize(fileno(rcptlst),0);
1608: state=SMTP_STATE_HELO;
1609: continue;
1610: }
1611: if(!strnicmp(buf,"MAIL FROM:",10)) {
1612: smb_freemsgmem(&msg);
1613: memset(&msg,0,sizeof(smbmsg_t)); /* Initialize message header */
1614: memcpy(msg.hdr.id,"SHD\x1a",4);
1615: msg.hdr.version=smb_ver();
1616: msg.hdr.when_imported.time=time(NULL);
1617: msg.hdr.when_imported.zone=scfg.sys_timezone;
1618: p=buf+10;
1619: while(*p && *p<=' ') p++;
1620: sprintf(reverse_path,"%.*s",(int)sizeof(reverse_path)-1,p);
1621: sender[0]=0;
1622: sender_addr[0]=0;
1623: if(spy==NULL && trashcan(&scfg,reverse_path,"smtpspy")) {
1624: sprintf(str,"%sSMTPSPY.TXT", scfg.data_dir);
1625: spy=fopen(str,"a");
1626: }
1627: sockprintf(socket,SMTP_OK);
1628: state=SMTP_STATE_MAIL_FROM;
1629: continue;
1630: }
1631: #if 0 /* No one uses this command */
1632: if(!strnicmp(buf,"VRFY",4)) {
1633: p=buf+4;
1634: while(*p && *p<=' ') p++;
1635: if(*p==0) {
1636: sockprintf(socket,"550 No user specified.");
1637: continue;
1638: }
1639: #endif
1640:
1641:
1642:
1643: if(!strnicmp(buf,"RCPT TO:",8)) {
1644:
1645: if(state<SMTP_STATE_MAIL_FROM) {
1646: lprintf("%04d !SMTP Missing 'MAIL' command",socket);
1647: sockprintf(socket, SMTP_BADSEQ);
1648: continue;
1649: }
1650:
1651: sprintf(str,"%.*s",(int)sizeof(str)-1,buf+8);
1652: p=str;
1653: while(*p && *p<=' ') p++;
1654:
1655: if(*p=='<') p++; /* Skip '<' */
1656: tp=strchr(str,'>'); /* Truncate '>' */
1657: if(tp!=NULL) *tp=0;
1658:
1659: tp=strrchr(str,'@');
1660: if(tp!=NULL) {
1661:
1662: /* RELAY */
1663: if(stricmp(tp+1,scfg.sys_inetaddr) &&
1664: resolve_ip(tp+1)!=server_addr.sin_addr.s_addr) {
1665:
1666: if(!trashcan(&scfg,host_name,"relay") &&
1667: !trashcan(&scfg,host_ip,"relay")) {
1668: lprintf("%04d !SMTP ILLEGAL RELAY ATTEMPT from %s [%s] to %s"
1669: ,socket, host_name, host_ip, tp+1);
1670: sockprintf(socket, "550 Relay not allowed.");
1671: continue;
1672: }
1673:
1674: lprintf("%04d SMTP Relaying to external mail service: %s"
1675: ,socket, tp+1);
1676:
1677: fprintf(rcptlst,"0\n%.*s\n%.*s\n"
1678: ,(int)sizeof(rcpt_name)-1,p
1679: ,(int)sizeof(rcpt_addr)-1,p);
1680:
1681: sockprintf(socket,SMTP_OK);
1682: state=SMTP_STATE_RCPT_TO;
1683: continue;
1684: }
1685: *tp=0; /* truncate at '@' */
1686: }
1687: while(*p && !isalnum(*p)) p++; /* Skip '<' or '"' */
1688: tp=strrchr(p,'"');
1689: if(tp!=NULL) *tp=0; /* truncate at '"' */
1690:
1691: p=alias(p,alias_buf);
1692:
1693: /* RX by sysop alias */
1694: if(!stricmp(p,"SYSOP") || !stricmp(p,scfg.sys_id)
1695: || !stricmp(p,"POSTMASTER") || !stricmp(p,scfg.sys_op))
1696: usernum=1;
1697: else if(startup->options&MAIL_OPT_ALLOW_RX_BY_NUMBER
1698: && isdigit(*p)) {
1699: usernum=atoi(p); /* RX by user number */
1700: /* verify usernum */
1701: username(&scfg,usernum,str);
1702: if(!str[0] || !stricmp(str,"DELETED USER"))
1703: usernum=0;
1704: p=str;
1705: } else {
1706: usernum=matchuser(&scfg,p); /* RX by "user alias", "user.alias" or "user_alias" */
1707:
1708: if(!usernum) { /* RX by "real name", "real.name", or "sysop.alias" */
1709:
1710: /* convert "user.name" to "user name" */
1711: sprintf(rcpt_name,"%.*s",sizeof(rcpt_name)-1,p);
1712: for(tp=rcpt_name;*tp;tp++)
1713: if(*tp=='.') *tp=' ';
1714:
1715: if(!stricmp(rcpt_name,scfg.sys_op))
1716: usernum=1; /* RX by "sysop.alias" */
1717:
1718: if(!usernum) /* RX by "real name" */
1719: usernum=userdatdupe(&scfg, 0, U_NAME, LEN_NAME, p, FALSE);
1720:
1721: if(!usernum) /* RX by "real.name" */
1722: usernum=userdatdupe(&scfg, 0, U_NAME, LEN_NAME, rcpt_name, FALSE);
1723: }
1724: }
1725: if(!usernum) {
1726: lprintf("%04d !SMTP UNKNOWN USER: %s", socket, buf+8);
1727: sockprintf(socket, "550 Unknown User: %s", buf+8);
1728: continue;
1729: }
1730: user.number=usernum;
1731: if((i=getuserdat(&scfg, &user))!=0) {
1732: lprintf("%04d !SMTP ERROR %d getting data on user #%u (%s)"
1733: ,socket, i, usernum, p);
1734: sockprintf(socket, "550 Unknown User: %s", buf+8);
1735: continue;
1736: }
1737: if(user.misc&(DELETED|INACTIVE)) {
1738: lprintf("%04d !SMTP DELETED or INACTIVE user #%u (%s)"
1739: ,socket, usernum, p);
1740: sockprintf(socket, "550 Unknown User: %s", buf+8);
1741: continue;
1742: }
1743: #if 0 /* implement later */
1744: if(useron.etoday>=cfg.level_emailperday[useron.level]
1745: && !(useron.rest&FLAG('Q'))) {
1746: bputs(text[TooManyEmailsToday]);
1747: continue; }
1748: #endif
1749:
1750: fprintf(rcptlst,"%u\n%.*s\n",user.number,(int)sizeof(rcpt_name)-1,p);
1751:
1752: /* Forward to Internet */
1753: tp=strrchr(user.netmail,'@');
1754: if(scfg.sys_misc&SM_FWDTONET && user.misc&NETMAIL
1755: && tp && strchr(tp,'.') && !strchr(tp,'/')
1756: && !strstr(tp,scfg.sys_inetaddr)) {
1757: lprintf("%04d SMTP Forwarding to: %s"
1758: ,socket, user.netmail);
1759: fprintf(rcptlst,"%s\n",user.netmail);
1760: sockprintf(socket,"251 User not local; will forward to %s", user.netmail);
1761: } else { /* Local (no-forward) */
1762: fprintf(rcptlst,"#%u\n",usernum);
1763: sockprintf(socket,SMTP_OK);
1764: }
1765: state=SMTP_STATE_RCPT_TO;
1766: continue;
1767: }
1768: if(!strnicmp(buf,"DATA",4)) {
1769: if(state<SMTP_STATE_RCPT_TO) {
1770: lprintf("%04d !SMTP Missing 'RCPT TO' command", socket);
1771: sockprintf(socket, SMTP_BADSEQ);
1772: continue;
1773: }
1774: if(msgtxt!=NULL)
1775: fclose(msgtxt);
1776: sprintf(msgtxt_fname,"%sSMTP%d.RX", scfg.data_dir, socket);
1777: if((msgtxt=fopen(msgtxt_fname,"w+b"))==NULL) {
1778: lprintf("%04d !SMTP Error %d opening %s"
1779: ,socket, errno, msgtxt_fname);
1780: sockprintf(socket, "452 Insufficient system storage");
1781: continue;
1782: }
1783: sockprintf(socket, "354 send the mail data, end with <CRLF>.<CRLF>");
1784: state=SMTP_STATE_DATA_HEADER;
1785: continue;
1786: }
1787: sockprintf(socket,"500 Syntax error");
1788: lprintf("%04d !SMTP UNSUPPORTED COMMAND: %s", socket, buf);
1789: }
1790:
1791: /* Free up resources here */
1792: mail_close_socket(socket);
1793:
1794: smb_freemsgmem(&msg);
1795:
1796: if(msgtxt!=NULL) {
1797: fclose(msgtxt);
1798: if(!(startup->options&MAIL_OPT_DEBUG_RX_BODY))
1799: unlink(msgtxt_fname);
1800: }
1801: if(rcptlst!=NULL) {
1802: fclose(rcptlst);
1803: unlink(rcptlst_fname);
1804: }
1805: if(spy!=NULL)
1806: fclose(spy);
1807:
1808: status(STATUS_WFC);
1809:
1810: lprintf("%04d SMTP RX Session thread terminated", socket);
1811: active_clients--;
1812: update_clients();
1813: client_off(socket);
1814:
1815: thread_down();
1816: }
1817:
1818: BOOL bounce(smb_t* smb, smbmsg_t* msg, char* err, BOOL immediate)
1819: {
1820: char str[128],full_err[512];
1821: int i;
1822: ushort agent=AGENT_PROCESS;
1823: smbmsg_t newmsg;
1824:
1825: if((i=smb_lockmsghdr(smb,msg))!=0) {
1826: lprintf("0000 !BOUNCE ERROR %d locking message header #%lu"
1827: ,i,msg->hdr.number);
1828: return(FALSE);
1829: }
1830:
1831: msg->hdr.delivery_attempts++;
1832: if((i=smb_putmsg(smb,msg))!=0) {
1833: lprintf("0000 !BOUNCE ERROR %d incrementing delivery attempt counter",i);
1834: smb_unlockmsghdr(smb,msg);
1835: return(FALSE);
1836: }
1837:
1838: lprintf("0000 !Delivery attempt #%u FAILED for message #%lu from %s to %s"
1839: ,msg->hdr.delivery_attempts, msg->hdr.number
1840: ,msg->from, msg->to_net.addr);
1841:
1842: if(!immediate && msg->hdr.delivery_attempts<startup->max_delivery_attempts) {
1843: smb_unlockmsghdr(smb,msg);
1844: return(TRUE);
1845: }
1846:
1847: lprintf("0000 !Bouncing message back to %s", msg->from);
1848:
1849: newmsg=*msg;
1850: /* Mark original message as deleted */
1851: msg->hdr.attr|=MSG_DELETE;
1852: msg->idx.attr=msg->hdr.attr;
1853: if((i=smb_putmsg(smb,msg))!=0) {
1854: lprintf("0000 !BOUNCE ERROR %d deleting message",i);
1855: smb_unlockmsghdr(smb,msg);
1856: return(FALSE);
1857: }
1858: smb_unlockmsghdr(smb,msg);
1859:
1860: newmsg.hfield=NULL;
1861: newmsg.hfield_dat=NULL;
1862: newmsg.total_hfields=0;
1863: newmsg.idx.to=newmsg.idx.from;
1864: newmsg.idx.from=0;
1865: newmsg.hdr.delivery_attempts=0;
1866:
1867: smb_hfield(&newmsg, RECIPIENT, (ushort)strlen(newmsg.from), newmsg.from);
1868: if(newmsg.idx.to) {
1869: sprintf(str,"%u",newmsg.idx.to);
1870: smb_hfield(&newmsg, RECIPIENTEXT, (ushort)strlen(str), str);
1871: }
1872: smb_hfield(&newmsg, RECIPIENTAGENT, sizeof(ushort), &newmsg.from_agent);
1873: smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(newmsg.from_net.type), &newmsg.from_net.type);
1874: if(newmsg.from_net.type)
1875: smb_hfield(&newmsg, RECIPIENTNETADDR, (ushort)strlen(newmsg.from_net.addr)
1876: ,newmsg.from_net.addr);
1877: strcpy(str,"Mail Delivery Subsystem");
1878: smb_hfield(&newmsg, SENDER, (ushort)strlen(str), str);
1879: smb_hfield(&newmsg, SENDERAGENT, sizeof(agent), &agent);
1880:
1881: /* Put error message in subject for now */
1882: sprintf(full_err,"Delivery failure of message to %s after %u attempts: %s"
1883: ,(char*)msg->to_net.addr, msg->hdr.delivery_attempts, err);
1884: smb_hfield(&newmsg, SUBJECT, (ushort)strlen(full_err), full_err);
1885:
1886: if((i=smb_addmsghdr(smb,&newmsg,SMB_SELFPACK))!=0)
1887: lprintf("0000 !BOUNCE ERROR %d adding message header",i);
1888:
1889: newmsg.dfield=NULL; /* Don't double-free the data fields */
1890: newmsg.hdr.total_dfields=0;
1891: smb_freemsgmem(&newmsg);
1892:
1893: return(TRUE);
1894: }
1895:
1896: #ifdef __BORLANDC__
1897: #pragma argsused
1898: #endif
1899: static void sendmail_thread(void* arg)
1900: {
1901: int i,j;
1902: char to[128];
1903: char mx[128];
1904: char mx2[128];
1905: char err[128];
1906: char buf[512];
1907: char fromaddr[256];
1908: char* server;
1909: char* msgtxt=NULL;
1910: char* p;
1911: ulong offset;
1912: ulong last_msg=0;
1913: ulong total_msgs;
1914: ulong ip_addr;
1915: ulong dns;
1916: BOOL success;
1917: SOCKET sock=INVALID_SOCKET;
1918: SOCKADDR_IN addr;
1919: SOCKADDR_IN server_addr;
1920: time_t last_scan=0;
1921: smb_t smb;
1922: smbmsg_t msg;
1923:
1924: sendmail_running=TRUE;
1925:
1926: thread_up();
1927:
1928: lprintf("0000 SendMail thread started");
1929:
1930: memset(&msg,0,sizeof(msg));
1931: memset(&smb,0,sizeof(smb));
1932:
1933: while(server_socket!=INVALID_SOCKET) {
1934:
1935: if(startup->options&MAIL_OPT_NO_SENDMAIL) {
1936: mswait(1000);
1937: continue;
1938: }
1939:
1940: if(active_sendmail!=0) {
1941: active_sendmail=0;
1942: update_clients();
1943: }
1944:
1945: smb_close(&smb);
1946:
1947: if(sock!=INVALID_SOCKET) {
1948: mail_close_socket(sock);
1949: sock=INVALID_SOCKET;
1950: }
1951:
1952: if(msgtxt!=NULL) {
1953: smb_freemsgtxt(msgtxt);
1954: msgtxt=NULL;
1955: }
1956:
1957: smb_freemsgmem(&msg);
1958:
1959: mswait(3000);
1960:
1961: sprintf(smb.file,"%smail",scfg.data_dir);
1962: if((i=smb_open(&smb))!=0)
1963: continue;
1964: if((i=smb_locksmbhdr(&smb))!=0)
1965: continue;
1966: if((i=smb_getstatus(&smb))!=0) {
1967: smb_unlocksmbhdr(&smb);
1968: continue;
1969: }
1970: smb_unlocksmbhdr(&smb);
1971: if(smb.status.last_msg==last_msg && time(NULL)-last_scan<startup->rescan_frequency)
1972: continue;
1973: last_msg=smb.status.last_msg;
1974: last_scan=time(NULL);
1975: total_msgs=smb.status.total_msgs;
1976: smb_rewind(smb.sid_fp);
1977: for(offset=0;offset<total_msgs;offset++) {
1978:
1979: if(active_sendmail!=0) {
1980: active_sendmail=0;
1981: update_clients();
1982: }
1983:
1984: if(sock!=INVALID_SOCKET) {
1985: mail_close_socket(sock);
1986: sock=INVALID_SOCKET;
1987: }
1988:
1989: if(msgtxt!=NULL) {
1990: smb_freemsgtxt(msgtxt);
1991: msgtxt=NULL;
1992: }
1993:
1994: smb_freemsgmem(&msg);
1995:
1996: smb_fseek(smb.sid_fp, offset*sizeof(msg.idx), SEEK_SET);
1997: if(smb_fread(&msg.idx, sizeof(msg.idx), smb.sid_fp) != sizeof(msg.idx))
1998: break;
1999: if(msg.idx.attr&MSG_DELETE) /* Marked for deletion */
2000: continue;
2001: if(msg.idx.to) /* Local */
2002: continue;
2003: msg.offset=offset;
2004:
2005: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
2006: lprintf("0000 !SEND ERROR %d locking message header #%lu"
2007: ,i,msg.idx.number);
2008: continue;
2009: }
2010: if((i=smb_getmsghdr(&smb,&msg))!=0) {
2011: smb_unlockmsghdr(&smb,&msg);
2012: lprintf("0000 !SEND ERROR %d reading message header #%lu"
2013: ,i,msg.idx.number);
2014: continue;
2015: }
2016: smb_unlockmsghdr(&smb,&msg);
2017:
2018: if(msg.to_net.type!=NET_INTERNET)
2019: continue;
2020:
2021: active_sendmail=1;
2022: update_clients();
2023:
2024: lprintf("0000 SEND Message #%lu from %s to %s"
2025: ,msg.hdr.number, msg.from, msg.to_net.addr);
2026: status("SendMail");
2027: #ifdef _WIN32
2028: if(startup->outbound_sound[0] && !(startup->options&MAIL_OPT_MUTE))
2029: PlaySound(startup->outbound_sound, NULL, SND_ASYNC|SND_FILENAME);
2030: #endif
2031:
2032: lprintf("0000 SEND getting message text");
2033: if((msgtxt=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))==NULL) {
2034: lprintf("0000 !SEND ERROR retrieving message text");
2035: continue;
2036: }
2037:
2038: if(startup->options&MAIL_OPT_RELAY_TX)
2039: server=startup->relay_server;
2040: else {
2041: sprintf(to,"%.*s",(int)sizeof(to)-1,(char*)msg.to_net.addr);
2042: p=strrchr(to,'>'); /* Truncate '>' */
2043: if(p!=NULL) *p=0;
2044:
2045: p=strrchr(to,'@');
2046: if(p==NULL) {
2047: lprintf("0000 !SEND INVALID destination address: %s", to);
2048: sprintf(err,"Invalid destination address: %s", to);
2049: bounce(&smb,&msg,err,TRUE);
2050: continue;
2051: }
2052: if((dns=resolve_ip(startup->dns_server))==0)
2053: continue;
2054: p++;
2055: lprintf("0000 SEND getting MX records for %s from %s",p,startup->dns_server);
2056: if((i=dns_getmx(p, mx, mx2, startup->interface_addr, dns
2057: ,startup->options&MAIL_OPT_USE_TCP_DNS ? TRUE : FALSE))!=0) {
2058: lprintf("0000 !SEND ERROR %d obtaining MX records for %s from %s"
2059: ,i,p,startup->dns_server);
2060: sprintf(err,"Error %d obtaining MX record for %s",i,p);
2061: bounce(&smb,&msg,err,FALSE);
2062: continue;
2063: }
2064: server=mx;
2065: }
2066:
2067:
2068: lprintf("0000 SEND opening socket");
2069: if((sock=mail_open_socket(SOCK_STREAM))==INVALID_SOCKET) {
2070: lprintf("0000 !SEND ERROR %d opening socket", ERROR_VALUE);
2071: continue;
2072: }
2073:
2074: lprintf("%04d SEND socket opened",sock);
2075:
2076: memset(&addr,0,sizeof(addr));
2077: addr.sin_addr.s_addr = htonl(startup->interface_addr);
2078: addr.sin_family = AF_INET;
2079:
2080: lprintf("%04d SEND binding socket",sock);
2081: if((i=bind(sock, (struct sockaddr *) &addr, sizeof (addr)))!=0) {
2082: lprintf("%04d !SEND ERROR %d (%d) binding socket", sock, i, ERROR_VALUE);
2083: continue;
2084: }
2085:
2086: strcpy(err,"UNKNOWN ERROR");
2087: success=FALSE;
2088: for(j=0;j<2 && !success;j++) {
2089: if(j) {
2090: if(startup->options&MAIL_OPT_RELAY_TX || !mx2[0])
2091: break;
2092: server=mx2; /* Give second mx record a try */
2093: }
2094:
2095: lprintf("%04d SEND resolving SMTP host name: %s", sock, server);
2096: ip_addr=resolve_ip(server);
2097: if(!ip_addr) {
2098: sprintf(err,"Failed to resolve SMTP host name: %s",server);
2099: continue;
2100: }
2101:
2102: memset(&server_addr,0,sizeof(server_addr));
2103: server_addr.sin_addr.s_addr = ip_addr;
2104: server_addr.sin_family = AF_INET;
2105: if(startup->options&MAIL_OPT_RELAY_TX)
2106: server_addr.sin_port = htons(startup->relay_port);
2107: else
2108: server_addr.sin_port = htons(IPPORT_SMTP);
2109:
2110: lprintf("%04d SEND connecting to port %u on %s [%s]"
2111: ,sock
2112: ,ntohs(server_addr.sin_port)
2113: ,server,inet_ntoa(server_addr.sin_addr));
2114: if((i=connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)))!=0) {
2115: lprintf("%04d !SEND ERROR %d (%d) connecting to SMTP server: %s"
2116: ,sock
2117: ,i,ERROR_VALUE, server);
2118: sprintf(err,"Error %d connecting to SMTP server: %s"
2119: ,(int)ERROR_VALUE,server);
2120: continue;
2121: }
2122: success=TRUE;
2123: }
2124: if(!success) { /* Failed to send, so bounce */
2125: bounce(&smb,&msg,err,FALSE);
2126: continue;
2127: }
2128:
2129: lprintf("%04d SEND connected to %s",sock,server);
2130:
2131: /* HELO */
2132: if(!sockgetrsp(sock,"220",buf,sizeof(buf))) {
2133: sprintf(err,"%s replied with '%s' instead of 220",server,buf);
2134: bounce(&smb,&msg,err,buf[0]=='5');
2135: continue;
2136: }
2137: sockprintf(sock,"HELO %s",scfg.sys_inetaddr);
2138: if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
2139: sprintf(err,"%s replied with '%s' instead of 250",server,buf);
2140: bounce(&smb,&msg,err,buf[0]=='5');
2141: continue;
2142: }
2143: /* MAIL */
2144: if(msg.from_net.type==NET_INTERNET)
2145: strcpy(fromaddr,msg.from_net.addr);
2146: else
2147: usermailaddr(fromaddr,msg.from);
2148: if(fromaddr[0]=='<')
2149: sockprintf(sock,"MAIL FROM: %s",fromaddr);
2150: else
2151: sockprintf(sock,"MAIL FROM: <%s>",fromaddr);
2152: if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
2153: sprintf(err,"%s replied with '%s' instead of 250",server,buf);
2154: bounce(&smb,&msg,err,buf[0]=='5');
2155: continue;
2156: }
2157: /* RCPT */
2158: if(*((char*)msg.to_net.addr)=='<')
2159: sockprintf(sock,"RCPT TO: %s", (char*)msg.to_net.addr);
2160: else
2161: sockprintf(sock,"RCPT TO: <%s>", (char*)msg.to_net.addr);
2162: if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
2163: sprintf(err,"%s replied with '%s' instead of 250",server,buf);
2164: bounce(&smb,&msg,err,buf[0]=='5');
2165: continue;
2166: }
2167: /* DATA */
2168: sockprintf(sock,"DATA");
2169: if(!sockgetrsp(sock,"354", buf, sizeof(buf))) {
2170: sprintf(err,"%s replied with '%s' instead of 354",server,buf);
2171: bounce(&smb,&msg,err,buf[0]=='5');
2172: continue;
2173: }
2174: lprintf("%04d SEND sending message text (%u bytes)"
2175: ,sock, strlen(msgtxt));
2176: sockmsgtxt(sock,&msg,msgtxt,fromaddr,-1);
2177: if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
2178: sprintf(err,"%s replied with '%s' instead of 250",server,buf);
2179: bounce(&smb,&msg,err,buf[0]=='5');
2180: continue;
2181: }
2182: lprintf("%04d SEND message transfer complete", sock);
2183:
2184: msg.hdr.attr|=MSG_DELETE;
2185: msg.idx.attr=msg.hdr.attr;
2186: if((i=smb_lockmsghdr(&smb,&msg))!=0)
2187: lprintf("%04d !SEND ERROR %d locking message header #%lu"
2188: ,sock
2189: ,i,msg.hdr.number);
2190: if((i=smb_putmsg(&smb,&msg))!=0)
2191: lprintf("%04d !SEND ERROR %d deleting message #%lu"
2192: ,sock
2193: ,i,msg.hdr.number);
2194: smb_unlockmsghdr(&smb,&msg);
2195:
2196: /* QUIT */
2197: sockprintf(sock,"QUIT");
2198: sockgetrsp(sock,"221", buf, sizeof(buf));
2199: mail_close_socket(sock);
2200: sock=INVALID_SOCKET;
2201: }
2202: status(STATUS_WFC);
2203: }
2204: if(sock!=INVALID_SOCKET)
2205: mail_close_socket(sock);
2206:
2207: smb_freemsgtxt(msgtxt);
2208: smb_freemsgmem(&msg);
2209: smb_close(&smb);
2210:
2211: lprintf("0000 SendMail thread terminated");
2212:
2213: sendmail_running=FALSE;
2214:
2215: thread_down();
2216: }
2217:
2218: void DLLCALL mail_terminate(void)
2219: {
2220: if(server_socket!=INVALID_SOCKET) {
2221: lprintf("%04d MAIL Terminate: closing socket",server_socket);
2222: mail_close_socket(server_socket);
2223: server_socket=INVALID_SOCKET;
2224: }
2225: }
2226:
2227: static void cleanup(int code)
2228: {
2229: if(server_socket!=INVALID_SOCKET) {
2230: mail_close_socket(server_socket);
2231: server_socket=INVALID_SOCKET;
2232: }
2233:
2234: if(pop3_socket!=INVALID_SOCKET) {
2235: mail_close_socket(pop3_socket);
2236: pop3_socket=INVALID_SOCKET;
2237: }
2238:
2239: update_clients();
2240:
2241: #ifdef _WINSOCKAPI_
2242: if(WSAInitialized && WSACleanup()!=0)
2243: lprintf("0000 !WSACleanup ERROR %d",ERROR_VALUE);
2244: #endif
2245:
2246: lprintf("#### Mail Server thread terminated");
2247: status("Down");
2248: if(startup!=NULL && startup->terminated!=NULL)
2249: startup->terminated(code);
2250: thread_down();
2251: }
2252:
2253: char* DLLCALL mail_ver(void)
2254: {
2255: static char ver[256];
2256: char compiler[32];
2257:
2258: COMPILER_DESC(compiler);
2259:
2260: sprintf(ver,"Synchronet Mail Server v%s%s SMBLIB v%s "
2261: "Compiled %s %s with %s"
2262: ,MAIL_VERSION
2263: #ifdef _DEBUG
2264: ," Debug"
2265: #else
2266: ,""
2267: #endif
2268: ,smb_lib_ver()
2269: ,__DATE__, __TIME__, compiler
2270: );
2271:
2272: return(ver);
2273: }
2274:
2275: void DLLCALL mail_server(void* arg)
2276: {
2277: char compiler[32];
2278: SOCKADDR_IN server_addr;
2279: SOCKADDR_IN client_addr;
2280: int client_addr_len;
2281: SOCKET client_socket;
2282: int i;
2283: int result;
2284: ulong l;
2285: time_t t;
2286: time_t start;
2287: LINGER linger;
2288: fd_set socket_set;
2289: SOCKET high_socket_set;
2290: pop3_t* pop3;
2291: smtp_t* smtp;
2292: struct timeval tv;
2293:
2294: startup=(mail_startup_t*)arg;
2295:
2296: if(startup==NULL) {
2297: sbbs_beep(100,500);
2298: fprintf(stderr, "No startup structure passed!\n");
2299: return;
2300: }
2301:
2302: if(startup->size!=sizeof(mail_startup_t)) { /* verify size */
2303: sbbs_beep(100,500);
2304: sbbs_beep(300,500);
2305: sbbs_beep(100,500);
2306: fprintf(stderr, "Invalid startup structure!\n");
2307: return;
2308: }
2309:
2310: if(startup->relay_port==0)
2311: startup->relay_port=IPPORT_SMTP;
2312:
2313: thread_up();
2314:
2315: status("Initializing");
2316:
2317: #ifdef __unix__ /* Ignore "Broken Pipe" signal */
2318: signal(SIGPIPE,SIG_IGN);
2319: #endif
2320:
2321: lprintf("Synchronet Mail Server Version %s%s"
2322: ,MAIL_VERSION
2323: #ifdef _DEBUG
2324: ," Debug"
2325: #else
2326: ,""
2327: #endif
2328: );
2329:
2330: COMPILER_DESC(compiler);
2331:
2332: lprintf("Compiled %s %s with %s", __DATE__, __TIME__, compiler);
2333:
2334: lprintf("SMBLIB v%s (format %x.%02x)",smb_lib_ver(),smb_ver()>>8,smb_ver()&0xff);
2335:
2336: srand(time(NULL));
2337:
2338: if(!(startup->options&MAIL_OPT_LOCAL_TIMEZONE)) {
2339: if(PUTENV("TZ=UCT0"))
2340: lprintf("!putenv() FAILED");
2341: tzset();
2342:
2343: if((t=checktime())!=0) { /* Check binary time */
2344: lprintf("!TIME PROBLEM (%ld)",t);
2345: cleanup(1);
2346: return;
2347: }
2348: }
2349:
2350: if(!winsock_startup()) {
2351: cleanup(1);
2352: return;
2353: }
2354:
2355: t=time(NULL);
2356: lprintf("Initializing on %.24s with options: %lx"
2357: ,ctime(&t),startup->options);
2358:
2359: /* Initial configuration and load from CNF files */
2360: memset(&scfg, 0, sizeof(scfg));
2361: sprintf(scfg.ctrl_dir, "%.*s", (int)sizeof(scfg.ctrl_dir)-1
2362: ,startup->ctrl_dir);
2363: lprintf("Loading configuration files from %s", scfg.ctrl_dir);
2364: if(!load_cfg(&scfg, NULL)) {
2365: lprintf("!Failed to load configuration files");
2366: cleanup(1);
2367: return;
2368: }
2369:
2370: if(!startup->max_clients) {
2371: startup->max_clients=scfg.sys_nodes;
2372: if(startup->max_clients<10)
2373: startup->max_clients=10;
2374: }
2375:
2376: lprintf("Maximum clients: %u",startup->max_clients);
2377:
2378: if(!startup->max_inactivity)
2379: startup->max_inactivity=120; /* seconds */
2380:
2381: lprintf("Maximum inactivity: %u seconds",startup->max_inactivity);
2382:
2383: active_clients=0;
2384: update_clients();
2385:
2386: /* open a socket and wait for a client */
2387:
2388: server_socket = mail_open_socket(SOCK_STREAM);
2389:
2390: if (server_socket == INVALID_SOCKET) {
2391: lprintf("!ERROR %d opening socket", ERROR_VALUE);
2392: cleanup(1);
2393: return;
2394: }
2395:
2396: lprintf("%04d SMTP socket opened",server_socket);
2397:
2398: #if 1
2399: linger.l_onoff=TRUE;
2400: linger.l_linger=5; /* seconds */
2401:
2402: result = setsockopt (server_socket, SOL_SOCKET, SO_LINGER
2403: ,(char *)&linger, sizeof(linger));
2404:
2405: if (result != 0) {
2406: lprintf("%04d !ERROR %d (%d) setting socket options"
2407: ,server_socket, result, ERROR_VALUE);
2408: cleanup(1);
2409: return;
2410: }
2411: #endif
2412:
2413: /*****************************/
2414: /* Listen for incoming calls */
2415: /*****************************/
2416: memset(&server_addr, 0, sizeof(server_addr));
2417:
2418: server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
2419: server_addr.sin_family = AF_INET;
2420: server_addr.sin_port = htons(startup->smtp_port);
2421:
2422: result = bind(server_socket, (struct sockaddr *) &server_addr
2423: ,sizeof (server_addr));
2424:
2425: if (result != 0) {
2426: lprintf("%04d !ERROR %d (%d) binding SMTP socket to port %u"
2427: ,server_socket, result, ERROR_VALUE, startup->smtp_port);
2428: cleanup(1);
2429: return;
2430: }
2431:
2432: lprintf("%04d SMTP socket bound to port %u"
2433: ,server_socket, startup->smtp_port);
2434:
2435: result = listen (server_socket, 1);
2436:
2437: if (result != 0) {
2438: lprintf("%04d !ERROR %d (%d) listening on socket"
2439: ,server_socket, result, ERROR_VALUE);
2440: cleanup(1);
2441: return;
2442: }
2443:
2444: if(startup->options&MAIL_OPT_ALLOW_POP3) {
2445:
2446: /* open a socket and wait for a client */
2447:
2448: pop3_socket = mail_open_socket(SOCK_STREAM);
2449:
2450: if (pop3_socket == INVALID_SOCKET) {
2451: lprintf("!ERROR %d opening POP3 socket", ERROR_VALUE);
2452: cleanup(1);
2453: return;
2454: }
2455:
2456: lprintf("%04d POP3 socket opened",pop3_socket);
2457:
2458: /*****************************/
2459: /* Listen for incoming calls */
2460: /*****************************/
2461: memset(&server_addr, 0, sizeof(server_addr));
2462:
2463: server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
2464: server_addr.sin_family = AF_INET;
2465: server_addr.sin_port = htons(startup->pop3_port);
2466:
2467: result = bind(pop3_socket, (struct sockaddr *) &server_addr
2468: ,sizeof (server_addr));
2469:
2470: if (result != 0) {
2471: lprintf("%04d !ERROR %d (%d) binding POP3 socket to port %u"
2472: ,pop3_socket, result, ERROR_VALUE, startup->pop3_port);
2473: cleanup(1);
2474: return;
2475: }
2476:
2477: lprintf("%04d POP3 socket bound to port %u"
2478: ,pop3_socket, startup->pop3_port);
2479:
2480: result = listen (pop3_socket, 1);
2481:
2482: if (result != 0) {
2483: lprintf("%04d !ERROR %d (%d) listening on POP3 socket"
2484: ,pop3_socket, result, ERROR_VALUE);
2485: cleanup(1);
2486: return;
2487: }
2488: }
2489:
2490: /* signal caller that we've started up successfully */
2491: if(startup->started!=NULL)
2492: startup->started();
2493:
2494: if(!(startup->options&MAIL_OPT_NO_SENDMAIL))
2495: _beginthread (sendmail_thread, 0, NULL);
2496:
2497: lprintf("%04d Mail Server thread started",server_socket);
2498: status(STATUS_WFC);
2499:
2500: while (server_socket!=INVALID_SOCKET) {
2501:
2502: /* now wait for connection */
2503:
2504: FD_ZERO(&socket_set);
2505: FD_SET(server_socket,&socket_set);
2506: high_socket_set=server_socket+1;
2507: if(startup->options&MAIL_OPT_ALLOW_POP3) {
2508: FD_SET(pop3_socket,&socket_set);
2509: if(pop3_socket+1>high_socket_set)
2510: high_socket_set=pop3_socket+1;
2511: }
2512:
2513: tv.tv_sec=2;
2514: tv.tv_usec=0;
2515:
2516: if((i=select(high_socket_set,&socket_set,NULL,NULL,&tv))<1) {
2517: if(i==0) {
2518: mswait(1);
2519: continue;
2520: }
2521: if(ERROR_VALUE==EINTR)
2522: lprintf("0000 Mail Server listening interrupted");
2523: else if(ERROR_VALUE == ENOTSOCK)
2524: lprintf("0000 Mail Server sockets closed");
2525: else
2526: lprintf("0000 !ERROR %d selecting sockets",ERROR_VALUE);
2527: break;
2528: }
2529:
2530:
2531: if(FD_ISSET(server_socket,&socket_set)) {
2532:
2533: client_addr_len = sizeof (client_addr);
2534: client_socket = accept(server_socket, (struct sockaddr *)&client_addr
2535: ,&client_addr_len);
2536:
2537: if (client_socket == INVALID_SOCKET)
2538: {
2539: if(ERROR_VALUE == ENOTSOCK)
2540: lprintf("%04d SMTP socket closed while listening",server_socket);
2541: else
2542: lprintf("%04d !ERROR %d accept failed", server_socket, ERROR_VALUE);
2543: break;
2544: }
2545: if(startup->socket_open!=NULL)
2546: startup->socket_open(TRUE);
2547: sockets++;
2548:
2549: if(active_clients>=startup->max_clients) {
2550: lprintf("%04d !MAXMIMUM CLIENTS (%u) reached, access denied"
2551: ,client_socket, startup->max_clients);
2552: sockprintf(client_socket,"421 Maximum active clients reached, please try again later.");
2553: mswait(3000);
2554: mail_close_socket(client_socket);
2555: continue;
2556: }
2557:
2558: l=1;
2559:
2560: if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
2561: lprintf("%04d !ERROR %d (%d) disabling blocking on socket"
2562: ,client_socket, i, ERROR_VALUE);
2563: mail_close_socket(client_socket);
2564: continue;
2565: }
2566:
2567: if((smtp=malloc(sizeof(smtp_t)))==NULL) {
2568: lprintf("%04d !ERROR allocating %u bytes of memory for smtp_t"
2569: ,client_socket, sizeof(smtp_t));
2570: mail_close_socket(client_socket);
2571: continue;
2572: }
2573:
2574: smtp->socket=client_socket;
2575: smtp->client_addr=client_addr;
2576: _beginthread (smtp_thread, 0, smtp);
2577: }
2578:
2579: if(FD_ISSET(pop3_socket,&socket_set)) {
2580:
2581: client_addr_len = sizeof (client_addr);
2582: client_socket = accept(pop3_socket, (struct sockaddr *)&client_addr
2583: ,&client_addr_len);
2584:
2585: if (client_socket == INVALID_SOCKET)
2586: {
2587: if(ERROR_VALUE == ENOTSOCK)
2588: lprintf("%04d POP3 socket closed while listening",pop3_socket);
2589: else
2590: lprintf("%04d !ERROR %d accept failed", pop3_socket, ERROR_VALUE);
2591: break;
2592: }
2593: if(startup->socket_open!=NULL)
2594: startup->socket_open(TRUE);
2595: sockets++;
2596:
2597: if(active_clients>=startup->max_clients) {
2598: lprintf("%04d !MAXMIMUM CLIENTS (%u) reached, access denied"
2599: ,client_socket, startup->max_clients);
2600: sockprintf(client_socket,"-ERR Maximum active clients reached, please try again later.");
2601: mswait(3000);
2602: mail_close_socket(client_socket);
2603: continue;
2604: }
2605:
2606:
2607: l=1;
2608:
2609: if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
2610: lprintf("%04d !ERROR %d (%d) disabling blocking on socket"
2611: ,client_socket, i, ERROR_VALUE);
2612: sockprintf(client_socket,"-ERR System error, please try again later.");
2613: mswait(3000);
2614: mail_close_socket(client_socket);
2615: continue;
2616: }
2617:
2618: if((pop3=malloc(sizeof(pop3_t)))==NULL) {
2619: lprintf("%04d !ERROR allocating %u bytes of memory for pop3_t"
2620: ,client_socket,sizeof(pop3_t));
2621: sockprintf(client_socket,"-ERR System error, please try again later.");
2622: mswait(3000);
2623: mail_close_socket(client_socket);
2624: continue;
2625: }
2626:
2627: pop3->socket=client_socket;
2628: pop3->client_addr=client_addr;
2629:
2630: _beginthread (pop3_thread, 0, pop3);
2631: }
2632: }
2633:
2634: if(active_clients) {
2635: lprintf("0000 Waiting for %d active clients to disconnect...", active_clients);
2636: start=time(NULL);
2637: while(active_clients) {
2638: if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
2639: lprintf("!TIMEOUT waiting for %u active clients ",active_clients);
2640: break;
2641: }
2642: mswait(100);
2643: }
2644: }
2645:
2646: if(sendmail_running) {
2647: lprintf("0000 Waiting for SendMail thread to terminate...");
2648: start=time(NULL);
2649: while(sendmail_running) {
2650: if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
2651: lprintf("!TIMEOUT waiting for sendmail thread to "
2652: "terminate");
2653: break;
2654: }
2655: mswait(100);
2656: }
2657: }
2658:
2659: cleanup(0);
2660: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.