9 |
#include "data.h" |
#include "data.h" |
10 |
|
|
11 |
|
|
12 |
extern int sockpri, sockaux; |
extern conn_t connpri, connaux; |
13 |
extern unsigned int options; |
extern unsigned int options; |
14 |
extern char charset[CHARSET_LEN]; |
extern char charset[CHARSET_LEN]; |
|
extern unsigned int capspri, capsaux; |
|
|
|
|
|
namesp_t nsppri, nspaux; /* Primary and auxiliary namespace. */ |
|
15 |
|
|
16 |
|
|
17 |
#ifdef DEBUG |
#ifdef DEBUG |
19 |
* Test/ping server. |
* Test/ping server. |
20 |
*/ |
*/ |
21 |
int |
int |
22 |
test(int *sock) |
test(conn_t * conn) |
23 |
{ |
{ |
24 |
return server_response(sock, imap_noop(sock)); |
return server_response(conn, imap_noop(conn)); |
25 |
} |
} |
26 |
|
|
27 |
#endif |
#endif |
31 |
* Check server's capabilities. |
* Check server's capabilities. |
32 |
*/ |
*/ |
33 |
int |
int |
34 |
check_capabilities(int *sock) |
check_capabilities(conn_t * conn) |
35 |
{ |
{ |
36 |
if (sock == &sockpri) |
conn->caps = CAPABILITY_NONE; |
|
capspri = CAPABILITY_NONE; |
|
|
else |
|
|
capsaux = CAPABILITY_NONE; |
|
37 |
|
|
38 |
return capability_response(sock, imap_capability(sock)); |
return capability_response(conn, imap_capability(conn)); |
39 |
} |
} |
40 |
|
|
41 |
|
|
43 |
* Get namespace of mail server's mailboxes. |
* Get namespace of mail server's mailboxes. |
44 |
*/ |
*/ |
45 |
int |
int |
46 |
check_namespace(int *sock, namesp_t * nsp) |
check_namespace(conn_t * conn) |
47 |
{ |
{ |
48 |
unsigned int *caps; |
conn->nsp.prefix[0] = conn->nsp.delim = '\0'; |
|
|
|
|
caps = (sock == &sockpri ? &capspri : &capsaux); |
|
|
nsp->prefix[0] = nsp->delim = '\0'; |
|
49 |
|
|
50 |
if (!(options & OPTION_NAMESPACE) || |
if (!(options & OPTION_NAMESPACE) || |
51 |
!(*caps & CAPABILITY_NAMESPACE)) |
!(conn->caps & CAPABILITY_NAMESPACE)) |
52 |
return 0; |
return 0; |
53 |
else |
else |
54 |
return namespace_response(sock, imap_namespace(sock), nsp); |
return namespace_response(conn, imap_namespace(conn)); |
55 |
} |
} |
56 |
|
|
57 |
|
|
60 |
* Begin TLS negotiation (STARTTLS). |
* Begin TLS negotiation (STARTTLS). |
61 |
*/ |
*/ |
62 |
int |
int |
63 |
imf_starttls(int *sock) |
imf_starttls(conn_t * conn) |
64 |
{ |
{ |
65 |
int r; |
int r; |
66 |
|
|
67 |
r = server_response(sock, imap_starttls(sock)); |
r = server_response(conn, imap_starttls(conn)); |
68 |
imf_ssl_init(sock, SSL_TLS_V1); |
imf_ssl_init(conn, SSL_TLS_V1); |
69 |
|
|
70 |
return r; |
return r; |
71 |
} |
} |
77 |
* Login to server. |
* Login to server. |
78 |
*/ |
*/ |
79 |
int |
int |
80 |
login(int *sock, char *user, char *pass) |
login(conn_t * conn, char *user, char *pass) |
81 |
{ |
{ |
82 |
return server_response(sock, imap_login(sock, user, pass)); |
return server_response(conn, imap_login(conn, user, pass)); |
83 |
} |
} |
84 |
|
|
85 |
|
|
88 |
* Check if a mailbox exists. |
* Check if a mailbox exists. |
89 |
*/ |
*/ |
90 |
int |
int |
91 |
check_mailbox(int *sock, char *mbox) |
check_mailbox(conn_t * conn, char *mbox) |
92 |
{ |
{ |
93 |
return server_response(sock, imap_status(sock, mbox, "MESSAGES")); |
return server_response(conn, imap_status(conn, mbox, "MESSAGES")); |
94 |
} |
} |
95 |
|
|
96 |
|
|
98 |
* Open mailbox in read-write mode. |
* Open mailbox in read-write mode. |
99 |
*/ |
*/ |
100 |
int |
int |
101 |
select_mailbox(int *sock, char *mbox, namesp_t * nsp) |
select_mailbox(conn_t * conn, char *mbox) |
102 |
{ |
{ |
103 |
int r; |
int r; |
104 |
|
|
105 |
if (mailbox_status(sock, mbox, nsp) == -2) |
if (mailbox_status(conn, mbox) == -2) |
106 |
return -2; /* No messages exist. No filters need to be |
return -2; /* No messages exist. No filters need to be |
107 |
* applied. */ |
* applied. */ |
108 |
|
|
109 |
r = select_response(sock, imap_select(sock, |
r = select_response(conn, imap_select(conn, |
110 |
apply_namespace(mbox, nsp->prefix, |
apply_namespace(mbox, conn->nsp.prefix, conn->nsp.delim))); |
|
nsp->delim))); |
|
111 |
|
|
112 |
log_info(LOG_MAILBOX, mbox); |
log_info(LOG_MAILBOX, mbox); |
113 |
|
|
119 |
* Get mailbox's status. |
* Get mailbox's status. |
120 |
*/ |
*/ |
121 |
int |
int |
122 |
mailbox_status(int *sock, char *mbox, namesp_t * nsp) |
mailbox_status(conn_t * conn, char *mbox) |
123 |
{ |
{ |
124 |
return status_response(sock, imap_status(sock, |
return status_response(conn, imap_status(conn, |
125 |
apply_namespace(mbox, nsp->prefix, nsp->delim), |
apply_namespace(mbox, conn->nsp.prefix, conn->nsp.delim), |
126 |
"MESSAGES RECENT UNSEEN"), mbox); |
"MESSAGES RECENT UNSEEN"), mbox); |
127 |
} |
} |
128 |
|
|
131 |
* Close examined/selected mailbox. |
* Close examined/selected mailbox. |
132 |
*/ |
*/ |
133 |
int |
int |
134 |
close_mailbox(int *sock) |
close_mailbox(conn_t * conn) |
135 |
{ |
{ |
136 |
return server_response(sock, imap_close(sock)); |
return server_response(conn, imap_close(conn)); |
137 |
} |
} |
138 |
|
|
139 |
|
|
141 |
* Logout from server. |
* Logout from server. |
142 |
*/ |
*/ |
143 |
int |
int |
144 |
logout(int *sock) |
logout(conn_t * conn) |
145 |
{ |
{ |
146 |
return logout_response(sock, imap_logout(sock)); |
return logout_response(conn, imap_logout(conn)); |
147 |
} |
} |
148 |
|
|
149 |
|
|
191 |
search = generate_filter_and(filter->masks, filter->masknum, |
search = generate_filter_and(filter->masks, filter->masknum, |
192 |
filter->masklen); |
filter->masklen); |
193 |
|
|
194 |
search_response(&sockpri, imap_search(&sockpri, charset, search), |
search_response(&connpri, imap_search(&connpri, charset, search), |
195 |
mesgs); |
mesgs); |
196 |
|
|
197 |
xfree(search); |
xfree(search); |
420 |
info("%d message%s copied from \"%s\" to mailbox \"%s\".\n", |
info("%d message%s copied from \"%s\" to mailbox \"%s\".\n", |
421 |
cnt, plural(cnt), mbox, destmbox); |
cnt, plural(cnt), mbox, destmbox); |
422 |
action_copy(mbox, mesgs, apply_namespace(destmbox, |
action_copy(mbox, mesgs, apply_namespace(destmbox, |
423 |
nsppri.prefix, nsppri.delim), args); |
connpri.nsp.prefix, connpri.nsp.delim), args); |
424 |
break; |
break; |
425 |
case FILTER_ACTION_MOVE: |
case FILTER_ACTION_MOVE: |
426 |
info("%d message%s moved from \"%s\" to mailbox \"%s\".\n", |
info("%d message%s moved from \"%s\" to mailbox \"%s\".\n", |
427 |
cnt, plural(cnt), mbox, destmbox); |
cnt, plural(cnt), mbox, destmbox); |
428 |
action_move(mbox, mesgs, apply_namespace(destmbox, |
action_move(mbox, mesgs, apply_namespace(destmbox, |
429 |
nsppri.prefix, nsppri.delim), args); |
connpri.nsp.prefix, connpri.nsp.delim), args); |
430 |
break; |
break; |
431 |
case FILTER_ACTION_RCOPY: |
case FILTER_ACTION_RCOPY: |
432 |
info("%d message%s copied from \"%s\" to mailbox " |
info("%d message%s copied from \"%s\" to mailbox " |
473 |
|
|
474 |
tok = strtok_r(m, " ", &m); |
tok = strtok_r(m, " ", &m); |
475 |
while (tok) { |
while (tok) { |
476 |
server_response(&sockpri, imap_store(&sockpri, tok, |
server_response(&connpri, imap_store(&connpri, tok, |
477 |
STORE_FLAG_ADD, "\\Deleted")); |
STORE_FLAG_ADD, "\\Deleted")); |
478 |
|
|
479 |
tok = strtok_r(NULL, " ", &m); |
tok = strtok_r(NULL, " ", &m); |
480 |
} |
} |
481 |
|
|
482 |
if (options & OPTION_EXPUNGE) |
if (options & OPTION_EXPUNGE) |
483 |
server_response(&sockpri, imap_expunge(&sockpri)); |
server_response(&connpri, imap_expunge(&connpri)); |
484 |
|
|
485 |
xfree(mcp); |
xfree(mcp); |
486 |
|
|
516 |
xstrncpy(dm[1], dm[0], MBOX_NAME_LEN - 1); |
xstrncpy(dm[1], dm[0], MBOX_NAME_LEN - 1); |
517 |
message_date(tok, dm[1]); |
message_date(tok, dm[1]); |
518 |
|
|
519 |
if ((r = copy_response(&sockpri, imap_copy(&sockpri, tok, |
if ((r = copy_response(&connpri, imap_copy(&connpri, tok, |
520 |
dm[1]))) == RESPONSE_TRYCREATE) |
dm[1]))) == RESPONSE_TRYCREATE) |
521 |
if (!server_response(&sockpri, imap_create(&sockpri, |
if (!server_response(&connpri, imap_create(&connpri, |
522 |
dm[1]))) { |
dm[1]))) { |
523 |
if ((options & OPTION_SUBSCRIBE)) |
if ((options & OPTION_SUBSCRIBE)) |
524 |
server_response(&sockpri, |
server_response(&connpri, |
525 |
imap_subscribe(&sockpri, dm[1])); |
imap_subscribe(&connpri, dm[1])); |
526 |
r = copy_response(&sockpri, |
r = copy_response(&connpri, |
527 |
imap_copy(&sockpri, tok, dm[1])); |
imap_copy(&connpri, tok, dm[1])); |
528 |
} |
} |
529 |
tok = strtok_r(NULL, " ", &m); |
tok = strtok_r(NULL, " ", &m); |
530 |
} |
} |
563 |
|
|
564 |
*dm[0] = *dm[1] = *dm[2] = '\0'; |
*dm[0] = *dm[1] = *dm[2] = '\0'; |
565 |
|
|
566 |
if (init_connection(&sockaux, destacc->server, destacc->port, |
if (init_connection(&connaux, destacc->server, destacc->port, |
567 |
destacc->ssl)) |
destacc->ssl)) |
568 |
return ERROR_NETWORK; |
return ERROR_NETWORK; |
569 |
|
|
570 |
r = greeting_response(&sockaux); |
r = greeting_response(&connaux); |
571 |
|
|
572 |
#ifdef DEBUG |
#ifdef DEBUG |
573 |
test(&sockaux); |
test(&connaux); |
574 |
#endif |
#endif |
575 |
|
|
576 |
if (r == RESPONSE_BYE || check_capabilities(&sockaux)) |
if (r == RESPONSE_BYE || check_capabilities(&connaux)) |
577 |
return ERROR_NETWORK; |
return ERROR_NETWORK; |
578 |
|
|
579 |
#ifdef SSL_TLS |
#ifdef SSL_TLS |
580 |
if (destacc->ssl == SSL_DISABLED && capsaux & CAPABILITY_STARTTLS) |
if (destacc->ssl == SSL_DISABLED && connaux.caps & CAPABILITY_STARTTLS) |
581 |
if (imf_starttls(&sockaux) == RESPONSE_OK) |
if (imf_starttls(&connaux) == RESPONSE_OK) |
582 |
check_capabilities(&sockaux); |
check_capabilities(&connaux); |
583 |
#endif |
#endif |
584 |
|
|
585 |
if (r != RESPONSE_PREAUTH) { |
if (r != RESPONSE_PREAUTH) { |
590 |
destacc->passwdattr = PASSWORD_PLAIN; |
destacc->passwdattr = PASSWORD_PLAIN; |
591 |
} |
} |
592 |
#ifdef CRAM_MD5 |
#ifdef CRAM_MD5 |
593 |
if (capsaux & CAPABILITY_AUTH_CRAM_MD5) |
if (connaux.caps & CAPABILITY_AUTH_CRAM_MD5) |
594 |
r = imf_cram_md5(&sockaux, destacc->username, |
r = imf_cram_md5(&connaux, destacc->username, |
595 |
destacc->password); |
destacc->password); |
596 |
else |
else |
597 |
#endif |
#endif |
598 |
r = login(&sockaux, destacc->username, |
r = login(&connaux, destacc->username, |
599 |
destacc->password); |
destacc->password); |
600 |
|
|
601 |
if (r == RESPONSE_NO) { |
if (r == RESPONSE_NO) { |
604 |
return ERROR_NETWORK; |
return ERROR_NETWORK; |
605 |
} |
} |
606 |
} |
} |
607 |
check_namespace(&sockaux, &nspaux); |
check_namespace(&connaux); |
608 |
|
|
609 |
m = mcp = xstrdup(mesgs); |
m = mcp = xstrdup(mesgs); |
610 |
|
|
617 |
message_date(tok, dm[2]); |
message_date(tok, dm[2]); |
618 |
|
|
619 |
/* apply_namespace() returns a pointer to a static buffer. */ |
/* apply_namespace() returns a pointer to a static buffer. */ |
620 |
ndm = apply_namespace(dm[2], nspaux.prefix, nspaux.delim); |
ndm = apply_namespace(dm[2], connaux.nsp.prefix, |
621 |
|
connaux.nsp.delim); |
622 |
|
|
623 |
/* Check only if mailbox name is different from last one. */ |
/* Check only if mailbox name is different from last one. */ |
624 |
if (strncmp(dm[0], dm[2], strlen(dm[2]))) { |
if (strncmp(dm[0], dm[2], strlen(dm[2]))) { |
625 |
r = check_mailbox(&sockaux, ndm); |
r = check_mailbox(&connaux, ndm); |
626 |
if (r == RESPONSE_NO) { |
if (r == RESPONSE_NO) { |
627 |
server_response(&sockaux, |
server_response(&connaux, |
628 |
imap_create(&sockaux, ndm)); |
imap_create(&connaux, ndm)); |
629 |
if ((options & OPTION_SUBSCRIBE)) |
if ((options & OPTION_SUBSCRIBE)) |
630 |
server_response(&sockaux, |
server_response(&connaux, |
631 |
imap_subscribe(&sockaux, ndm)); |
imap_subscribe(&connaux, ndm)); |
632 |
} |
} |
633 |
} |
} |
634 |
xstrncpy(dm[0], dm[2], MBOX_NAME_LEN - 1); |
xstrncpy(dm[0], dm[2], MBOX_NAME_LEN - 1); |
635 |
|
|
636 |
fetchsize_response(&sockpri, &n, |
fetchsize_response(&connpri, &n, |
637 |
imap_fetch(&sockpri, tok, "RFC822.SIZE")); |
imap_fetch(&connpri, tok, "RFC822.SIZE")); |
638 |
|
|
639 |
ta = imap_append(&sockaux, ndm, n); |
ta = imap_append(&connaux, ndm, n); |
640 |
|
|
641 |
fetch_response(&sockpri, 0, 1, NULL); |
fetch_response(&connpri, 0, 1, NULL); |
642 |
tf = imap_fetch(&sockpri, tok, "RFC822.HEADER"); |
tf = imap_fetch(&connpri, tok, "RFC822.HEADER"); |
643 |
do { |
do { |
644 |
r = fetch_response(&sockpri, tf, 0, buf); |
r = fetch_response(&connpri, tf, 0, buf); |
645 |
socket_write(&sockaux, buf); |
socket_write(&connaux, buf); |
646 |
} while (r == RESPONSE_NONE); |
} while (r == RESPONSE_NONE); |
647 |
|
|
648 |
socket_write(&sockaux, "\r\n"); |
socket_write(&connaux, "\r\n"); |
649 |
|
|
650 |
fetch_response(&sockpri, 0, 1, NULL); |
fetch_response(&connpri, 0, 1, NULL); |
651 |
tf = imap_fetch(&sockpri, tok, "BODY[TEXT]"); |
tf = imap_fetch(&connpri, tok, "BODY[TEXT]"); |
652 |
do { |
do { |
653 |
r = fetch_response(&sockpri, tf, 0, buf); |
r = fetch_response(&connpri, tf, 0, buf); |
654 |
if (r != RESPONSE_NULLBODY) |
if (r != RESPONSE_NULLBODY) |
655 |
socket_write(&sockaux, buf); |
socket_write(&connaux, buf); |
656 |
} while (r == RESPONSE_NONE); |
} while (r == RESPONSE_NONE); |
657 |
|
|
658 |
if (r != RESPONSE_NULLBODY) |
if (r != RESPONSE_NULLBODY) |
659 |
socket_write(&sockaux, "\r\n\r\n"); |
socket_write(&connaux, "\r\n\r\n"); |
660 |
else |
else |
661 |
socket_write(&sockaux, "\r\n"); |
socket_write(&connaux, "\r\n"); |
662 |
|
|
663 |
append_response(&sockaux, ta); |
append_response(&connaux, ta); |
664 |
|
|
665 |
tok = strtok_r(NULL, " ", &m); |
tok = strtok_r(NULL, " ", &m); |
666 |
} |
} |
667 |
|
|
668 |
logout(&sockaux); |
logout(&connaux); |
669 |
|
|
670 |
action_list(mesgs, args); |
action_list(mesgs, args); |
671 |
|
|
736 |
|
|
737 |
tok = strtok_r(m, " ", &m); |
tok = strtok_r(m, " ", &m); |
738 |
while (tok != NULL) { |
while (tok != NULL) { |
739 |
server_response(&sockpri, imap_store(&sockpri, tok, t, s)); |
server_response(&connpri, imap_store(&connpri, tok, t, s)); |
740 |
|
|
741 |
tok = strtok_r(NULL, " ", &m); |
tok = strtok_r(NULL, " ", &m); |
742 |
} |
} |
743 |
|
|
744 |
if (options & OPTION_EXPUNGE) |
if (options & OPTION_EXPUNGE) |
745 |
server_response(&sockpri, imap_expunge(&sockpri)); |
server_response(&connpri, imap_expunge(&connpri)); |
746 |
|
|
747 |
xfree(mcp); |
xfree(mcp); |
748 |
|
|
770 |
tok = strtok_r(m, " ", &m); |
tok = strtok_r(m, " ", &m); |
771 |
while (tok != NULL) { |
while (tok != NULL) { |
772 |
/* Reset internal fetch counter. */ |
/* Reset internal fetch counter. */ |
773 |
fetch_response(&sockpri, 0, 1, NULL); |
fetch_response(&connpri, 0, 1, NULL); |
774 |
t = imap_fetch(&sockpri, tok, s); |
t = imap_fetch(&connpri, tok, s); |
775 |
|
|
776 |
log_info(LOG_PREAMBLE, NULL); |
log_info(LOG_PREAMBLE, NULL); |
777 |
do { |
do { |
778 |
r = fetch_response(&sockpri, t, 0, hdrs); |
r = fetch_response(&connpri, t, 0, hdrs); |
779 |
|
|
780 |
if (*hdrs != '\0') { |
if (*hdrs != '\0') { |
781 |
if (options & OPTION_HEADERS) |
if (options & OPTION_HEADERS) |
945 |
|
|
946 |
substitute_date(destmbox); |
substitute_date(destmbox); |
947 |
|
|
948 |
fetch_response(&sockpri, 0, 1, NULL); |
fetch_response(&connpri, 0, 1, NULL); |
949 |
t = imap_fetch(&sockpri, mesg, "BODY.PEEK[HEADER.FIELDS (DATE)]"); |
t = imap_fetch(&connpri, mesg, "BODY.PEEK[HEADER.FIELDS (DATE)]"); |
950 |
|
|
951 |
while (fetch_response(&sockpri, t, 0, dbuf) == RESPONSE_NONE); |
while (fetch_response(&connpri, t, 0, dbuf) == RESPONSE_NONE); |
952 |
|
|
953 |
if (strptime(dbuf, "Date: %a, %d %b %Y %H:%M:%S", &tl) && |
if (strptime(dbuf, "Date: %a, %d %b %Y %H:%M:%S", &tl) && |
954 |
strftime(s, MBOX_NAME_LEN - 1, destmbox, &tl)) |
strftime(s, MBOX_NAME_LEN - 1, destmbox, &tl)) |