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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 647 - (hide annotations) (download)
Sat Oct 25 23:34:13 2003 UTC (9 years, 7 months ago) by weasel
File MIME type: text/plain
File size: 20852 byte(s)
Set keyword expansion for Id on all files that already have $Id$ tags.
1 rabbi 1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2    
3     Mixmaster may be redistributed and modified under certain conditions.
4     This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5     ANY KIND, either express or implied. See the file COPYRIGHT for
6     details.
7    
8     Socket-based mail transport services
9 weasel 647 $Id$ */
10 rabbi 1
11    
12     #include "mix3.h"
13     #include <stdio.h>
14     #include <stdlib.h>
15     #include <string.h>
16    
17     #if defined(UNIX) && defined(USE_SOCK)
18     #include <unistd.h>
19     #include <sys/types.h>
20     #include <sys/socket.h>
21     #include <netinet/in.h>
22     #include <arpa/inet.h>
23     #include <netdb.h>
24 rabbi 262 #endif /* defined(UNIX) && defined(USE_SOCK) */
25    
26 rabbi 1 #include <fcntl.h>
27 weaselp 203 #include <time.h>
28     #include <sys/stat.h>
29     #include <errno.h>
30 rabbi 1
31 weaselp 203
32 rabbi 1 int sendinfofile(char *name, char *logname, BUFFER *address, BUFFER *header)
33     {
34 weaselp 122 FILE *f = NULL, *log = NULL;
35 rabbi 1 BUFFER *msg, *addr;
36     char line[LINELEN];
37     int ret = -1;
38    
39     if (bufeq(address, ANONNAME))
40     return (0); /* don't reply to our own anon messages */
41     f = mix_openfile(name, "r");
42     if (f == NULL)
43     return (-1);
44    
45     addr = buf_new();
46     rfc822_addr(address, addr);
47     if (addr->length == 0)
48     buf_set(addr, address), buf_nl(addr);
49    
50     if (logname != NULL) {
51     if ((log = mix_openfile(logname, "r+")) != NULL) {
52     /* log recipients to prevent mail loop */
53     while (fgets(line, sizeof(line), log) != NULL)
54     if (strieq(line, addr->data))
55     goto end;
56     } else if ((log = mix_openfile(logname, "w")) == NULL) {
57     errlog(ERRORMSG, "Can't create %s.\n", logname);
58     ret = -1;
59     goto end;
60     }
61     fprintf(log, "%s", addr->data);
62     }
63     msg = buf_new();
64     if (header)
65     buf_cat(msg, header), buf_nl(msg);
66     while (fgets(line, sizeof(line), f) != NULL) {
67     if (streq(line, "DESTINATION-BLOCK\n"))
68     buf_appendf(msg, "destination-block %b", addr);
69     else
70     buf_appends(msg, line);
71     }
72     ret = sendmail(msg, REMAILERNAME, address);
73     buf_free(msg);
74     end:
75 weaselp 122 if (f)
76     fclose(f);
77 rabbi 1 if (log)
78     fclose(log);
79     buf_free(addr);
80     return (ret);
81     }
82    
83     int smtpsend(BUFFER *head, BUFFER *message, char *from);
84    
85 weaselp 116
86     int sendmail_loop(BUFFER *message, char *from, BUFFER *address)
87     {
88     BUFFER *msg;
89     int err;
90    
91     msg = buf_new();
92     buf_appendf(msg, "X-Loop: %s\n", REMAILERADDR);
93     buf_cat(msg, message);
94     err = sendmail(msg, from, address);
95     buf_free(msg);
96    
97     return(err);
98 weaselp 121 }
99 weaselp 116
100 weaselp 545 /* 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 rabbi 1 int sendmail(BUFFER *message, char *from, BUFFER *address)
149     {
150     /* returns: 0: ok 1: problem, try again -1: failed */
151    
152 weaselp 523 BUFFER *head, *block, *rcpt;
153 rabbi 1 FILE *f;
154     int err = -1;
155 weaselp 591 int rcpt_cnt;
156 rabbi 1
157     head = buf_new();
158 weaselp 523 rcpt = buf_new();
159 rabbi 1
160     block = readdestblk( );
161     if ( !block ) block = buf_new( );
162    
163     if (address != NULL &&
164     (address->length == 0 || doblock(address, block, 1) == -1))
165     goto end;
166    
167     if (from != NULL) {
168     buf_setf(head, "From: %s", from);
169     hdr_encode(head, 255);
170     buf_nl(head);
171     }
172     if (address != NULL)
173     buf_appendf(head, "To: %b\n", address);
174    
175 weaselp 548 if (PRECEDENCE[0])
176     buf_appendf(head, "Precedence: %s\n", PRECEDENCE);
177    
178 rabbi 1 buf_rewind(message);
179    
180 weaselp 545 /* search recipient addresses */
181 weaselp 523 if (address == NULL) {
182     BUFFER *field, *content;
183     field = buf_new();
184     content = buf_new();
185    
186 weaselp 591 rcpt_cnt = 0;
187 weaselp 523 while (buf_getheader(message, field, content) == 0) {
188 weaselp 545 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 weaselp 523 }
199     }
200     buf_free(field);
201     buf_free(content);
202 weaselp 591 } 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 weaselp 523 buf_set(rcpt, address);
209 weaselp 591 } else
210     rcpt_cnt = 0;
211    
212 weaselp 537 buf_rewind(message);
213 weaselp 523
214 weaselp 545 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 weaselp 523 buf_cat(head, message);
225 weaselp 545 errlog(LOG, "Message loops back to us; storing in pool rather than sending it.\n");
226 weaselp 523 err = pool_add(head, "inf");
227     } else if (SMTPRELAY[0])
228 rabbi 1 err = smtpsend(head, message, from);
229     else if (strieq(SENDMAIL, "outfile")) {
230     char path[PATHMAX];
231     FILE *f = NULL;
232 weaselp 203 #ifdef SHORTNAMES
233 rabbi 1 int i;
234     for (i = 0; i < 10000; i++) {
235 weaselp 204 snprintf(path, PATHMAX, "%s%cout%i.txt", POOLDIR, DIRSEP, i);
236 rabbi 1 f = fopen(path, "r");
237     if (f)
238     fclose(f);
239     else
240     break;
241     }
242     f = fopen(path, "w");
243 rabbi 262 #else /* end of SHORTNAMES */
244 weaselp 203 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 rabbi 262 #else /* end of WIN32 */
270 weaselp 203 sleep(2); /* sleep and retry */
271 rabbi 262 #endif /* else not WIN32 */
272 weaselp 203 }
273 rabbi 262 #endif /* else not SHORTNAMES */
274 rabbi 1 if (f != NULL) {
275     err = buf_write(head, f);
276     err = buf_write(message, f);
277     fclose(f);
278     } else
279     errlog(ERRORMSG, "Can't create %s!\n", path);
280     } else {
281     if (SENDANONMAIL[0] != '\0' && (from == NULL || streq(from, ANONNAME)))
282     f = openpipe(SENDANONMAIL);
283     else
284     f = openpipe(SENDMAIL);
285     if (f != NULL) {
286     err = buf_write(head, f);
287     err = buf_write(message, f);
288     closepipe(f);
289     }
290     }
291     if (err != 0)
292     err = 1; /* error while sending, retry later */
293     end:
294     buf_free(block);
295     buf_free(head);
296 weaselp 523 buf_free(rcpt);
297 rabbi 1 return (err);
298     }
299    
300     /* socket communication **********************************************/
301    
302     #ifdef USE_SOCK
303     #ifdef WIN32
304     WSADATA w;
305    
306     int sock_init()
307     {
308     if (WSAStartup(MAKEWORD(2, 0), &w) != 0) {
309     errlog(ERRORMSG, "Unable to initialize WINSOCK.\n");
310     return 0;
311     }
312     return 1;
313     }
314    
315     void sock_exit(void)
316     {
317     WSACleanup();
318     }
319 rabbi 262 #endif /* WIN32 */
320 rabbi 1
321     SOCKET opensocket(char *hostname, int port)
322     {
323     struct hostent *hp;
324     struct sockaddr_in server;
325     SOCKET s;
326    
327     if ((hp = gethostbyname(hostname)) == NULL)
328     return (INVALID_SOCKET);
329    
330     memset((char *) &server, 0, sizeof(server));
331     server.sin_family = AF_INET;
332     server.sin_addr.s_addr = *(unsigned long *) hp->h_addr;
333     server.sin_port = htons((unsigned short) port);
334    
335     s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
336     if (s != INVALID_SOCKET)
337     if (connect(s, (struct sockaddr *) &server, sizeof(server)) < 0) {
338     closesocket(s);
339     return (INVALID_SOCKET);
340     }
341     return (s);
342     }
343    
344     #ifndef WIN32
345     int closesocket(SOCKET s)
346     {
347     return (close(s));
348     }
349 rabbi 262 #endif /* ifndef WIN32 */
350 rabbi 1
351     int sock_getline(SOCKET s, BUFFER *line)
352     {
353     char c;
354     int ok;
355    
356     buf_clear(line);
357     while ((ok = recv(s, &c, 1, 0)) > 0) {
358     if (c == '\n')
359     break;
360     if (c != '\r')
361     buf_appendc(line, c);
362     }
363     if (ok <= 0)
364     return (-1);
365     if (line->length == 0)
366     return (1);
367     return (0);
368     }
369    
370     int sock_cat(SOCKET s, BUFFER *b)
371     {
372     int p = 0, n;
373    
374     do {
375     n = send(s, b->data, b->length, 0);
376     if (n < 0)
377     return (-1);
378     p += n;
379     } while (p < b->length);
380     return (0);
381     }
382 rabbi 262 #else /* end of USE_SOCK */
383 rabbi 1 SOCKET opensocket(char *hostname, int port)
384     {
385     return (INVALID_SOCKET);
386     }
387    
388     int closesocket(SOCKET s)
389     {
390     return (INVALID_SOCKET);
391     }
392    
393     int sock_getline(SOCKET s, BUFFER *line)
394     {
395     return (-1);
396     }
397    
398     int sock_cat(SOCKET s, BUFFER *b)
399     {
400     return (-1);
401     }
402 rabbi 262 #endif /* else not USE_SOCK */
403 rabbi 1
404     /* send messages by SMTP ************************************************/
405    
406 ulfm 269 static int sock_getsmtp(SOCKET s, BUFFER *response)
407 rabbi 1 {
408     int ret;
409 ulfm 269 BUFFER *line;
410     line = buf_new();
411 rabbi 1
412 ulfm 269 buf_clear(response);
413     do {
414 rabbi 1 ret = sock_getline(s, line);
415 ulfm 269 buf_cat(response, line);
416     } while (line->length >= 4 && line->data[3] == '-');
417     buf_free(line);
418 rabbi 1 return (ret);
419     }
420    
421     SOCKET smtp_open(void)
422     {
423     int s = INVALID_SOCKET;
424 ulfm 269 int esmtp = 0;
425 rabbi 1 BUFFER *line;
426    
427     #ifdef USE_SOCK
428     if (SMTPRELAY[0] != '\0')
429     s = opensocket(SMTPRELAY, 25);
430     if (s != INVALID_SOCKET) {
431     line = buf_new();
432     sock_getsmtp(s, line);
433 ulfm 269 if (bufifind(line, "ESMTP"))
434     esmtp = 1;
435 rabbi 1 if (line->data[0] != '2') {
436     errlog(ERRORMSG, "SMTP relay not ready. %b\n", line);
437     closesocket(s);
438     s = INVALID_SOCKET;
439     } else {
440     errlog(DEBUGINFO, "Opening SMTP connection.\n");
441 ulfm 269 if (esmtp)
442 weaselp 332 buf_sets(line, "EHLO ");
443 ulfm 269 else
444 weaselp 332 buf_sets(line, "HELO ");
445 rabbi 1 if (HELONAME[0])
446     buf_appends(line, HELONAME);
447     else if (strchr(ENVFROM, '@'))
448     buf_appends(line, strchr(ENVFROM, '@') + 1);
449     else {
450     struct sockaddr_in sa;
451     int len = sizeof(sa);
452     struct hostent *hp;
453    
454     if (getsockname(s, (struct sockaddr *) &sa, &len) == 0 &&
455     (hp = gethostbyaddr((char *) &sa.sin_addr, sizeof(sa.sin_addr),
456     AF_INET)) != NULL)
457     buf_appends(line, (char *) hp->h_name);
458     else if (strchr(REMAILERADDR, '@'))
459     buf_appends(line, strchr(REMAILERADDR, '@') + 1);
460     else
461     buf_appends(line, SHORTNAME);
462     }
463 ulfm 269 buf_chop(line);
464 rabbi 1 buf_appends(line, "\r\n");
465     sock_cat(s, line);
466     sock_getsmtp(s, line);
467     if (line->data[0] != '2') {
468     errlog(ERRORMSG, "SMTP relay refuses HELO: %b\n", line);
469     closesocket(s);
470     s = INVALID_SOCKET;
471 ulfm 269 } else if (SMTPUSERNAME[0] && esmtp && bufifind(line, "AUTH") && bufifind(line, "LOGIN")) {
472 weaselp 332 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 rabbi 1 }
496     }
497 ulfm 269 err:
498 rabbi 1 buf_free(line);
499     }
500 rabbi 262 #endif /* USE_SOCK */
501 rabbi 1 return (s);
502     }
503    
504     int smtp_close(SOCKET s)
505     {
506     BUFFER *line;
507     int ret = -1;
508    
509     #ifdef USE_SOCK
510     line = buf_new();
511     buf_sets(line, "QUIT\r\n");
512     sock_cat(s, line);
513     if (sock_getsmtp(s, line) == 0 && line->data[0] == '2') {
514     errlog(DEBUGINFO, "Closing SMTP connection.\n");
515     ret = 0;
516     } else
517     errlog(WARNING, "SMTP quit failed: %b\n", line);
518     closesocket(s);
519     buf_free(line);
520 rabbi 262 #endif /* USE_SOCK */
521 rabbi 1 return (ret);
522     }
523    
524     int smtp_send(SOCKET relay, BUFFER *head, BUFFER *message, char *from)
525     {
526     BUFFER *rcpt, *line, *field, *content;
527     int ret = -1;
528    
529     #ifdef USE_SOCK
530     line = buf_new();
531     field = buf_new();
532     content = buf_new();
533     rcpt = buf_new();
534    
535     while (buf_getheader(head, field, content) == 0)
536     if (bufieq(field, "to"))
537 rabbi 29 #ifdef BROKEN_MTA
538 weaselp 332 if (!bufifind(rcpt, content->data))
539     /* Do not add the same recipient twice.
540     Needed for brain-dead MTAs. */
541 rabbi 221 #endif /* BROKEN_MTA */
542 rabbi 29 rfc822_addr(content, rcpt);
543 rabbi 1 buf_rewind(head);
544    
545 weaselp 116 while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {
546 rabbi 1 if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
547 rabbi 29 #ifdef BROKEN_MTA
548 weaselp 332 if (!bufifind(rcpt, content->data))
549     /* Do not add the same recipient twice.
550     Needed for brain-dead MTAs. */
551 rabbi 221 #endif /* BROKEN_MTA */
552 rabbi 29 rfc822_addr(content, rcpt);
553 rabbi 1 }
554     if (!bufieq(field, "bcc"))
555     buf_appendheader(head, field, content);
556     }
557     buf_nl(head);
558    
559     buf_clear(content);
560     if (from) {
561     buf_sets(line, from);
562     rfc822_addr(line, content);
563     buf_chop(content);
564     }
565     if (bufieq(content, REMAILERADDR) || bufieq(content, ANONADDR))
566     buf_clear(content);
567     if (content->length == 0)
568     buf_sets(content, ENVFROM[0] ? ENVFROM : ANONADDR);
569    
570     buf_setf(line, "MAIL FROM:<%b>\r\n", content);
571     sock_cat(relay, line);
572     sock_getsmtp(relay, line);
573     if (!line->data[0] == '2') {
574     errlog(ERRORMSG, "SMTP relay does not accept mail: %b\n", line);
575     goto end;
576     }
577     while (buf_getline(rcpt, content) == 0) {
578     buf_setf(line, "RCPT TO:<%b>\r\n", content);
579     sock_cat(relay, line);
580     sock_getsmtp(relay, line);
581     if (bufleft(line, "421")) {
582     errlog(ERRORMSG, "SMTP relay error: %b\n", line);
583     goto end;
584     }
585 ulfm 269 if (bufleft(line, "530")) {
586     errlog(ERRORMSG, "SMTP authentication required: %b\n", line);
587     goto end;
588     }
589 rabbi 1 }
590    
591     buf_sets(line, "DATA\r\n");
592     sock_cat(relay, line);
593     sock_getsmtp(relay, line);
594     if (!bufleft(line, "354")) {
595     errlog(WARNING, "SMTP relay does not accept message: %b\n", line);
596     goto end;
597     }
598     while (buf_getline(head, line) >= 0) {
599     buf_appends(line, "\r\n");
600     if (bufleft(line, ".")) {
601     buf_setf(content, ".%b", line);
602     buf_move(line, content);
603     }
604     sock_cat(relay, line);
605     }
606     while (buf_getline(message, line) >= 0) {
607     buf_appends(line, "\r\n");
608     if (bufleft(line, ".")) {
609     buf_setf(content, ".%b", line);
610     buf_move(line, content);
611     }
612     sock_cat(relay, line);
613     }
614     buf_sets(line, ".\r\n");
615     sock_cat(relay, line);
616     sock_getsmtp(relay, line);
617     if (bufleft(line, "2"))
618     ret = 0;
619     else
620     errlog(WARNING, "SMTP relay will not send message: %b\n", line);
621     end:
622     buf_free(line);
623     buf_free(field);
624     buf_free(content);
625     buf_free(rcpt);
626 rabbi 262 #endif /* USE_SOCK */
627 rabbi 1 return (ret);
628     }
629    
630     static SOCKET sendmail_state = INVALID_SOCKET;
631    
632     void sendmail_begin(void)
633     {
634     /* begin mail sending session */
635     if (sendmail_state == INVALID_SOCKET)
636     sendmail_state = smtp_open();
637     }
638     void sendmail_end(void)
639     {
640     /* end mail sending session */
641     if (sendmail_state != INVALID_SOCKET) {
642     smtp_close(sendmail_state);
643     sendmail_state = INVALID_SOCKET;
644     }
645     }
646    
647     int smtpsend(BUFFER *head, BUFFER *message, char *from)
648     {
649     SOCKET s;
650     int ret = -1;
651    
652     if (sendmail_state != INVALID_SOCKET)
653     ret = smtp_send(sendmail_state, head, message, from);
654     else {
655     s = smtp_open();
656     if (s != INVALID_SOCKET) {
657     ret = smtp_send(s, head, message, from);
658     smtp_close(s);
659     }
660     }
661     return (ret);
662     }
663    
664     /* retrieve mail with POP3 **********************************************/
665     #ifdef USE_SOCK
666     int pop3_close(SOCKET s);
667    
668     #define POP3_ANY 0
669     #define POP3_APOP 1
670     #define POP3_PASS 2
671    
672     SOCKET pop3_open(char *user, char *host, char *pass, int auth)
673     {
674     SOCKET server = INVALID_SOCKET;
675     BUFFER *line;
676     int authenticated = 0;
677 weaselp 228 char md[33];
678     int c;
679 rabbi 1
680     line = buf_new();
681     server = opensocket(host, 110);
682     if (server == INVALID_SOCKET)
683     errlog(NOTICE, "Can't connect to POP3 server %s.\n", host);
684     else {
685     sock_getline(server, line);
686     if (!bufleft(line, "+")) {
687     errlog(WARNING, "No POP3 service at %s.\n", host);
688     closesocket(server);
689 rabbi 11 server = INVALID_SOCKET;
690 rabbi 1 }
691     }
692     if (server != INVALID_SOCKET) {
693     errlog(DEBUGINFO, "Opening POP3 connection to %s.\n", host);
694     do
695     c = buf_getc(line);
696     while (c != '<' && c != -1);
697     while (c != '>' && c != -1) {
698     buf_appendc(line, c);
699     c = buf_getc(line);
700     }
701     if (c == '>' && (auth == POP3_ANY || auth == POP3_APOP)) {
702     buf_appendc(line, c);
703     buf_appends(line, pass);
704     digest_md5(line, line);
705     id_encode(line->data, md);
706     buf_setf(line, "APOP %s %s\r\n", user, md);
707     sock_cat(server, line);
708     sock_getline(server, line);
709     if (bufleft(line, "+"))
710     authenticated = 1;
711     else {
712     errlog(auth == POP3_APOP ? ERRORMSG : NOTICE,
713     "POP3 APOP auth at %s failed: %b\n", host, line);
714     buf_sets(line, "QUIT\r\n");
715     sock_cat(server, line);
716     closesocket(server);
717     server = pop3_open(user, host, pass, POP3_PASS);
718     goto end;
719     }
720     }
721     if (!authenticated) {
722     buf_setf(line, "USER %s\r\n", user);
723     sock_cat(server, line);
724     sock_getline(server, line);
725     if (!bufleft(line, "+"))
726     errlog(ERRORMSG, "POP3 USER command at %s failed: %b\n", host, line);
727     else {
728     buf_setf(line, "PASS %s\r\n", pass);
729     sock_cat(server, line);
730     sock_getline(server, line);
731     if (bufleft(line, "+"))
732     authenticated = 1;
733     else
734     errlog(ERRORMSG, "POP3 auth at %s failed: %b\n", host, line);
735     }
736     }
737     if (!authenticated) {
738     pop3_close(server);
739 rabbi 11 closesocket(server);
740 rabbi 1 server = INVALID_SOCKET;
741     }
742     }
743     end:
744     buf_free(line);
745     return (server);
746     }
747    
748     int pop3_close(SOCKET s)
749     {
750     BUFFER *line;
751     int ret = -1;
752    
753     line = buf_new();
754     buf_sets(line, "QUIT\r\n");
755     sock_cat(s, line);
756     sock_getline(s, line);
757     if (bufleft(line, "+")) {
758     ret = 0;
759     errlog(DEBUGINFO, "Closing POP3 connection.\n");
760     } else
761     errlog(ERRORMSG, "POP3 QUIT failed:\n", line->data);
762     buf_free(line);
763     return (ret);
764     }
765    
766     int pop3_stat(SOCKET s)
767     {
768     BUFFER *line;
769     int val = -1;
770    
771     line = buf_new();
772     buf_sets(line, "STAT\r\n");
773     sock_cat(s, line);
774     sock_getline(s, line);
775     if (bufleft(line, "+"))
776     sscanf(line->data, "+%*s %d", &val);
777     buf_free(line);
778     return (val);
779     }
780    
781     int pop3_list(SOCKET s, int n)
782     {
783     BUFFER *line;
784     int val = -1;
785    
786     line = buf_new();
787     buf_setf(line, "LIST %d\r\n", n);
788     sock_cat(s, line);
789     sock_getline(s, line);
790     if (bufleft(line, "+"))
791     sscanf(line->data, "+%*s %d", &val);
792     buf_free(line);
793     return (val);
794     }
795    
796     int pop3_dele(SOCKET s, int n)
797     {
798     BUFFER *line;
799     int ret = 0;
800    
801     line = buf_new();
802     buf_setf(line, "DELE %d\r\n", n);
803     sock_cat(s, line);
804     sock_getline(s, line);
805     if (!bufleft(line, "+"))
806     ret = -1;
807     buf_free(line);
808     return (ret);
809     }
810    
811     int pop3_retr(SOCKET s, int n, BUFFER *msg)
812     {
813     BUFFER *line;
814     int ret = -1;
815    
816     line = buf_new();
817     buf_clear(msg);
818     buf_setf(line, "RETR %d\r\n", n);
819     sock_cat(s, line);
820     sock_getline(s, line);
821     if (bufleft(line, "+")) {
822     for (;;) {
823     if (sock_getline(s, line) == -1)
824     break;
825     if (bufeq(line, ".")) {
826     ret = 0;
827     break;
828     } else if (bufleft(line, ".")) {
829     buf_append(msg, line->data + 1, line->length - 1);
830     } else
831     buf_cat(msg, line);
832     buf_nl(msg);
833     }
834     }
835     buf_free(line);
836     return (ret);
837     }
838    
839     void pop3get(void)
840     {
841     FILE *f;
842     char cfg[LINELEN], user[LINELEN], host[LINELEN], pass[LINELEN], auth[5];
843     SOCKET server;
844     BUFFER *line, *msg;
845     int i = 0, num = 0;
846    
847     line = buf_new();
848     msg = buf_new();
849     f = mix_openfile(POP3CONF, "r");
850     if (f != NULL)
851     while (fgets(cfg, sizeof(cfg), f) != NULL) {
852 weaselp 173 if (cfg[0] == '#')
853 weaselp 332 continue;
854 rabbi 1 if (strchr(cfg, '@'))
855     strchr(cfg, '@')[0] = ' ';
856     if (sscanf(cfg, "%127s %127s %127s %4s", user, host, pass, auth) < 3)
857     continue;
858     i = POP3_ANY;
859     if (strileft(auth, "apop"))
860     i = POP3_APOP;
861     if (strileft(auth, "pass"))
862     i = POP3_PASS;
863     server = pop3_open(user, host, pass, i);
864     if (server != INVALID_SOCKET) {
865     num = pop3_stat(server);
866     if (num < 0)
867     errlog(WARNING, "POP3 protocol error at %s.\n", host);
868     else if (num == 0)
869     errlog(DEBUGINFO, "No mail at %s.\n", host);
870     else
871     for (i = 1; i <= num; i++) {
872     if (POP3SIZELIMIT > 0 &&
873     pop3_list(server, i) > POP3SIZELIMIT * 1024) {
874     errlog(WARNING, "Over size message on %s.", host);
875     if (POP3DEL == 1)
876     pop3_dele(server, i);
877     } else {
878     if (pop3_retr(server, i, msg) == 0 &&
879     pool_add(msg, "inf") == 0)
880     pop3_dele(server, i);
881     else {
882     errlog(WARNING, "POP3 error while getting mail from %s.",
883     host);
884     closesocket(server);
885     goto end;
886     }
887     }
888     }
889     pop3_close(server);
890 rabbi 11 closesocket(server);
891 rabbi 1 }
892     }
893     end:
894 rabbi 11 if (f != NULL)
895     fclose(f);
896 rabbi 1 buf_free(line);
897     buf_free(msg);
898     }
899 rabbi 262 #endif /* USE_SOCK */

Properties

Name Value
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5