Aggregation of remote POP3 accounts is now working.
authorArt Cancro <ajc@citadel.org>
Tue, 18 Sep 2007 21:38:15 +0000 (21:38 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 18 Sep 2007 21:38:15 +0000 (21:38 +0000)
You can use it by declaring -DPOP3_AGGREGATION in your CFLAGS, and
then manually editing the netconfigs file for a room (typically
an inbox) with a line like:
pop3client|popserver.host.com|username|password
Client configuration screens will follow.

12 files changed:
citadel/clientsocket.c
citadel/clientsocket.h
citadel/control.c
citadel/modules/calendar/serv_calendar.c
citadel/modules/funambol/serv_funambol.c
citadel/modules/network/serv_network.c
citadel/modules/pop3client/serv_pop3client.c
citadel/modules/sieve/serv_sieve.c
citadel/modules/smtp/serv_smtp.c
citadel/modules/spam/serv_spam.c
citadel/msgbase.c
citadel/msgbase.h

index a1c93a251309c661ef6699b4eb779b2145ba0d9e..eef8a3563a28213c8ca3ad970d5c8e98c176c55c 100644 (file)
@@ -189,7 +189,7 @@ int sock_write(int sock, char *buf, int nbytes)
  * Input string from socket - implemented in terms of sock_read()
  * 
  */
-int sock_gets(int sock, char *buf)
+int sock_getln(int sock, char *buf, int bufsize)
 {
        int i;
 
@@ -197,13 +197,13 @@ int sock_gets(int sock, char *buf)
         */
        for (i = 0;; i++) {
                if (sock_read(sock, &buf[i], 1) < 0) return(-1);
-               if (buf[i] == '\n' || i == (SIZ-1))
+               if (buf[i] == '\n' || i == (bufsize-1))
                        break;
        }
 
        /* If we got a long line, discard characters until the newline.
         */
-       if (i == (SIZ-1))
+       if (i == (bufsize-1))
                while (buf[i] != '\n')
                        if (sock_read(sock, &buf[i], 1) < 0) return(-1);
 
@@ -227,12 +227,12 @@ int ml_sock_gets(int sock, char *buf) {
        char bigbuf[1024];
        int g;
 
-       g = sock_gets(sock, buf);
+       g = sock_getln(sock, buf, SIZ);
        if (g < 4) return(g);
        if (buf[3] != '-') return(g);
 
        do {
-               g = sock_gets(sock, bigbuf);
+               g = sock_getln(sock, bigbuf, SIZ);
                if (g < 0) return(g);
        } while ( (g >= 4) && (bigbuf[3] == '-') );
 
index 1fdbcb1af2b5eac66f38f060494fceafb75588cc..0e5a6ecb4cc5eca53256b2f64205bfb22ba85efc 100644 (file)
@@ -9,7 +9,7 @@ int sock_read_to(int sock, char *buf, int bytes, int timeout);
 int sock_read(int sock, char *buf, int bytes);
 int sock_write(int sock, char *buf, int nbytes);
 int ml_sock_gets(int sock, char *buf);
-int sock_gets(int sock, char *buf);
+int sock_getln(int sock, char *buf, int bufsize);
 int sock_puts(int sock, char *buf);
 
 
index 7dc74798b5b8664c710a293576f1b31020db7f0f..710c38d63035bc9d13039b480725f121fbc9cd54 100644 (file)
@@ -540,8 +540,7 @@ void cmd_conf(char *argbuf)
                extract_token(confname, argbuf, 1, '|', sizeof confname);
                unbuffer_output();
                cprintf("%d %s\n", SEND_LISTING, confname);
-               confptr = CtdlReadMessageBody("000",
-                               config.c_maxmsglen, NULL, 0);
+               confptr = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0);
                CtdlPutSysConfig(confname, confptr);
                free(confptr);
        }
index 2809ddc96830878f72ad74a74cf42e7546be55de..05fe7d9947e45aa5c9c5d5427138966730b7f547 100644 (file)
@@ -1457,7 +1457,7 @@ void ical_putics(void)
        }
 
        cprintf("%d Transmit data now\n", SEND_LISTING);
-        calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0);
+        calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0);
        if (calstream == NULL) {
                return;
        }
