/[pkg-mixmaster]/trunk/Mix/Src/mail.c
ViewVC logotype

Diff of /trunk/Mix/Src/mail.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 122 by weaselp, Wed Aug 7 17:27:01 2002 UTC revision 710 by rabbi, Wed Jan 21 00:47:21 2004 UTC
# Line 1  Line 1 
1  /* Mixmaster version 3  --  (C) 1999 Anonymizer Inc.  /* Mixmaster version 3.0  --  (C) 1999 - 2004 Anonymizer Inc. and others.
2    
3     Mixmaster may be redistributed and modified under certain conditions.     Mixmaster may be redistributed and modified under certain conditions.
4     This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF     This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
# Line 6  Line 6 
6     details.     details.
7    
8     Socket-based mail transport services     Socket-based mail transport services
9     $Id: mail.c,v 1.7 2002/08/07 17:27:01 weaselp Exp $ */     $Id$ */
10    
11    
12  #include "mix3.h"  #include "mix3.h"
# Line 21  Line 21 
21  #include <netinet/in.h>  #include <netinet/in.h>
22  #include <arpa/inet.h>  #include <arpa/inet.h>
23  #include <netdb.h>  #include <netdb.h>
24    #endif /* defined(UNIX) && defined(USE_SOCK) */
25    
26  #include <fcntl.h>  #include <fcntl.h>
27  #endif  #include <time.h>
28    #include <sys/stat.h>
29    #include <errno.h>
30    
31    
32  int sendinfofile(char *name, char *logname, BUFFER *address, BUFFER *header)  int sendinfofile(char *name, char *logname, BUFFER *address, BUFFER *header)
33  {  {
# Line 92  int sendmail_loop(BUFFER *message, char Line 97  int sendmail_loop(BUFFER *message, char
97    return(err);    return(err);
98  }  }
99    
100    /* Returns true if more than one of the recipients in the
101     * rcpt buffer is a remailer
102     */
103    int has_more_than_one_remailer(BUFFER *rcpts)
104    {
105      BUFFER *newlinelist;
106      BUFFER *line;
107      int remailers = 0;
108      REMAILER type1[MAXREM];
109      REMAILER type2[MAXREM];
110      int num1;
111      int num2;
112      int i;
113    
114      newlinelist = buf_new();
115      line = buf_new();
116    
117      num1 = t1_rlist(type1, NULL);
118      num2 = mix2_rlist(type2, NULL);
119    
120      rfc822_addr(rcpts, newlinelist);
121    
122      while (buf_getline(newlinelist, line) != -1) {
123        int found = 0;
124        printf("%s\n", line->data);
125    
126        for (i = 0; i < num2; i++)
127          if (strcmp(type2[i].addr, line->data) == 0) {
128            found = 1;
129            break;
130          }
131        if (!found)
132          for (i = 0; i < num1; i++)
133            if (strcmp(type1[i].addr, line->data) == 0) {
134              found = 1;
135              break;
136            }
137        if (found)
138          remailers++;
139      }
140      printf("found %d\n", remailers);
141    
142      buf_free(newlinelist);
143      buf_free(line);
144    
145      return(remailers > 1);
146    }
147    
148  int sendmail(BUFFER *message, char *from, BUFFER *address)  int sendmail(BUFFER *message, char *from, BUFFER *address)
149  {  {
150    /* returns: 0: ok  1: problem, try again  -1: failed */    /* returns: 0: ok  1: problem, try again  -1: failed */
151    
152    BUFFER *head, *block;    BUFFER *head, *block, *rcpt;
153    FILE *f;    FILE *f;
154    int err = -1;    int err = -1;
155      int rcpt_cnt;
156    
157    head = buf_new();    head = buf_new();
158      rcpt = buf_new();
159    
160    block = readdestblk( );    block = readdestblk( );
161    if ( !block ) block = buf_new( );    if ( !block ) block = buf_new( );
# Line 117  int sendmail(BUFFER *message, char *from Line 172  int sendmail(BUFFER *message, char *from
172    if (address != NULL)    if (address != NULL)
173      buf_appendf(head, "To: %b\n", address);      buf_appendf(head, "To: %b\n", address);
174    
175      if (PRECEDENCE[0])
176            buf_appendf(head, "Precedence: %s\n", PRECEDENCE);
177    
178    buf_rewind(message);    buf_rewind(message);
179    
180    if (SMTPRELAY[0])    /* search recipient addresses */
181      if (address == NULL) {
182        BUFFER *field, *content;
183        field = buf_new();
184        content = buf_new();
185    
186        rcpt_cnt = 0;
187        while (buf_getheader(message, field, content) == 0) {
188          if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
189            int thislinercpts = 1;
190            char *tmp = content->data;
191            while ((tmp = strchr(tmp+1, ',')))
192              thislinercpts ++;
193            rcpt_cnt += thislinercpts;
194    
195            if ( rcpt->data[0] )
196              buf_appends(rcpt, ", ");
197            buf_cat(rcpt, content);
198          }
199        }
200        buf_free(field);
201        buf_free(content);
202      } else if (address->data[0]) {
203        char *tmp = address->data;
204        rcpt_cnt = 1;
205        while ((tmp = strchr(tmp+1, ',')))
206          rcpt_cnt ++;
207    
208        buf_set(rcpt, address);
209      } else
210        rcpt_cnt = 0;
211    
212      buf_rewind(message);
213    
214      if ( ! rcpt_cnt ) {
215        errlog(NOTICE, "No recipients found.\n");
216        err = 0;
217      } else if ( rcpt_cnt > MAXRECIPIENTS ) {
218        errlog(NOTICE, "Too many recipients.  Dropping message.\n");
219        err = 0;
220      } else if ( rcpt_cnt > 1 && has_more_than_one_remailer(rcpt) ) {
221        errlog(NOTICE, "Message is destined to more than one remailer.  Dropping.\n");
222        err = 0;
223      } else if ( REMAIL && strcmp(REMAILERADDR, rcpt->data) == 0) {
224        buf_cat(head, message);
225        errlog(LOG, "Message loops back to us; storing in pool rather than sending it.\n");
226        err = pool_add(head, "inf");
227      } else if (SMTPRELAY[0])
228      err = smtpsend(head, message, from);      err = smtpsend(head, message, from);
229    else if (strieq(SENDMAIL, "outfile")) {    else if (strieq(SENDMAIL, "outfile")) {
230      char path[PATHMAX];      char path[PATHMAX];
231      FILE *f = NULL;      FILE *f = NULL;
232    #ifdef SHORTNAMES
233      int i;      int i;
   
234      for (i = 0; i < 10000; i++) {      for (i = 0; i < 10000; i++) {
235        sprintf(path, "%s%cout%i.txt", POOLDIR, DIRSEP, i);        snprintf(path, PATHMAX, "%s%cout%i.txt", POOLDIR, DIRSEP, i);
236        f = fopen(path, "r");        f = fopen(path, "r");
237        if (f)        if (f)
238          fclose(f);          fclose(f);
# Line 135  int sendmail(BUFFER *message, char *from Line 240  int sendmail(BUFFER *message, char *from
240          break;          break;
241      }      }
242      f = fopen(path, "w");      f = fopen(path, "w");
243    #else /* end of SHORTNAMES */
244        static unsigned long namecounter = 0;
245        struct stat statbuf;
246        int count;
247        char hostname[64];
248    
249        hostname[0] = '\0';
250        gethostname(hostname, 63);
251        hostname[63] = '\0';
252    
253        /* Step 2:  Stat the file.  Wait for ENOENT as a response. */
254        for (count = 0;; count++) {
255          snprintf(path, PATHMAX, "%s%cout.%lu.%u_%lu.%s,S=%lu.txt",
256            POOLDIR, DIRSEP, time(NULL), getpid(), namecounter++, hostname, head->length + message->length);
257    
258          if (stat(path, &statbuf) == 0)
259            errno = EEXIST;
260          else if (errno == ENOENT) { /* create the file (at least try) */
261            f = fopen(path, "w");
262            if (f != NULL)
263              break; /* we managed to open the file */
264          }
265          if (count > 5)
266            break; /* Too many retries - give up */
267    #ifdef WIN32
268          Sleep(2000); /* sleep and retry */
269    #else /* end of WIN32 */
270          sleep(2); /* sleep and retry */
271    #endif /* else not WIN32 */
272        }
273    #endif /* else not SHORTNAMES */
274      if (f != NULL) {      if (f != NULL) {
275        err = buf_write(head, f);        err = buf_write(head, f);
276        err = buf_write(message, f);        err = buf_write(message, f);
# Line 157  int sendmail(BUFFER *message, char *from Line 293  int sendmail(BUFFER *message, char *from
293  end:  end:
294    buf_free(block);    buf_free(block);
295    buf_free(head);    buf_free(head);
296      buf_free(rcpt);
297    return (err);    return (err);
298  }  }
299    
# Line 179  void sock_exit(void) Line 316  void sock_exit(void)
316  {  {
317    WSACleanup();    WSACleanup();
318  }  }
319  #endif  #endif /* WIN32 */
320    
321  SOCKET opensocket(char *hostname, int port)  SOCKET opensocket(char *hostname, int port)
322  {  {
# Line 209  int closesocket(SOCKET s) Line 346  int closesocket(SOCKET s)
346  {  {
347    return (close(s));    return (close(s));
348  }  }
349  #endif  #endif /* ifndef WIN32 */
350    
351  int sock_getline(SOCKET s, BUFFER *line)  int sock_getline(SOCKET s, BUFFER *line)
352  {  {
# Line 242  int sock_cat(SOCKET s, BUFFER *b) Line 379  int sock_cat(SOCKET s, BUFFER *b)
379    } while (p < b->length);    } while (p < b->length);
380    return (0);    return (0);
381  }  }
382  #else  #else /* end of USE_SOCK */
383  SOCKET opensocket(char *hostname, int port)  SOCKET opensocket(char *hostname, int port)
384  {  {
385    return (INVALID_SOCKET);    return (INVALID_SOCKET);
# Line 262  int sock_cat(SOCKET s, BUFFER *b) Line 399  int sock_cat(SOCKET s, BUFFER *b)
399  {  {
400    return (-1);    return (-1);
401  }  }
402  #endif  #endif /* else not USE_SOCK */
403    
404  /* send messages by SMTP ************************************************/  /* send messages by SMTP ************************************************/
405    
406  static int sock_getsmtp(SOCKET s, BUFFER *line)  static int sock_getsmtp(SOCKET s, BUFFER *response)
407  {  {
408    int ret;    int ret;
409      BUFFER *line;
410      line = buf_new();
411    
412    do    buf_clear(response);
413      do {
414      ret = sock_getline(s, line);      ret = sock_getline(s, line);
415    while (line->length >= 4 && line->data[3] == '-');      buf_cat(response, line);
416      } while (line->length >= 4 && line->data[3] == '-');
417      buf_free(line);
418    return (ret);    return (ret);
419  }  }
420    
421  SOCKET smtp_open(void)  SOCKET smtp_open(void)
422  {  {
423    int s = INVALID_SOCKET;    int s = INVALID_SOCKET;
424      int esmtp = 0;
425    BUFFER *line;    BUFFER *line;
426    
427  #ifdef USE_SOCK  #ifdef USE_SOCK
# Line 287  SOCKET smtp_open(void) Line 430  SOCKET smtp_open(void)
430    if (s != INVALID_SOCKET) {    if (s != INVALID_SOCKET) {
431      line = buf_new();      line = buf_new();
432      sock_getsmtp(s, line);      sock_getsmtp(s, line);
433        if (bufifind(line, "ESMTP"))
434          esmtp = 1;
435      if (line->data[0] != '2') {      if (line->data[0] != '2') {
436        errlog(ERRORMSG, "SMTP relay not ready. %b\n", line);        errlog(ERRORMSG, "SMTP relay not ready. %b\n", line);
437        closesocket(s);        closesocket(s);
438        s = INVALID_SOCKET;        s = INVALID_SOCKET;
439      } else {      } else {
440        errlog(DEBUGINFO, "Opening SMTP connection.\n");        errlog(DEBUGINFO, "Opening SMTP connection.\n");
441        buf_sets(line, "HELO ");        if (esmtp)
442            buf_sets(line, "EHLO ");
443          else
444            buf_sets(line, "HELO ");
445        if (HELONAME[0])        if (HELONAME[0])
446          buf_appends(line, HELONAME);          buf_appends(line, HELONAME);
447        else if (strchr(ENVFROM, '@'))        else if (strchr(ENVFROM, '@'))
# Line 312  SOCKET smtp_open(void) Line 460  SOCKET smtp_open(void)
460          else          else
461            buf_appends(line, SHORTNAME);            buf_appends(line, SHORTNAME);
462        }        }
463          buf_chop(line);
464        buf_appends(line, "\r\n");        buf_appends(line, "\r\n");
465        sock_cat(s, line);        sock_cat(s, line);
466        sock_getsmtp(s, line);        sock_getsmtp(s, line);
# Line 319  SOCKET smtp_open(void) Line 468  SOCKET smtp_open(void)
468          errlog(ERRORMSG, "SMTP relay refuses HELO: %b\n", line);          errlog(ERRORMSG, "SMTP relay refuses HELO: %b\n", line);
469          closesocket(s);          closesocket(s);
470          s = INVALID_SOCKET;          s = INVALID_SOCKET;
471          } else if (SMTPUSERNAME[0] && esmtp && bufifind(line, "AUTH") && bufifind(line, "LOGIN")) {
472            buf_sets(line, "AUTH LOGIN\r\n");
473            sock_cat(s, line);
474            sock_getsmtp(s, line);
475            if (!bufleft(line, "334")) {
476              errlog(ERRORMSG, "SMTP AUTH fails: %b\n", line);
477              goto err;
478            }
479            buf_sets(line, SMTPUSERNAME);
480            encode(line, 0);
481            buf_appends(line, "\r\n");
482            sock_cat(s, line);
483            sock_getsmtp(s, line);
484            if (!bufleft(line, "334")) {
485              errlog(ERRORMSG, "SMTP username rejected: %b\n", line);
486              goto err;
487            }
488            buf_sets(line, SMTPPASSWORD);
489            encode(line, 0);
490            buf_appends(line, "\r\n");
491            sock_cat(s, line);
492            sock_getsmtp(s, line);
493            if (!bufleft(line, "235"))
494              errlog(ERRORMSG, "SMTP authentication failed: %b\n", line);
495        }        }
496      }      }
497    err:
498      buf_free(line);      buf_free(line);
499    }    }
500  #endif  #endif /* USE_SOCK */
501    return (s);    return (s);
502  }  }
503    
# Line 343  int smtp_close(SOCKET s) Line 517  int smtp_close(SOCKET s)
517      errlog(WARNING, "SMTP quit failed: %b\n", line);      errlog(WARNING, "SMTP quit failed: %b\n", line);
518    closesocket(s);    closesocket(s);
519    buf_free(line);    buf_free(line);
520  #endif  #endif /* USE_SOCK */
521    return (ret);    return (ret);
522  }  }
523    
# Line 361  int smtp_send(SOCKET relay, BUFFER *head Line 535  int smtp_send(SOCKET relay, BUFFER *head
535    while (buf_getheader(head, field, content) == 0)    while (buf_getheader(head, field, content) == 0)
536      if (bufieq(field, "to"))      if (bufieq(field, "to"))
537  #ifdef BROKEN_MTA  #ifdef BROKEN_MTA
538        if (!bufifind(rcpt, content->data))        if (!bufifind(rcpt, content->data))
539        /* Do not add the same recipient twice.        /* Do not add the same recipient twice.
540           Needed for brain-dead MTAs.      */           Needed for brain-dead MTAs.      */
541  #endif //BROKEN_MTA  #endif /* BROKEN_MTA */
542          rfc822_addr(content, rcpt);          rfc822_addr(content, rcpt);
543    buf_rewind(head);    buf_rewind(head);
544    
545    while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {    while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {
546      if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {      if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
547  #ifdef BROKEN_MTA  #ifdef BROKEN_MTA
548        if (!bufifind(rcpt, content->data))        if (!bufifind(rcpt, content->data))
549        /* Do not add the same recipient twice.        /* Do not add the same recipient twice.
550           Needed for brain-dead MTAs.      */           Needed for brain-dead MTAs.      */
551  #endif //BROKEN_MTA  #endif /* BROKEN_MTA */
552          rfc822_addr(content, rcpt);          rfc822_addr(content, rcpt);
553      }      }
554      if (!bufieq(field, "bcc"))      if (!bufieq(field, "bcc"))
# Line 408  int smtp_send(SOCKET relay, BUFFER *head Line 582  int smtp_send(SOCKET relay, BUFFER *head
582        errlog(ERRORMSG, "SMTP relay error: %b\n", line);        errlog(ERRORMSG, "SMTP relay error: %b\n", line);
583        goto end;        goto end;
584      }      }
585        if (bufleft(line, "530")) {
586          errlog(ERRORMSG, "SMTP authentication required: %b\n", line);
587          goto end;
588        }
589    }    }
590    
591    buf_sets(line, "DATA\r\n");    buf_sets(line, "DATA\r\n");
# Line 445  end: Line 623  end:
623    buf_free(field);    buf_free(field);
624    buf_free(content);    buf_free(content);
625    buf_free(rcpt);    buf_free(rcpt);
626  #endif  #endif /* USE_SOCK */
627    return (ret);    return (ret);
628  }  }
629    
# Line 496  SOCKET pop3_open(char *user, char *host, Line 674  SOCKET pop3_open(char *user, char *host,
674    SOCKET server = INVALID_SOCKET;    SOCKET server = INVALID_SOCKET;
675    BUFFER *line;    BUFFER *line;
676    int authenticated = 0;    int authenticated = 0;
677    char c, md[33];    char md[33];
678      int c;
679    
680    line = buf_new();    line = buf_new();
681    server = opensocket(host, 110);    server = opensocket(host, 110);
# Line 670  void pop3get(void) Line 849  void pop3get(void)
849    f = mix_openfile(POP3CONF, "r");    f = mix_openfile(POP3CONF, "r");
850    if (f != NULL)    if (f != NULL)
851      while (fgets(cfg, sizeof(cfg), f) != NULL) {      while (fgets(cfg, sizeof(cfg), f) != NULL) {
852          if (cfg[0] == '#')
853            continue;
854        if (strchr(cfg, '@'))        if (strchr(cfg, '@'))
855          strchr(cfg, '@')[0] = ' ';          strchr(cfg, '@')[0] = ' ';
856        if (sscanf(cfg, "%127s %127s %127s %4s", user, host, pass, auth) < 3)        if (sscanf(cfg, "%127s %127s %127s %4s", user, host, pass, auth) < 3)
# Line 715  void pop3get(void) Line 896  void pop3get(void)
896    buf_free(line);    buf_free(line);
897    buf_free(msg);    buf_free(msg);
898  }  }
899  #endif  #endif /* USE_SOCK */

Legend:
Removed from v.122  
changed lines
  Added in v.710

  ViewVC Help
Powered by ViewVC 1.1.5