Initial revision
[citadel.git] / citadel / netmailer.c
1 /*
2  * netmailer for Citadel/UX
3  * see copyright.doc for copyright information
4  *
5  * netproc calls this to export Citadel mail to RFC822-compliant mailers.
6  *
7  */
8
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <time.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <syslog.h>
17 #include "citadel.h"
18
19 int struncmp();
20 void LoadInternetConfig();
21 void get_config();
22 struct config config;
23
24 char temp[20];
25
26 char ALIASES[128];
27 char CIT86NET[128];
28 char SENDMAIL[128];
29 char FALLBACK[128];
30 char GW_DOMAIN[128];
31 char TABLEFILE[128];
32 int RUN_NETPROC = 1;
33
34 int haschar(st,ch)
35 char st[];
36 int ch; {
37         int a,b;
38         b=0;
39         for (a=0; a<strlen(st); ++a) if (st[a]==ch) ++b;
40         return(b);
41         }
42
43
44 int struncmp(lstr,rstr,len)
45 char lstr[],rstr[];
46 int len; {
47         int pos = 0;
48         char lc,rc;
49         while (pos<len) {
50                 lc=tolower(lstr[pos]);
51                 rc=tolower(rstr[pos]);
52                 if ((lc==0)&&(rc==0)) return(0);
53                 if (lc<rc) return(-1);
54                 if (lc>rc) return(1);
55                 pos=pos+1;
56                 }
57         return(0);
58         }
59
60
61 void fpgetfield(fp,string)
62 FILE *fp;
63 char string[];
64 {
65         int a,b;
66         strcpy(string,"");
67         a=0;
68         do {
69                 b=getc(fp);
70                 if (b<1) {
71                         string[a]=0;
72                         return;
73                         }
74                 string[a]=b;
75                 ++a;
76                 } while (b!=0);
77         }
78
79
80 /* This is NOT the same msgform() found in the main program. It has been
81  * modified to format 80 columns into a temporary file, and extract the
82  * sender and recipient names for use within the main() loop.
83  */
84 void msgform(msgfile,mfout,sbuf,rbuf,nbuf,pbuf,mid_buf,rmname,subj)
85 char *msgfile;
86 FILE *mfout;
87 char *sbuf;             /* sender */
88 char *rbuf;             /* recipient (in this case, an Internet address) */
89 char *nbuf;             /* source node */
90 char *pbuf;             /* path */
91 long *mid_buf;          /* message ID */
92 char *rmname;           /* room name */
93 char *subj;             /* subject */
94         {
95         int a,b,c,e,old,mtype,aflag;
96         int real = 0;
97         char aaa[128],bbb[128];
98         FILE *fp;
99         int width;
100         int generate_subject = 1;
101
102         strcpy(subj, "");
103         strcpy(pbuf, "");       
104         strcpy(nbuf, NODENAME); 
105         strcpy(rmname,"");
106         time(mid_buf);
107         width=80;
108         fp=fopen(msgfile, "rb");
109         if (fp==NULL) {
110                 fprintf(stderr, "netmailer: can't open message file\n");
111                 return;
112                 }
113         strcpy(aaa,""); old=255;
114         c=1; /* c is the current pos */
115         e=getc(fp);
116         if (e!=255) {
117                 fprintf(stderr,"netmailer: This is not a Citadel message.\n");
118                 goto END;
119                 }
120         mtype=getc(fp); aflag=getc(fp);
121         goto BONFGM;
122 A:      if (aflag==1) goto AFLAG;
123         old=real; a=getc(fp); real=a;
124         if (a==0) goto END;
125         if (a<0) goto END;
126
127         /* generate subject... */
128         if ( (generate_subject == 1) && (strlen(subj) < 60)) {
129                 subj[strlen(subj)+1] = 0;
130                 subj[strlen(subj)] = (((a>31)&&(a<127)) ? a : 32);
131                 }
132         
133         if ( ((a==13)||(a==10)) && (old!=13) && (old!=10) ) a=32;
134         if ( ((old==13)||(old==10)) && ((real==32)||(real==13)||(real==10))) {
135                                                 fprintf(mfout,"\n"); c=1; }
136
137         if (a!=32) {
138         if ( ((strlen(aaa)+c)>(width-5)) && (strlen(aaa)>(width-5)) )
139                 { fprintf(mfout,"\n%s",aaa); c=strlen(aaa); aaa[0]=0; }
140          b=strlen(aaa); aaa[b]=a; aaa[b+1]=0; }
141         if (a==32) {    if ((strlen(aaa)+c)>(width-5)) { 
142                                                         fprintf(mfout,"\n");
143                                                         c=1;
144                                                         }
145                         fprintf(mfout,"%s ",aaa); ++c; c=c+strlen(aaa);
146                         strcpy(aaa,""); goto A; }
147         if ((a==13)||(a==10)) {
148                                 fprintf(mfout,"%s\n",aaa); c=1;
149                                 strcpy(aaa,""); goto A; }
150         goto A;
151
152 AFLAG:  a=getc(fp);
153         if (a==0) goto END;
154         if (a==13) {
155                 putc(10, mfout);
156                 }
157         else {
158                 putc(a, mfout);
159                 }
160         goto AFLAG;
161
162 END:    fclose(fp);
163         return;
164
165 BONFGM: b=getc(fp); if (b<0) goto END;
166         if (b=='M') goto A;
167         fpgetfield(fp, bbb);
168         if (b=='A') strcpy(sbuf, bbb);
169         if (b=='R') strcpy(rbuf, bbb);
170         if (b=='N') strcpy(nbuf, bbb);
171         if (b=='P') strcpy(pbuf, bbb);
172         if (b=='I') *mid_buf = atol(bbb);
173         if (b=='O') strcpy(rmname, bbb);
174         if (b=='U') {
175                 strcpy(subj, bbb);
176                 generate_subject = 0; /* have a real subj so don't gen one */
177                 }
178         goto BONFGM;
179         }
180
181 void main(argc,argv)
182 int argc;
183 char *argv[]; {
184         int a;
185         FILE *fp,*rmail;
186         char sbuf[200],rbuf[200],cstr[100],fstr[128];
187         char nbuf[64],pbuf[128],rmname[128],buf[128];
188         char subject[200];
189         long mid_buf;
190         long now;
191         int mlist = 0;
192
193         fprintf(stderr, "netmailer: started...  sending mail to %s\n", argv[1]);
194         openlog("netmailer", LOG_PID, LOG_USER);
195         get_config();   
196         LoadInternetConfig();
197         sprintf(temp, "/tmp/netmailer.%d", getpid()); /* temp file name */
198
199         if ( (argc < 2) || (argc > 3) ) {
200                 fprintf(stderr, "netmailer: usage: netmailer recipient@node.dom [mlist]\n");
201                 exit(1);
202                 }
203
204         /*
205          * If we are running in mailing list mode, the room is being two-way
206          * gatewayed to an Internet mailing list.  Since many listprocs only
207          * accept postings from subscribed addresses, we must always use the
208          * room's address as the originating user.
209          */
210         if ( (argc == 3) && (!strucmp(argv[2], "mlist")) ) {
211                 mlist = 1;
212                 }
213
214         /* convert to ASCII & get info */
215         fp=fopen(temp,"w");
216         msgform(argv[1], fp, sbuf, rbuf, nbuf, pbuf, &mid_buf, rmname, subject);
217         fclose(fp);
218
219         strcpy(buf, rmname);
220         strcpy(rmname, "room_");
221         strcat(rmname, buf);
222         for (a=0; a<strlen(rmname); ++a) {
223                 if (rmname[a] == ' ') rmname[a] = '_';
224                 rmname[a] = tolower(rmname[a]);
225                 }
226
227         sprintf(cstr, SENDMAIL, rbuf);
228         rmail=(FILE *)popen(cstr,"w");
229
230         strcpy(fstr,sbuf);
231         for (a=0; a<strlen(sbuf); ++a) if (sbuf[a]==32) sbuf[a]='_';
232         for (a=0; a<strlen(rbuf); ++a) if (rbuf[a]==32) rbuf[a]='_';
233
234         /*
235          * This logic attempts to compose From and From: lines that are
236          * as RFC822-compliant as possible.  The return addresses are correct
237          * if you're using Citadel's 'citmail' delivery agent to allow BBS
238          * users to receive Internet mail.
239          */
240         fprintf(rmail,"From ");
241         if (strucmp(nbuf,NODENAME)) fprintf(rmail,"%s!",nbuf);
242
243         if (!strucmp(nbuf,NODENAME)) strcpy(nbuf, FQDN);
244         
245         if (mlist) {
246                 fprintf(rmail,"%s\n", rmname);
247                 fprintf(rmail,"From: %s@%s (%s)\n", rmname, FQDN, fstr);
248                 }
249         else {
250
251                 if (!strucmp(nbuf, NODENAME)) {         /* from this system */
252                         fprintf(rmail,"%s\n",pbuf);
253                         fprintf(rmail,"From: %s@%s (%s)\n",
254                                 sbuf, FQDN, fstr);
255                         }
256                 else if (haschar(nbuf, '.')) {          /* from an FQDN */
257                         fprintf(rmail,"%s\n",sbuf);
258                         fprintf(rmail,"From: %s@%s (%s)\n",
259                                 sbuf, nbuf, fstr);
260                         }
261                 else {                                  /* from another Cit */
262                         fprintf(rmail,"%s\n",sbuf);
263                         fprintf(rmail,"From: %s@%s.%s (%s)\n",
264                                 sbuf, nbuf, GW_DOMAIN, fstr);
265                         }
266
267                 }
268
269         /*
270          * Everything else is pretty straightforward.
271          */
272         fprintf(rmail,"To: %s\n", rbuf);
273         time(&now);
274         fprintf(rmail,"Date: %s", asctime(localtime(&now)));
275         fprintf(rmail,"Message-Id: <%ld@%s>\n", mid_buf, nbuf);
276         fprintf(rmail,"X-Mailer: %s\n", CITADEL);
277         fprintf(rmail,"Subject: %s\n", subject);
278         fprintf(rmail,"\n");
279         fp=fopen(temp,"r");
280         if (fp!=NULL) {
281                 do {
282                         a=getc(fp);
283                         if (a>=0) putc(a,rmail);
284                         } while(a>=0);
285                 fclose(fp);
286                 }
287         fprintf(rmail,"\n");
288         pclose(rmail);
289   
290         unlink(temp);           /* get rid of the ASCII file */
291         exit(0);                /* go back to the main program */
292         }