X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Flistdeliver%2Fserv_listdeliver.c;h=29c1c5c82e737a78e9be648b49539db7e480a735;hb=51b18018ff923284d76a36cbd421d62abf6afcf4;hp=2fe3bcec50dd898371908f2f62e7c9a36c7d030c;hpb=77dc5d1730634ba7d115ca63e4ce937aa2466d5d;p=citadel.git diff --git a/citadel/modules/listdeliver/serv_listdeliver.c b/citadel/modules/listdeliver/serv_listdeliver.c index 2fe3bcec5..29c1c5c82 100644 --- a/citadel/modules/listdeliver/serv_listdeliver.c +++ b/citadel/modules/listdeliver/serv_listdeliver.c @@ -43,14 +43,169 @@ int doing_listdeliver = 0; +// data passed back and forth between listdeliver_do_msg() and listdeliver_sweep_room() +struct lddata { + long msgnum; // number of most recent message processed + char *netconf; // netconfig for this room (contains the recipients) +}; -void listdeliver_sweep_room(struct ctdlroom *qrbuf, void *data) { + + +void listdeliver_do_msg(long msgnum, void *userdata) { + struct lddata *ld = (struct lddata *) userdata; + if (!ld) return; + char buf[SIZ]; + char *ch; + char bounce_to[256]; + + ld->msgnum = msgnum; + if (msgnum <= 0) return; + + struct CtdlMessage *TheMessage = CtdlFetchMessage(msgnum, 1); + if (!TheMessage) return; + + // If the subject line does not contain the name of the room, add it now. + if (!bmstrcasestr(TheMessage->cm_fields[eMsgSubject], CC->room.QRname)) { + snprintf(buf, sizeof buf, "[%s] %s", CC->room.QRname, TheMessage->cm_fields[eMsgSubject]); + CM_SetField(TheMessage, eMsgSubject, buf, strlen(buf)); + } + + // Reply-to: should be set so that replies come to the list. + snprintf(buf, sizeof buf, "room_%s@%s", CC->room.QRname, CtdlGetConfigStr("c_fqdn")); + for (ch=buf; *ch; ++ch) { + if (isspace(*ch)) *ch = '_'; + } + CM_SetField(TheMessage, eReplyTo, buf, strlen(buf)); + + // With that out of the way, let's figure out who this message needs to be sent to. + char *recipients = malloc(strlen(ld->netconf)); + if (recipients) { + recipients[0] = 0; + + int config_lines = num_tokens(ld->netconf, '\n'); + for (int i=0; inetconf, i, '\n', sizeof buf); + if (!strncasecmp(buf, "listrecp|", 9)) { + if (recipients[0] != 0) { + strcat(recipients, ","); + } + strcat(recipients, &buf[9]); + } + if (!strncasecmp(buf, "digestrecp|", 11)) { + if (recipients[0] != 0) { + strcat(recipients, ","); + } + strcat(recipients, &buf[11]); + } + } + + // Where do we want bounces and other noise to be sent? Certainly not to the list members! + snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", CtdlGetConfigStr("c_fqdn")); + + // Now submit the message + struct recptypes *valid = validate_recipients(recipients, NULL, 0); + if (valid) { + valid->bounce_to = strdup(bounce_to); + valid->envelope_from = strdup(bounce_to); + CtdlSubmitMsg(TheMessage, valid, ""); + free_recipients(valid); + } + } + CM_Free(TheMessage); +} + + +/* + * Sweep through one room looking for mailing list deliveries to do + */ +void listdeliver_sweep_room(char *roomname) { + char *netconfig = NULL; + char *newnetconfig = NULL; + long lastsent = 0; + char buf[SIZ]; + int config_lines; + int i; + int number_of_messages_processed = 0; + int number_of_recipients = 0; + struct lddata ld; + + if (CtdlGetRoom(&CC->room, roomname)) { + syslog(LOG_DEBUG, "listdeliver: no room <%s>", roomname); + return; + } + + netconfig = LoadRoomNetConfigFile(CC->room.QRnumber); + if (!netconfig) { + return; // no netconfig, no processing, no problem + } + + config_lines = num_tokens(netconfig, '\n'); + for (i=0; i 0) { + syslog(LOG_DEBUG, "listdeliver: processing new messages in <%s> for <%d> recipients", CC->room.QRname, number_of_recipients); + ld.netconf = netconfig; + number_of_messages_processed = CtdlForEachMessage(MSGS_GT, lastsent, NULL, NULL, NULL, listdeliver_do_msg, &ld); + syslog(LOG_INFO, "listdeliver: processed <%d> messages in <%s> for <%d> recipients", number_of_messages_processed, CC->room.QRname, number_of_recipients); + + if (number_of_messages_processed > 0) { + syslog(LOG_DEBUG, "listdeliver: new lastsent is %ld", ld.msgnum); + + // Update this room's netconfig with the updated lastsent + begin_critical_section(S_NETCONFIGS); + netconfig = LoadRoomNetConfigFile(CC->room.QRnumber); + if (!netconfig) { + netconfig = strdup(""); + } + + // The new netconfig begins with the new lastsent directive + newnetconfig = malloc(strlen(netconfig) + 1024); + sprintf(newnetconfig, "lastsent|%ld\n", ld.msgnum); + + // And then we append all of the old netconfig, minus the old lastsent. Also omit blank lines. + config_lines = num_tokens(netconfig, '\n'); + for (i=0; iroom.QRnumber, newnetconfig); + end_critical_section(S_NETCONFIGS); + free(newnetconfig); // this was the new netconfig, free it because we're done with it + } + } + free(netconfig); // this was the old netconfig, free it even if we didn't do anything } +/* + * Callback for listdeliver_sweep() + * Adds one room to the queue + */ +void listdeliver_queue_room(struct ctdlroom *qrbuf, void *data) { + Array *roomlistarr = (Array *)data; + array_append(roomlistarr, qrbuf->QRname); +} + +/* + * Queue up the list of rooms so we can sweep them for mailing list delivery instructions + */ void listdeliver_sweep(void) { static time_t last_run = 0L; + int i = 0; /* * Run mailing list delivery no more frequently than once every 15 minutes (we should make this configurable) @@ -72,21 +227,27 @@ void listdeliver_sweep(void) { * Go through each room looking for mailing lists to process */ syslog(LOG_DEBUG, "listdeliver: sweep started"); - CtdlForEachRoom(listdeliver_sweep_room, NULL); + + Array *roomlistarr = array_new(ROOMNAMELEN); // we have to queue them + CtdlForEachRoom(listdeliver_queue_room, roomlistarr); // otherwise we get multiple cursors in progress + + for (i=0; i