/[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 545 - (show annotations) (download)
Mon Jul 7 11:18:20 2003 UTC (9 years, 11 months ago) by weaselp
File MIME type: text/plain
File size: 20676 byte(s)
The 'working on the train' commit:
Don't try to send a message if there are no recipients left.
Set default max-randhops from 20 to 4.
Remix-To chain is limited by max-randhops limit as well.
Messages to more than one remailer are dropped.
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 $Id: mail.c,v 1.19 2003/07/07 11:18:20 weaselp Exp $ */
10
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 #endif /* defined(UNIX) && defined(USE_SOCK) */
25
26 #include <fcntl.h>
27 #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)
33 {
34 FILE *f = NULL, *log = NULL;
35 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 if (f)
76 fclose(f);
77 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
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 }
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)
149 {
150 /* returns: 0: ok 1: problem, try again -1: failed */
151
152 BUFFER *head, *block, *rcpt;
153 FILE *f;
154 int err = -1;
155 int rcpt_cnt = 0;
156
157 head = buf_new();
158 rcpt = buf_new();
159
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 buf_rewind(message);
176
177 /* search recipient addresses */
178 if (address == NULL) {
179 BUFFER *field, *content;
180 field = buf_new();
181 content = buf_new();
182
183 while (buf_getheader(message, field, content) == 0) {
184 if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
185 int thislinercpts = 1;
186 char *tmp = content->data;
187 while ((tmp = strchr(tmp+1, ',')))
188 thislinercpts ++;
189 rcpt_cnt += thislinercpts;
190
191 if ( rcpt->data[0] )
192 buf_appends(rcpt, ", ");
193 buf_cat(rcpt, content);
194 }
195 }
196 buf_free(field);
197 buf_free(content);
198 } else {
199 buf_set(rcpt, address);
200 rcpt_cnt = 1;
201 }
202 buf_rewind(message);
203
204 if ( ! rcpt_cnt ) {
205 errlog(NOTICE, "No recipients found.\n");
206 err = 0;
207 } else if ( rcpt_cnt > MAXRECIPIENTS ) {
208 errlog(NOTICE, "Too many recipients. Dropping message.\n");
209 err = 0;
210 } else if ( rcpt_cnt > 1 && has_more_than_one_remailer(rcpt) ) {
211 errlog(NOTICE, "Message is destined to more than one remailer. Dropping.\n");
212 err = 0;
213 } else if ( REMAIL && strcmp(REMAILERADDR, rcpt->data) == 0) {
214 buf_cat(head, message);
215 errlog(LOG, "Message loops back to us; storing in pool rather than sending it.\n");
216 err = pool_add(head, "inf");
217 } else if (SMTPRELAY[0])
218 err = smtpsend(head, message, from);
219 else if (strieq(SENDMAIL, "outfile")) {
220 char path[PATHMAX];
221 FILE *f = NULL;
222 #ifdef SHORTNAMES
223 int i;
224 for (i = 0; i < 10000; i++) {
225 snprintf(path, PATHMAX, "%s%cout%i.txt", POOLDIR, DIRSEP, i);
226 f = fopen(path, "r");
227 if (f)
228 fclose(f);
229 else
230 break;
231 }
232 f = fopen(path, "w");
233 #else /* end of SHORTNAMES */
234 static unsigned long namecounter = 0;
235 struct stat statbuf;
236 int count;
237 char hostname[64];
238
239 hostname[0] = '\0';
240 gethostname(hostname, 63);
241 hostname[63] = '\0';
242
243 /* Step 2: Stat the file. Wait for ENOENT as a response. */
244 for (count = 0;; count++) {
245 snprintf(path, PATHMAX, "%s%cout.%lu.%u_%lu.%s,S=%lu.txt",
246 POOLDIR, DIRSEP, time(NULL), getpid(), namecounter++, hostname, head->length + message->length);
247
248 if (stat(path, &statbuf) == 0)
249 errno = EEXIST;
250 else if (errno == ENOENT) { /* create the file (at least try) */
251 f = fopen(path, "w");
252 if (f != NULL)
253 break; /* we managed to open the file */
254 }
255 if (count > 5)
256 break; /* Too many retries - give up */
257 #ifdef WIN32
258 Sleep(2000); /* sleep and retry */
259 #else /* end of WIN32 */
260 sleep(2); /* sleep and retry */
261 #endif /* else not WIN32 */
262 }
263 #endif /* else not SHORTNAMES */
264 if (f != NULL) {
265 err = buf_write(head, f);
266 err = buf_write(message, f);
267 fclose(f);
268 } else
269 errlog(ERRORMSG, "Can't create %s!\n", path);
270 } else {
271 if (SENDANONMAIL[0] != '\0' && (from == NULL || streq(from, ANONNAME)))
272 f = openpipe(SENDANONMAIL);
273 else
274 f = openpipe(SENDMAIL);
275 if (f != NULL) {
276 err = buf_write(head, f);
277 err = buf_write(message, f);
278 closepipe(f);
279 }
280 }
281 if (err != 0)
282 err = 1; /* error while sending, retry later */
283 end:
284 buf_free(block);
285 buf_free(head);
286 buf_free(rcpt);
287 return (err);
288 }
289
290 /* socket communication **********************************************/
291
292 #ifdef USE_SOCK
293 #ifdef WIN32
294 WSADATA w;
295
296 int sock_init()
297 {
298 if (WSAStartup(MAKEWORD(2, 0), &w) != 0) {
299 errlog(ERRORMSG, "Unable to initialize WINSOCK.\n");
300 return 0;
301 }
302 return 1;
303 }
304
305 void sock_exit(void)
306 {
307 WSACleanup();
308 }
309 #endif /* WIN32 */
310
311 SOCKET opensocket(char *hostname, int port)
312 {
313 struct hostent *hp;
314 struct sockaddr_in server;
315 SOCKET s;
316
317 if ((hp = gethostbyname(hostname)) == NULL)
318 return (INVALID_SOCKET);
319
320 memset((char *) &server, 0, sizeof(server));
321 server.sin_family = AF_INET;
322 server.sin_addr.s_addr = *(unsigned long *) hp->h_addr;
323 server.sin_port = htons((unsigned short) port);
324
325 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
326 if (s != INVALID_SOCKET)
327 if (connect(s, (struct sockaddr *) &server, sizeof(server)) < 0) {
328 closesocket(s);
329 return (INVALID_SOCKET);
330 }
331 return (s);
332 }
333
334 #ifndef WIN32
335 int closesocket(SOCKET s)
336 {
337 return (close(s));
338 }
339 #endif /* ifndef WIN32 */
340
341 int sock_getline(SOCKET s, BUFFER *line)
342 {
343 char c;
344 int ok;
345
346 buf_clear(line);
347 while ((ok = recv(s, &c, 1, 0)) > 0) {
348 if (c == '\n')
349 break;
350 if (c != '\r')
351 buf_appendc(line, c);
352 }
353 if (ok <= 0)
354 return (-1);
355 if (line->length == 0)
356 return (1);
357 return (0);
358 }
359
360 int sock_cat(SOCKET s, BUFFER *b)
361 {
362 int p = 0, n;
363
364 do {
365 n = send(s, b->data, b->length, 0);
366 if (n < 0)
367 return (-1);
368 p += n;
369 } while (p < b->length);
370 return (0);
371 }
372 #else /* end of USE_SOCK */
373 SOCKET opensocket(char *hostname, int port)
374 {
375 return (INVALID_SOCKET);
376 }
377
378 int closesocket(SOCKET s)
379 {
380 return (INVALID_SOCKET);
381 }
382
383 int sock_getline(SOCKET s, BUFFER *line)
384 {
385 return (-1);
386 }
387
388 int sock_cat(SOCKET s, BUFFER *b)
389 {
390 return (-1);
391 }
392 #endif /* else not USE_SOCK */
393
394 /* send messages by SMTP ************************************************/
395
396 static int sock_getsmtp(SOCKET s, BUFFER *response)
397 {
398 int ret;
399 BUFFER *line;
400 line = buf_new();
401
402 buf_clear(response);
403 do {
404 ret = sock_getline(s, line);
405 buf_cat(response, line);
406 } while (line->length >= 4 && line->data[3] == '-');
407 buf_free(line);
408 return (ret);
409 }
410
411 SOCKET smtp_open(void)
412 {
413 int s = INVALID_SOCKET;
414 int esmtp = 0;
415 BUFFER *line;
416
417 #ifdef USE_SOCK
418 if (SMTPRELAY[0] != '\0')
419 s = opensocket(SMTPRELAY, 25);
420 if (s != INVALID_SOCKET) {
421 line = buf_new();
422 sock_getsmtp(s, line);
423 if (bufifind(line, "ESMTP"))
424 esmtp = 1;
425 if (line->data[0] != '2') {
426 errlog(ERRORMSG, "SMTP relay not ready. %b\n", line);
427 closesocket(s);
428 s = INVALID_SOCKET;
429 } else {
430 errlog(DEBUGINFO, "Opening SMTP connection.\n");
431 if (esmtp)
432 buf_sets(line, "EHLO ");
433 else
434 buf_sets(line, "HELO ");
435 if (HELONAME[0])
436 buf_appends(line, HELONAME);
437 else if (strchr(ENVFROM, '@'))
438 buf_appends(line, strchr(ENVFROM, '@') + 1);
439 else {
440 struct sockaddr_in sa;
441 int len = sizeof(sa);
442 struct hostent *hp;
443
444 if (getsockname(s, (struct sockaddr *) &sa, &len) == 0 &&
445 (hp = gethostbyaddr((char *) &sa.sin_addr, sizeof(sa.sin_addr),
446 AF_INET)) != NULL)
447 buf_appends(line, (char *) hp->h_name);
448 else if (strchr(REMAILERADDR, '@'))
449 buf_appends(line, strchr(REMAILERADDR, '@') + 1);
450 else
451 buf_appends(line, SHORTNAME);
452 }
453 buf_chop(line);
454 buf_appends(line, "\r\n");
455 sock_cat(s, line);
456 sock_getsmtp(s, line);
457 if (line->data[0] != '2') {
458 errlog(ERRORMSG, "SMTP relay refuses HELO: %b\n", line);
459 closesocket(s);
460 s = INVALID_SOCKET;
461 } else if (SMTPUSERNAME[0] && esmtp && bufifind(line, "AUTH") && bufifind(line, "LOGIN")) {
462 buf_sets(line, "AUTH LOGIN\r\n");
463 sock_cat(s, line);
464 sock_getsmtp(s, line);
465 if (!bufleft(line, "334")) {
466 errlog(ERRORMSG, "SMTP AUTH fails: %b\n", line);
467 goto err;
468 }
469 buf_sets(line, SMTPUSERNAME);
470 encode(line, 0);
471 buf_appends(line, "\r\n");
472 sock_cat(s, line);
473 sock_getsmtp(s, line);
474 if (!bufleft(line, "334")) {
475 errlog(ERRORMSG, "SMTP username rejected: %b\n", line);
476 goto err;
477 }
478 buf_sets(line, SMTPPASSWORD);
479 encode(line, 0);
480 buf_appends(line, "\r\n");
481 sock_cat(s, line);
482 sock_getsmtp(s, line);
483 if (!bufleft(line, "235"))
484 errlog(ERRORMSG, "SMTP authentication failed: %b\n", line);
485 }
486 }
487 err:
488 buf_free(line);
489 }
490 #endif /* USE_SOCK */
491 return (s);
492 }
493
494 int smtp_close(SOCKET s)
495 {
496 BUFFER *line;
497 int ret = -1;
498
499 #ifdef USE_SOCK
500 line = buf_new();
501 buf_sets(line, "QUIT\r\n");
502 sock_cat(s, line);
503 if (sock_getsmtp(s, line) == 0 && line->data[0] == '2') {
504 errlog(DEBUGINFO, "Closing SMTP connection.\n");
505 ret = 0;
506 } else
507 errlog(WARNING, "SMTP quit failed: %b\n", line);
508 closesocket(s);
509 buf_free(line);
510 #endif /* USE_SOCK */
511 return (ret);
512 }
513
514 int smtp_send(SOCKET relay, BUFFER *head, BUFFER *message, char *from)
515 {
516 BUFFER *rcpt, *line, *field, *content;
517 int ret = -1;
518
519 #ifdef USE_SOCK
520 line = buf_new();
521 field = buf_new();
522 content = buf_new();
523 rcpt = buf_new();
524
525 while (buf_getheader(head, field, content) == 0)
526 if (bufieq(field, "to"))
527 #ifdef BROKEN_MTA
528 if (!bufifind(rcpt, content->data))
529 /* Do not add the same recipient twice.
530 Needed for brain-dead MTAs. */
531 #endif /* BROKEN_MTA */
532 rfc822_addr(content, rcpt);
533 buf_rewind(head);
534
535 while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {
536 if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
537 #ifdef BROKEN_MTA
538 if (!bufifind(rcpt, content->data))
539 /* Do not add the same recipient twice.
540 Needed for brain-dead MTAs. */
541 #endif /* BROKEN_MTA */
542 rfc822_addr(content, rcpt);
543 }
544 if (!bufieq(field, "bcc"))
545 buf_appendheader(head, field, content);
546 }
547 buf_nl(head);
548
549 buf_clear(content);
550 if (from) {
551 buf_sets(line, from);
552 rfc822_addr(line, content);
553 buf_chop(content);
554 }
555 if (bufieq(content, REMAILERADDR) || bufieq(content, ANONADDR))
556 buf_clear(content);
557 if (content->length == 0)
558 buf_sets(content, ENVFROM[0] ? ENVFROM : ANONADDR);
559
560 buf_setf(line, "MAIL FROM:<%b>\r\n", content);
561 sock_cat(relay, line);
562 sock_getsmtp(relay, line);
563 if (!line->data[0] == '2') {
564 errlog(ERRORMSG, "SMTP relay does not accept mail: %b\n", line);
565 goto end;
566 }
567 while (buf_getline(rcpt, content) == 0) {
568 buf_setf(line, "RCPT TO:<%b>\r\n", content);
569 sock_cat(relay, line);
570 sock_getsmtp(relay, line);
571 if (bufleft(line, "421")) {
572 errlog(ERRORMSG, "SMTP relay error: %b\n", line);
573 goto end;
574 }
575 if (bufleft(line, "530")) {
576 errlog(ERRORMSG, "SMTP authentication required: %b\n", line);
577 goto end;
578 }
579 }
580
581 buf_sets(line, "DATA\r\n");
582 sock_cat(relay, line);
583 sock_getsmtp(relay, line);
584 if (!bufleft(line, "354")) {
585 errlog(WARNING, "SMTP relay does not accept message: %b\n", line);
586 goto end;
587 }
588 while (buf_getline(head, line) >= 0) {
589 buf_appends(line, "\r\n");
590 if (bufleft(line, ".")) {
591 buf_setf(content, ".%b", line);
592 buf_move(line, content);
593 }
594 sock_cat(relay, line);
595 }
596 while (buf_getline(message, line) >= 0) {
597 buf_appends(line, "\r\n");
598 if (bufleft(line, ".")) {
599 buf_setf(content, ".%b", line);
600 buf_move(line, content);
601 }
602 sock_cat(relay, line);
603 }
604 buf_sets(line, ".\r\n");
605 sock_cat(relay, line);
606 sock_getsmtp(relay, line);
607 if (bufleft(line, "2"))
608 ret = 0;
609 else
610 errlog(WARNING, "SMTP relay will not send message: %b\n", line);
611 end:
612 buf_free(line);
613 buf_free(field);
614 buf_free(content);
615 buf_free(rcpt);
616 #endif /* USE_SOCK */
617 return (ret);
618 }
619
620 static SOCKET sendmail_state = INVALID_SOCKET;
621
622 void sendmail_begin(void)
623 {
624 /* begin mail sending session */
625 if (sendmail_state == INVALID_SOCKET)
626 sendmail_state = smtp_open();
627 }
628 void sendmail_end(void)
629 {
630 /* end mail sending session */
631 if (sendmail_state != INVALID_SOCKET) {
632 smtp_close(sendmail_state);
633 sendmail_state = INVALID_SOCKET;
634 }
635 }
636
637 int smtpsend(BUFFER *head, BUFFER *message, char *from)
638 {
639 SOCKET s;
640 int ret = -1;
641
642 if (sendmail_state != INVALID_SOCKET)
643 ret = smtp_send(sendmail_state, head, message, from);
644 else {
645 s = smtp_open();
646 if (s != INVALID_SOCKET) {
647 ret = smtp_send(s, head, message, from);
648 smtp_close(s);
649 }
650 }
651 return (ret);
652 }
653
654 /* retrieve mail with POP3 **********************************************/
655 #ifdef USE_SOCK
656 int pop3_close(SOCKET s);
657
658 #define POP3_ANY 0
659 #define POP3_APOP 1
660 #define POP3_PASS 2
661
662 SOCKET pop3_open(char *user, char *host, char *pass, int auth)
663 {
664 SOCKET server = INVALID_SOCKET;
665 BUFFER *line;
666 int authenticated = 0;
667 char md[33];
668 int c;
669
670 line = buf_new();
671 server = opensocket(host, 110);
672 if (server == INVALID_SOCKET)
673 errlog(NOTICE, "Can't connect to POP3 server %s.\n", host);
674 else {
675 sock_getline(server, line);
676 if (!bufleft(line, "+")) {
677 errlog(WARNING, "No POP3 service at %s.\n", host);
678 closesocket(server);
679 server = INVALID_SOCKET;
680 }
681 }
682 if (server != INVALID_SOCKET) {
683 errlog(DEBUGINFO, "Opening POP3 connection to %s.\n", host);
684 do
685 c = buf_getc(line);
686 while (c != '<' && c != -1);
687 while (c != '>' && c != -1) {
688 buf_appendc(line, c);
689 c = buf_getc(line);
690 }
691 if (c == '>' && (auth == POP3_ANY || auth == POP3_APOP)) {
692 buf_appendc(line, c);
693 buf_appends(line, pass);
694 digest_md5(line, line);
695 id_encode(line->data, md);
696 buf_setf(line, "APOP %s %s\r\n", user, md);
697 sock_cat(server, line);
698 sock_getline(server, line);
699 if (bufleft(line, "+"))
700 authenticated = 1;
701 else {
702 errlog(auth == POP3_APOP ? ERRORMSG : NOTICE,
703 "POP3 APOP auth at %s failed: %b\n", host, line);
704 buf_sets(line, "QUIT\r\n");
705 sock_cat(server, line);
706 closesocket(server);
707 server = pop3_open(user, host, pass, POP3_PASS);
708 goto end;
709 }
710 }
711 if (!authenticated) {
712 buf_setf(line, "USER %s\r\n", user);
713 sock_cat(server, line);
714 sock_getline(server, line);
715 if (!bufleft(line, "+"))
716 errlog(ERRORMSG, "POP3 USER command at %s failed: %b\n", host, line);
717 else {
718 buf_setf(line, "PASS %s\r\n", pass);
719 sock_cat(server, line);
720 sock_getline(server, line);
721 if (bufleft(line, "+"))
722 authenticated = 1;
723 else
724 errlog(ERRORMSG, "POP3 auth at %s failed: %b\n", host, line);
725 }
726 }
727 if (!authenticated) {
728 pop3_close(server);
729 closesocket(server);
730 server = INVALID_SOCKET;
731 }
732 }
733 end:
734 buf_free(line);
735 return (server);
736 }
737
738 int pop3_close(SOCKET s)
739 {
740 BUFFER *line;
741 int ret = -1;
742
743 line = buf_new();
744 buf_sets(line, "QUIT\r\n");
745 sock_cat(s, line);
746 sock_getline(s, line);
747 if (bufleft(line, "+")) {
748 ret = 0;
749 errlog(DEBUGINFO, "Closing POP3 connection.\n");
750 } else
751 errlog(ERRORMSG, "POP3 QUIT failed:\n", line->data);
752 buf_free(line);
753 return (ret);
754 }
755
756 int pop3_stat(SOCKET s)
757 {
758 BUFFER *line;
759 int val = -1;
760
761 line = buf_new();
762 buf_sets(line, "STAT\r\n");
763 sock_cat(s, line);
764 sock_getline(s, line);
765 if (bufleft(line, "+"))
766 sscanf(line->data, "+%*s %d", &val);
767 buf_free(line);
768 return (val);
769 }
770
771 int pop3_list(SOCKET s, int n)
772 {
773 BUFFER *line;
774 int val = -1;
775
776 line = buf_new();
777 buf_setf(line, "LIST %d\r\n", n);
778 sock_cat(s, line);
779 sock_getline(s, line);
780 if (bufleft(line, "+"))
781 sscanf(line->data, "+%*s %d", &val);
782 buf_free(line);
783 return (val);
784 }
785
786 int pop3_dele(SOCKET s, int n)
787 {
788 BUFFER *line;
789 int ret = 0;
790
791 line = buf_new();
792 buf_setf(line, "DELE %d\r\n", n);
793 sock_cat(s, line);
794 sock_getline(s, line);
795 if (!bufleft(line, "+"))
796 ret = -1;
797 buf_free(line);
798 return (ret);
799 }
800
801 int pop3_retr(SOCKET s, int n, BUFFER *msg)
802 {
803 BUFFER *line;
804 int ret = -1;
805
806 line = buf_new();
807 buf_clear(msg);
808 buf_setf(line, "RETR %d\r\n", n);
809 sock_cat(s, line);
810 sock_getline(s, line);
811 if (bufleft(line, "+")) {
812 for (;;) {
813 if (sock_getline(s, line) == -1)
814 break;
815 if (bufeq(line, ".")) {
816 ret = 0;
817 break;
818 } else if (bufleft(line, ".")) {
819 buf_append(msg, line->data + 1, line->length - 1);
820 } else
821 buf_cat(msg, line);
822 buf_nl(msg);
823 }
824 }
825 buf_free(line);
826 return (ret);
827 }
828
829 void pop3get(void)
830 {
831 FILE *f;
832 char cfg[LINELEN], user[LINELEN], host[LINELEN], pass[LINELEN], auth[5];
833 SOCKET server;
834 BUFFER *line, *msg;
835 int i = 0, num = 0;
836
837 line = buf_new();
838 msg = buf_new();
839 f = mix_openfile(POP3CONF, "r");
840 if (f != NULL)
841 while (fgets(cfg, sizeof(cfg), f) != NULL) {
842 if (cfg[0] == '#')
843 continue;
844 if (strchr(cfg, '@'))
845 strchr(cfg, '@')[0] = ' ';
846 if (sscanf(cfg, "%127s %127s %127s %4s", user, host, pass, auth) < 3)
847 continue;
848 i = POP3_ANY;
849 if (strileft(auth, "apop"))
850 i = POP3_APOP;
851 if (strileft(auth, "pass"))
852 i = POP3_PASS;
853 server = pop3_open(user, host, pass, i);
854 if (server != INVALID_SOCKET) {
855 num = pop3_stat(server);
856 if (num < 0)
857 errlog(WARNING, "POP3 protocol error at %s.\n", host);
858 else if (num == 0)
859 errlog(DEBUGINFO, "No mail at %s.\n", host);
860 else
861 for (i = 1; i <= num; i++) {
862 if (POP3SIZELIMIT > 0 &&
863 pop3_list(server, i) > POP3SIZELIMIT * 1024) {
864 errlog(WARNING, "Over size message on %s.", host);
865 if (POP3DEL == 1)
866 pop3_dele(server, i);
867 } else {
868 if (pop3_retr(server, i, msg) == 0 &&
869 pool_add(msg, "inf") == 0)
870 pop3_dele(server, i);
871 else {
872 errlog(WARNING, "POP3 error while getting mail from %s.",
873 host);
874 closesocket(server);
875 goto end;
876 }
877 }
878 }
879 pop3_close(server);
880 closesocket(server);
881 }
882 }
883 end:
884 if (f != NULL)
885 fclose(f);
886 buf_free(line);
887 buf_free(msg);
888 }
889 #endif /* USE_SOCK */

  ViewVC Help
Powered by ViewVC 1.1.5