index 3ea21710509be11ca107bc9611d2094e3b0f677f..309e33464c57180b3388b1bf781e13f1c6191776 100644 (file)
@@ -202,7 +202,7 @@ void notify_funambol(long msgnum, void *userdata) {
        
        /* Response */
        lprintf(CTDL_DEBUG, "Awaiting response\n");
-        if (sock_gets(sock, buf) < 0) {
+        if (sock_getln(sock, buf, sizeof buf) < 0) {
                 goto bail;
         }
         lprintf(CTDL_DEBUG, "<%s\n", buf);
index 29ad8379bdf78ef1045f23b98f7e08bebb78e189..8e8847546ec5e2b8ca42da5689588894194cd8c3 100644 (file)
@@ -1655,7 +1655,7 @@ void receive_spool(int sock, char *remote_nodename) {
 
        CtdlMakeTempFileName(tempfilename, sizeof tempfilename);
        if (sock_puts(sock, "NDOP") < 0) return;
-       if (sock_gets(sock, buf) < 0) return;
+       if (sock_getln(sock, buf, sizeof buf) < 0) return;
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (buf[0] != '2') {
                return;
@@ -1680,7 +1680,7 @@ void receive_spool(int sock, char *remote_nodename) {
                        unlink(tempfilename);
                        return;
                }
-               if (sock_gets(sock, buf) < 0) {
+               if (sock_getln(sock, buf, sizeof buf) < 0) {
                        fclose(fp);
                        unlink(tempfilename);
                        return;
@@ -1702,7 +1702,7 @@ void receive_spool(int sock, char *remote_nodename) {
                unlink(tempfilename);
                return;
        }
-       if (sock_gets(sock, buf) < 0) {
+       if (sock_getln(sock, buf, sizeof buf) < 0) {
                unlink(tempfilename);
                return;
        }
@@ -1736,7 +1736,7 @@ void transmit_spool(int sock, char *remote_nodename)
        char sfname[128];
 
        if (sock_puts(sock, "NUOP") < 0) return;
-       if (sock_gets(sock, buf) < 0) return;
+       if (sock_getln(sock, buf, sizeof buf) < 0) return;
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (buf[0] != '2') {
                return;
@@ -1763,7 +1763,7 @@ void transmit_spool(int sock, char *remote_nodename)
                                close(fd);
                                return;
                        }
-                       if (sock_gets(sock, buf) < 0) {
+                       if (sock_getln(sock, buf, sizeof buf) < 0) {
                                close(fd);
                                return;
                        }
@@ -1785,7 +1785,7 @@ void transmit_spool(int sock, char *remote_nodename)
 ABORTUPL:
        close(fd);
        if (sock_puts(sock, "UCLS 1") < 0) return;
-       if (sock_gets(sock, buf) < 0) return;
+       if (sock_getln(sock, buf, sizeof buf) < 0) return;
        lprintf(CTDL_NOTICE, "Sent %ld octets to <%s>\n",
                        bytes_written, remote_nodename);
        lprintf(CTDL_DEBUG, "<%s\n", buf);
@@ -1818,14 +1818,14 @@ void network_poll_node(char *node, char *secret, char *host, char *port) {
        lprintf(CTDL_DEBUG, "Connected!\n");
 
        /* Read the server greeting */
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
 
        /* Identify ourselves */
        snprintf(buf, sizeof buf, "NETP %s|%s", config.c_nodename, secret);
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (sock_puts(sock, buf) <0) goto bail;
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
        if (buf[0] != '2') goto bail;
 
index 0782894dd27ad81323fb370582b2dba16bb8e61e..449dcc95e190a33c43de4704d574c69fe3433da5 100644 (file)
@@ -29,6 +29,8 @@
 #include "room_ops.h"
 #include "ctdl_module.h"
 #include "clientsocket.h"
+#include "msgbase.h"
+#include "internet_addressing.h"
 
 struct pop3aggr {
        struct pop3aggr *next;
@@ -47,6 +49,14 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3
 {
        int sock;
        char buf[SIZ];
+       int msg_to_fetch = 0;
+       int *msglist = NULL;
+       int num_msgs = 0;
+       int alloc_msgs = 0;
+       int i;
+       char *body = NULL;
+       struct CtdlMessage *msg = NULL;
+       long msgnum = 0;
 
        lprintf(CTDL_DEBUG, "POP3: %s %s %s %s\n", roomname, pop3host, pop3user, pop3pass);
        lprintf(CTDL_NOTICE, "Connecting to <%s>\n", pop3host);
@@ -59,7 +69,7 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3
        lprintf(CTDL_DEBUG, "Connected!\n");
 
        /* Read the server greeting */
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
        if (strncasecmp(buf, "+OK", 3)) goto bail;
 
@@ -67,7 +77,7 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3
        snprintf(buf, sizeof buf, "USER %s", pop3user);
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (sock_puts(sock, buf) <0) goto bail;
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
        if (strncasecmp(buf, "+OK", 3)) goto bail;
 
@@ -75,12 +85,76 @@ void pop3_do_fetching(char *roomname, char *pop3host, char *pop3user, char *pop3
        snprintf(buf, sizeof buf, "PASS %s", pop3pass);
        lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (sock_puts(sock, buf) <0) goto bail;
-       if (sock_gets(sock, buf) < 0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
        lprintf(CTDL_DEBUG, ">%s\n", buf);
        if (strncasecmp(buf, "+OK", 3)) goto bail;
 
-       sock_puts(sock, "QUIT");
+       /* Get the list of messages */
+       snprintf(buf, sizeof buf, "LIST");
+       lprintf(CTDL_DEBUG, "<%s\n", buf);
+       if (sock_puts(sock, buf) <0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
+       lprintf(CTDL_DEBUG, ">%s\n", buf);
+       if (strncasecmp(buf, "+OK", 3)) goto bail;
+
+       do {
+               if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
+               lprintf(CTDL_DEBUG, ">%s\n", buf);
+               msg_to_fetch = atoi(buf);
+               if (msg_to_fetch > 0) {
+                       if (alloc_msgs == 0) {
+                               alloc_msgs = 100;
+                               msglist = malloc((alloc_msgs * (sizeof(int))));
+                       }
+                       else if (num_msgs >= alloc_msgs) {
+                               alloc_msgs = alloc_msgs * 2;
+                               msglist = realloc(msglist, (alloc_msgs * sizeof(int)));
+                       }
+                       if (msglist == NULL) goto bail;
+                       msglist[num_msgs++] = msg_to_fetch;
+               }
+       } while (buf[0] != '.');
+
+       if (num_msgs) for (i=0; i<num_msgs; ++i) {
+
+               /* Tell the server to fetch the message */
+               snprintf(buf, sizeof buf, "RETR %d", msglist[i]);
+               lprintf(CTDL_DEBUG, "<%s\n", buf);
+               if (sock_puts(sock, buf) <0) goto bail;
+               if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
+               lprintf(CTDL_DEBUG, ">%s\n", buf);
+               if (strncasecmp(buf, "+OK", 3)) goto bail;
+
+               /* If we get to this point, the message is on its way.  Read it. */
+               body = CtdlReadMessageBody(".", config.c_maxmsglen, NULL, 1, sock);
+               if (body == NULL) goto bail;
+
+               lprintf(CTDL_DEBUG, "Converting message...\n");
+               msg = convert_internet_message(body);
+               body = NULL;    /* yes, this should be dereferenced, NOT freed */
+
+               /* Do Something With It (tm) */
+               msgnum = CtdlSubmitMsg(msg, NULL, roomname);
+               if (msgnum > 0L) {
+                       /* Message has been committed to the store, so delete it from the remote server */
+                       snprintf(buf, sizeof buf, "DELE %d", msglist[i]);
+                       lprintf(CTDL_DEBUG, "<%s\n", buf);
+                       if (sock_puts(sock, buf) <0) goto bail;
+                       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
+                       lprintf(CTDL_DEBUG, ">%s\n", buf);
+                       if (strncasecmp(buf, "+OK", 3)) goto bail;
+               }
+               CtdlFreeMessage(msg);
+       }
+
+       /* Log out */
+       snprintf(buf, sizeof buf, "QUIT");
+       lprintf(CTDL_DEBUG, "<%s\n", buf);
+       if (sock_puts(sock, buf) <0) goto bail;
+       if (sock_getln(sock, buf, sizeof buf) < 0) goto bail;
+       lprintf(CTDL_DEBUG, ">%s\n", buf);
 bail:  sock_close(sock);
+       if (msglist) free(msglist);
 }
 
 
index 010e76b43de4a8936bcfeca943173f4fb1b6d684..fe485b41ea77579d7c5c9263e1aec59e43e29773 100644 (file)
@@ -1114,7 +1114,7 @@ void cmd_msiv(char *argbuf) {
                extract_token(script_name, argbuf, 1, '|', sizeof script_name);
                if (!IsEmptyStr(script_name)) {
                        cprintf("%d Transmit script now\n", SEND_LISTING);
-                       script_content = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0);
+                       script_content = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0);
                        msiv_putscript(&u, script_name, script_content);
                        changes_made = 1;
                }
index 960e105d0816164602b6a3182c861439a5179105..df9b3d632eea8e49cd6bb035c90ac76367dad85b 100644 (file)
@@ -673,7 +673,7 @@ void smtp_data(void) {
                        config.c_fqdn,
                        nowstamp);
        
-       body = CtdlReadMessageBody(".", config.c_maxmsglen, body, 1);
+       body = CtdlReadMessageBody(".", config.c_maxmsglen, body, 1, 0);
        if (body == NULL) {
                cprintf("550 5.6.5 "
                        "Unable to save message: internal error.\r\n");
index 64ad1f5cba100bdd7d9703c176e19f2422d2c8d9..cdf81557af86511a10eafab7d5ae49dc25bb00b2 100644 (file)
@@ -118,14 +118,14 @@ int spam_assassin(struct CtdlMessage *msg) {
        
        /* Response */
        lprintf(CTDL_DEBUG, "Awaiting response\n");
-        if (sock_gets(sock, buf) < 0) {
+        if (sock_getln(sock, buf, sizeof buf) < 0) {
                 goto bail;
         }
         lprintf(CTDL_DEBUG, "<%s\n", buf);
        if (strncasecmp(buf, "SPAMD", 5)) {
                goto bail;
        }
-        if (sock_gets(sock, buf) < 0) {
+        if (sock_getln(sock, buf, sizeof buf) < 0) {
                 goto bail;
         }
         lprintf(CTDL_DEBUG, "<%s\n", buf);
index 361f791a3e626776bbdaa6c95170da50028b36f8..b5732fe881c2a8ade6335c6d70c512f37ba56ac0 100644 (file)
@@ -53,6 +53,7 @@
 #include "euidindex.h"
 #include "journaling.h"
 #include "citadel_dirs.h"
+#include "clientsocket.h"
 
 
 long config_msgnum;
@@ -2819,7 +2820,8 @@ char *CtdlReadMessageBody(char *terminator,       /* token signalling EOT */
                        size_t maxlen,          /* maximum message length */
                        char *exist,            /* if non-null, append to it;
                                                   exist is ALWAYS freed  */
-                       int crlf                /* CRLF newlines instead of LF */
+                       int crlf,               /* CRLF newlines instead of LF */
+                       int sock                /* socket handle or 0 for this session's client socket */
                        ) {
        char buf[1024];
        int linelen;
@@ -2859,7 +2861,12 @@ char *CtdlReadMessageBody(char *terminator,      /* token signalling EOT */
 
        /* read in the lines of message text one by one */
        do {
-               if (client_getln(buf, (sizeof buf - 3)) < 1) finished = 1;
+               if (sock > 0) {
+                       if (sock_getln(sock, buf, (sizeof buf - 3)) < 0) finished = 1;
+               }
+               else {
+                       if (client_getln(buf, (sizeof buf - 3)) < 1) finished = 1;
+               }
                if (!strcmp(buf, terminator)) finished = 1;
                if (crlf) {
                        strcat(buf, "\r\n");
@@ -3029,7 +3036,7 @@ struct CtdlMessage *CtdlMakeMessage(
                msg->cm_fields['M'] = preformatted_text;
        }
        else {
-               msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0);
+               msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0);
        }
 
        return(msg);
index 6a6f5e109b831c0228376d364355f47f9356d03a..50a1a64876fb01352d3f9948851affe45fa6053e 100644 (file)
@@ -126,7 +126,7 @@ void ReplicationChecks(struct CtdlMessage *);
 int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newmsgs,
                                int do_repl_check, struct CtdlMessage *supplied_msg);
 int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check, struct CtdlMessage *msg);
-char *CtdlReadMessageBody(char *terminator, size_t maxlen, char *exist, int crlf);
+char *CtdlReadMessageBody(char *terminator, size_t maxlen, char *exist, int crlf, int sock);
 char *CtdlGetSysConfig(char *sysconfname);
 void CtdlPutSysConfig(char *sysconfname, char *sysconfdata);
 int CtdlOutputMsg(long msg_num,                /* message number (local) to fetch */