/[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 710 - (show annotations) (download)
Wed Jan 21 00:47:21 2004 UTC (9 years, 5 months ago) by rabbi
File MIME type: text/plain
File size: 20873 byte(s)
Updated copyright dates, doc issues, misc fixes.
1 /* Mixmaster version 3.0 -- (C) 1999 - 2004 Anonymizer Inc. and others.
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$ */
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;
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 if (PRECEDENCE[0])
176 buf_appendf(head, "Precedence: %s\n", PRECEDENCE);
177
178 buf_rewind(message);
179
180 /* 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);
229 else if (strieq(SENDMAIL, "outfile")) {
230 char path[PATHMAX];
231 FILE *f = NULL;
232 #ifdef SHORTNAMES
233 int i;
234 for (i = 0; i < 10000; i++) {
235 snprintf(path, PATHMAX, "%s%cout%i.txt", POOLDIR, DIRSEP, i);
236 f = fopen(path, "r");
237 if (f)
238 fclose(f);
239 else
240 break;
241 }
242 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) {
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 buf_free(rcpt);
297 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 #endif /* WIN32 */
320
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 #endif /* ifndef WIN32 */
350
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 #else /* end of USE_SOCK */
383 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 #endif /* else not USE_SOCK */
403
404 /* send messages by SMTP ************************************************/
405
406 static int sock_getsmtp(SOCKET s, BUFFER *response)
407 {
408 int ret;
409 BUFFER *line;
410 line = buf_new();
411
412 buf_clear(response);
413 do {
414 ret = sock_getline(s, line);
415 buf_cat(response, line);
416 } while (line->length >= 4 && line->data[3] == '-');
417 buf_free(line);
418 return (ret);
419 }
420
421 SOCKET smtp_open(void)
422 {
423 int s = INVALID_SOCKET;
424 int esmtp = 0;
425 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 if (bufifind(line, "ESMTP"))
434 esmtp = 1;
435 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 if (esmtp)
442 buf_sets(line, "EHLO ");
443 else
444 buf_sets(line, "HELO ");
445 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 buf_chop(line);
464 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 } 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);
499 }
500 #endif /* USE_SOCK */
501 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 #endif /* USE_SOCK */
521 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 #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 buf_rewind(head);
544
545 while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {
546 if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
547 #ifdef BROKEN_MTA
548 if (!bufifind(rcpt, content->data))
549 /* Do not add the same recipient twice.
550 Needed for brain-dead MTAs. */
551 #endif /* BROKEN_MTA */
552 rfc822_addr(content, rcpt);
553 }
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 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");
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 #endif /* USE_SOCK */
627 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 char md[33];
678 int c;
679
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 server = INVALID_SOCKET;
690 }
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 closesocket(server);
740 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 if (cfg[0] == '#')
853 continue;
854 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 closesocket(server);
891 }
892 }
893 end:
894 if (f != NULL)
895 fclose(f);
896 buf_free(line);
897 buf_free(msg);
898 }
899 #endif /* USE_SOCK */

Properties

Name Value
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5