X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fpop3client%2Fserv_pop3client.c;h=51d3f2dd9599ef9eabbf64a9718784b99faf8f3c;hb=c71df26b9d35c07eb9c1322a7e83caa86337ad82;hp=1af84971a5eaefc91a1cb79429e249bf71c14af3;hpb=887d52d85b8609af10d855819dfa70666d6bbb6c;p=citadel.git diff --git a/citadel/modules/pop3client/serv_pop3client.c b/citadel/modules/pop3client/serv_pop3client.c index 1af84971a..51d3f2dd9 100644 --- a/citadel/modules/pop3client/serv_pop3client.c +++ b/citadel/modules/pop3client/serv_pop3client.c @@ -1,7 +1,7 @@ /* * Consolidate mail from remote POP3 accounts. * - * Copyright (c) 2007-2017 by the citadel.org team + * Copyright (c) 2007-2019 by the citadel.org team * * This program is open source software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -49,36 +49,32 @@ #include "database.h" #include "citadel_dirs.h" +struct p3cq { // module-local queue of pop3 client work that needs processing + struct p3cq *next; + char *room; + char *host; + char *user; + char *pass; + int keep; + long interval; +}; -struct CitContext pop3_client_CC; static int doing_pop3client = 0; - - -// This is how we form a USETABLE record for pop3 client -// -// StrBufPrintf(RecvMsg->CurrMsg->MsgUID, -// "pop3/%s/%s:%s@%s", -// ChrPtr(RecvMsg->RoomName), -// ChrPtr(RecvMsg->CurrMsg->MsgUIDL), -// RecvMsg->IO.ConnectMe->User, -// RecvMsg->IO.ConnectMe->Host -// ); - +struct p3cq *p3cq = NULL; /* * Process one mailbox. */ -void pop3client_one_mailbox(struct ctdlroom *qrbuf, const char *host, const char *user, const char *pass, int keep, long interval) +void pop3client_one_mailbox(char *room, const char *host, const char *user, const char *pass, int keep, long interval) { - syslog(LOG_DEBUG, "pop3client: room=<%s> host=<%s> user=<%s> keep=<%d> interval=<%ld>", - qrbuf->QRname, host, user, keep, interval - ); + syslog(LOG_DEBUG, "pop3client: room=<%s> host=<%s> user=<%s> keep=<%d> interval=<%ld>", room, host, user, keep, interval); char url[SIZ]; CURL *curl; CURLcode res = CURLE_OK; StrBuf *Uidls = NULL; int i; + char cmd[1024]; curl = curl_easy_init(); if (!curl) { @@ -102,7 +98,7 @@ void pop3client_one_mailbox(struct ctdlroom *qrbuf, const char *host, const char res = curl_easy_perform(curl); if (res == CURLE_OK) { } else { - syslog(LOG_DEBUG, "POP3S client failed: %s , trying POP3 next", curl_easy_strerror(res)); + syslog(LOG_DEBUG, "pop3client: POP3S connection failed: %s , trying POP3 next", curl_easy_strerror(res)); snprintf(url, sizeof url, "pop3://%s", host); // try unencrypted next curl_easy_setopt(curl, CURLOPT_URL, url); FlushStrBuf(Uidls); @@ -110,7 +106,7 @@ void pop3client_one_mailbox(struct ctdlroom *qrbuf, const char *host, const char } if (res != CURLE_OK) { - syslog(LOG_DEBUG, "pop3 client failed: %s", curl_easy_strerror(res)); + syslog(LOG_DEBUG, "pop3client: POP3 connection failed: %s", curl_easy_strerror(res)); curl_easy_cleanup(curl); FreeStrBuf(&Uidls); return; @@ -120,7 +116,7 @@ void pop3client_one_mailbox(struct ctdlroom *qrbuf, const char *host, const char // Now go through the UIDL list and look for messages. int num_msgs = num_tokens(ChrPtr(Uidls), '\n'); - syslog(LOG_DEBUG, "There are %d messages.", num_msgs); + syslog(LOG_DEBUG, "pop3client: there are %d messages", num_msgs); for (i=0; i <\033[34m%s\033[0m>", this_msg, oneuidl); - + // Make up the Use Table record so we can check if we've already seen this message. + StrBuf *UT = NewStrBuf(); + StrBufPrintf(UT, "pop3/%s/%s:%s@%s", room, oneuidl, user, host); + int already_seen = CheckIfAlreadySeen(UT); + FreeStrBuf(&UT); + + // Only fetch the message if we haven't seen it before. + if (already_seen == 0) { + StrBuf *TheMsg = NewStrBuf(); + snprintf(cmd, sizeof cmd, "RETR %d", this_msg); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, cmd); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, TheMsg); + res = curl_easy_perform(curl); + if (res == CURLE_OK) { + struct CtdlMessage *msg = convert_internet_message_buf(&TheMsg); + CtdlSubmitMsg(msg, NULL, room, 0); + CM_Free(msg); + } + else { + FreeStrBuf(&TheMsg); + } + + // Unless the configuration says to keep the message on the server, delete it. + if (keep == 0) { + snprintf(cmd, sizeof cmd, "DELE %d", this_msg); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, cmd); + res = curl_easy_perform(curl); + } + } + else { + syslog(LOG_DEBUG, "pop3client: %s has already been retrieved", oneuidl); + } } } @@ -149,6 +175,7 @@ void pop3client_one_mailbox(struct ctdlroom *qrbuf, const char *host, const char void pop3client_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCFG) { const RoomNetCfgLine *pLine; + struct p3cq *pptr = NULL; if (server_shutting_down) return; @@ -156,15 +183,17 @@ void pop3client_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *One while (pLine != NULL) { - pop3client_one_mailbox(qrbuf, - ChrPtr(pLine->Value[0]), - ChrPtr(pLine->Value[1]), - ChrPtr(pLine->Value[2]), - atoi(ChrPtr(pLine->Value[3])), - atol(ChrPtr(pLine->Value[4])) - ); + pptr = malloc(sizeof(struct p3cq)); + pptr->next = p3cq; + p3cq = pptr; + pptr->room = strdup(qrbuf->QRname); + pptr->host = strdup(ChrPtr(pLine->Value[0])); + pptr->user = strdup(ChrPtr(pLine->Value[1])); + pptr->pass = strdup(ChrPtr(pLine->Value[2])); + pptr->keep = atoi(ChrPtr(pLine->Value[3])); + pptr->interval = atol(ChrPtr(pLine->Value[4])); + pLine = pLine->next; - } } @@ -172,8 +201,7 @@ void pop3client_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *One void pop3client_scan(void) { static time_t last_run = 0L; time_t fastest_scan; - - become_session(&pop3_client_CC); + struct p3cq *pptr = NULL; if (CtdlGetConfigLong("c_pop3_fastest") < CtdlGetConfigLong("c_pop3_fetch")) { fastest_scan = CtdlGetConfigLong("c_pop3_fastest"); @@ -198,9 +226,27 @@ void pop3client_scan(void) { if (doing_pop3client) return; doing_pop3client = 1; - syslog(LOG_DEBUG, "pop3client started"); + syslog(LOG_DEBUG, "pop3client: scan started"); CtdlForEachNetCfgRoom(pop3client_scan_room, NULL); - syslog(LOG_DEBUG, "pop3client ended"); + + /* + * We have to queue and process in separate phases, otherwise we leave a cursor open + */ + syslog(LOG_DEBUG, "pop3client: processing started"); + while (p3cq != NULL) { + pptr = p3cq; + p3cq = p3cq->next; + + pop3client_one_mailbox(pptr->room, pptr->host, pptr->user, pptr->pass, pptr->keep, pptr->interval); + + free(pptr->room); + free(pptr->host); + free(pptr->user); + free(pptr->pass); + free(pptr); + } + + syslog(LOG_DEBUG, "pop3client: ended"); last_run = time(NULL); doing_pop3client = 0; } @@ -210,7 +256,6 @@ CTDL_MODULE_INIT(pop3client) { if (!threading) { - CtdlFillSystemContext(&pop3_client_CC, "POP3aggr"); CtdlREGISTERRoomCfgType(pop3client, ParseGeneric, 0, 5, SerializeGeneric, DeleteGenericCfgLine); CtdlRegisterSessionHook(pop3client_scan, EVT_TIMER, PRIO_AGGR + 50); }