X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fnetwork%2Fserv_netmail.c;h=a8086b83b103fde4b4b0a5f9a9f2197e1c7d7bb7;hb=951fbe7c1ee0b3554af22d6ae0d1d51c1642ae0f;hp=d9cd510930065c9d315bd80822239605d3fece97;hpb=cccc01dc3c5b9f774156b199bc1fe11f6aa9d319;p=citadel.git diff --git a/citadel/modules/network/serv_netmail.c b/citadel/modules/network/serv_netmail.c index d9cd51093..a8086b83b 100644 --- a/citadel/modules/network/serv_netmail.c +++ b/citadel/modules/network/serv_netmail.c @@ -82,8 +82,9 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName); -void aggregate_recipients(StrBuf **recps, RoomNetCfg Which, OneRoomNetCfg *OneRNCfg) +void aggregate_recipients(StrBuf **recps, RoomNetCfg Which, OneRoomNetCfg *OneRNCfg, long nSegments) { + int i; size_t recps_len = 0; RoomNetCfgLine *nptr; struct CitContext *CCC = CC; @@ -112,26 +113,79 @@ void aggregate_recipients(StrBuf **recps, RoomNetCfg Which, OneRoomNetCfg *OneRN /* Each recipient */ for (nptr = OneRNCfg->NetConfigs[Which]; nptr != NULL; nptr = nptr->next) { if (nptr != OneRNCfg->NetConfigs[Which]) { - StrBufAppendBufPlain(*recps, HKEY(","), 0); + for (i = 0; i < nSegments; i++) + StrBufAppendBufPlain(*recps, HKEY(","), i); } StrBufAppendBuf(*recps, nptr->Value[0], 0); + if (Which == ignet_push_share) + { + StrBufAppendBufPlain(*recps, HKEY(","), 0); + StrBufAppendBuf(*recps, nptr->Value[1], 0); + + } } } +static void ListCalculateSubject(struct CtdlMessage *msg) +{ + struct CitContext *CCC = CC; + StrBuf *Subject, *FlatSubject; + int rlen; + char *pCh; + + if (msg->cm_fields[eMsgSubject] == NULL) { + Subject = NewStrBufPlain(HKEY("(no subject)")); + } + else { + Subject = NewStrBufPlain( + msg->cm_fields[eMsgSubject], -1); + } + FlatSubject = NewStrBufPlain(NULL, StrLength(Subject)); + StrBuf_RFC822_to_Utf8(FlatSubject, Subject, NULL, NULL); + + rlen = strlen(CCC->room.QRname); + pCh = strstr(ChrPtr(FlatSubject), CCC->room.QRname); + if ((pCh == NULL) || + (*(pCh + rlen) != ']') || + (pCh == ChrPtr(FlatSubject)) || + (*(pCh - 1) != '[') + ) + { + StrBuf *tmp; + StrBufPlain(Subject, HKEY("[")); + StrBufAppendBufPlain(Subject, + CCC->room.QRname, + rlen, 0); + StrBufAppendBufPlain(Subject, HKEY("] "), 0); + StrBufAppendBuf(Subject, FlatSubject, 0); + /* so we can free the right one swap them */ + tmp = Subject; + Subject = FlatSubject; + FlatSubject = tmp; + StrBufRFC2047encode(&Subject, FlatSubject); + } + + if (msg->cm_fields[eMsgSubject] != NULL) + free (msg->cm_fields[eMsgSubject]); + msg->cm_fields[eMsgSubject] = SmashStrBuf(&Subject); + + FreeStrBuf(&FlatSubject); +} + /* * Deliver digest messages */ void network_deliver_digest(SpoolControl *sc) { char buf[SIZ]; - int i; struct CtdlMessage *msg = NULL; long msglen; - StrBuf *recps = NULL; - char *precps; struct recptypes *valid; char bounce_to[256]; + if (sc->Users[listrecp] == NULL) + return; + if (sc->num_msgs_spooled < 1) { fclose(sc->digestfp); sc->digestfp = NULL; @@ -145,26 +199,16 @@ void network_deliver_digest(SpoolControl *sc) msg->cm_anon_type = MES_NORMAL; sprintf(buf, "%ld", time(NULL)); - msg->cm_fields['T'] = strdup(buf); - msg->cm_fields['A'] = strdup(CC->room.QRname); + msg->cm_fields[eTimestamp] = strdup(buf); + msg->cm_fields[eAuthor] = strdup(CC->room.QRname); snprintf(buf, sizeof buf, "[%s]", CC->room.QRname); - msg->cm_fields['U'] = strdup(buf); - sprintf(buf, "room_%s@%s", CC->room.QRname, config.c_fqdn); - for (i=0; buf[i]; ++i) { - if (isspace(buf[i])) buf[i]='_'; - buf[i] = tolower(buf[i]); - } - msg->cm_fields['F'] = strdup(buf); - msg->cm_fields['R'] = strdup(buf); + msg->cm_fields[eMsgSubject] = strdup(buf); + + CtdlMsgSetCM_Fields(msg, erFc822Addr, SKEY(sc->Users[roommailalias])); + CtdlMsgSetCM_Fields(msg, eRecipient, SKEY(sc->Users[roommailalias])); /* Set the 'List-ID' header */ - msg->cm_fields['L'] = malloc(1024); - snprintf(msg->cm_fields['L'], 1024, - "%s <%ld.list-id.%s>", - CC->room.QRname, - CC->room.QRnumber, - config.c_fqdn - ); + CtdlMsgSetCM_Fields(msg, eListID, SKEY(sc->ListID)); /* * Go fetch the contents of the digest @@ -172,25 +216,24 @@ void network_deliver_digest(SpoolControl *sc) fseek(sc->digestfp, 0L, SEEK_END); msglen = ftell(sc->digestfp); - msg->cm_fields['M'] = malloc(msglen + 1); + msg->cm_fields[eMesageText] = malloc(msglen + 1); fseek(sc->digestfp, 0L, SEEK_SET); - fread(msg->cm_fields['M'], (size_t)msglen, 1, sc->digestfp); - msg->cm_fields['M'][msglen] = '\0'; + fread(msg->cm_fields[eMesageText], (size_t)msglen, 1, sc->digestfp); + msg->cm_fields[eMesageText][msglen] = '\0'; fclose(sc->digestfp); sc->digestfp = NULL; /* Now generate the delivery instructions */ - aggregate_recipients(&recps, digestrecp, sc->RNCfg); + if (sc->Users[listrecp] == NULL) + return; /* Where do we want bounces and other noise to be heard? *Surely not the list members! */ snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", config.c_fqdn); /* Now submit the message */ - precps = SmashStrBuf(&recps); - valid = validate_recipients(precps, NULL, 0); - free(precps); + valid = validate_recipients(ChrPtr(sc->Users[listrecp]), NULL, 0); if (valid != NULL) { valid->bounce_to = strdup(bounce_to); valid->envelope_from = strdup(bounce_to); @@ -209,7 +252,7 @@ void network_process_digest(SpoolControl *sc, struct CtdlMessage *omsg, long *de /* * Process digest recipients */ - if ((sc->RNCfg->NetConfigs[digestrecp] == NULL) || + if ((sc->Users[digestrecp] == NULL)|| (sc->digestfp == NULL)) return; @@ -220,26 +263,26 @@ void network_process_digest(SpoolControl *sc, struct CtdlMessage *omsg, long *de "------------------------------------" "-------\n"); fprintf(sc->digestfp, "From: "); - if (msg->cm_fields['A'] != NULL) { + if (msg->cm_fields[eAuthor] != NULL) { fprintf(sc->digestfp, "%s ", - msg->cm_fields['A']); + msg->cm_fields[eAuthor]); } - if (msg->cm_fields['F'] != NULL) { + if (msg->cm_fields[erFc822Addr] != NULL) { fprintf(sc->digestfp, "<%s> ", - msg->cm_fields['F']); + msg->cm_fields[erFc822Addr]); } - else if (msg->cm_fields['N'] != NULL) { + else if (msg->cm_fields[eNodeName] != NULL) { fprintf(sc->digestfp, "@%s ", - msg->cm_fields['N']); + msg->cm_fields[eNodeName]); } fprintf(sc->digestfp, "\n"); - if (msg->cm_fields['U'] != NULL) { + if (msg->cm_fields[eMsgSubject] != NULL) { fprintf(sc->digestfp, "Subject: %s\n", - msg->cm_fields['U']); + msg->cm_fields[eMsgSubject]); } CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); @@ -268,16 +311,12 @@ void network_process_digest(SpoolControl *sc, struct CtdlMessage *omsg, long *de void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { - int rlen; - char *pCh; - StrBuf *Subject, *FlatSubject; struct CtdlMessage *msg = NULL; - int i; /* * Process mailing list recipients */ - if (sc->RNCfg->NetConfigs[listrecp] == NULL) + if (sc->Users[listrecp] == NULL) return; /* create our own copy of the message. @@ -287,100 +326,26 @@ void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *dele msg = CtdlDuplicateMessage(omsg); - if (msg->cm_fields['K'] != NULL) - free(msg->cm_fields['K']); - if (msg->cm_fields['V'] == NULL){ - /* local message, no enVelope */ - StrBuf *Buf; - Buf = NewStrBuf(); - StrBufAppendBufPlain(Buf, - msg->cm_fields['O'] - , -1, 0); - StrBufAppendBufPlain(Buf, HKEY("@"), 0); - StrBufAppendBufPlain(Buf, config.c_fqdn, -1, 0); - - msg->cm_fields['K'] = SmashStrBuf(&Buf); - } - else { - msg->cm_fields['K'] = - strdup (msg->cm_fields['V']); - } - /* Set the 'List-ID' header */ - if (msg->cm_fields['L'] != NULL) { - free(msg->cm_fields['L']); - } - msg->cm_fields['L'] = malloc(1024); - snprintf(msg->cm_fields['L'], 1024, - "%s <%ld.list-id.%s>", - CC->room.QRname, - CC->room.QRnumber, - config.c_fqdn - ); - - /* Prepend "[List name]" to the subject */ - if (msg->cm_fields['U'] == NULL) { - Subject = NewStrBufPlain(HKEY("(no subject)")); - } - else { - Subject = NewStrBufPlain( - msg->cm_fields['U'], -1); - } - FlatSubject = NewStrBufPlain(NULL, StrLength(Subject)); - StrBuf_RFC822_to_Utf8(FlatSubject, Subject, NULL, NULL); - - rlen = strlen(CC->room.QRname); - pCh = strstr(ChrPtr(FlatSubject), CC->room.QRname); - if ((pCh == NULL) || - (*(pCh + rlen) != ']') || - (pCh == ChrPtr(FlatSubject)) || - (*(pCh - 1) != '[') - ) - { - StrBuf *tmp; - StrBufPlain(Subject, HKEY("[")); - StrBufAppendBufPlain(Subject, - CC->room.QRname, - rlen, 0); - StrBufAppendBufPlain(Subject, HKEY("] "), 0); - StrBufAppendBuf(Subject, FlatSubject, 0); - /* so we can free the right one swap them */ - tmp = Subject; - Subject = FlatSubject; - FlatSubject = tmp; - StrBufRFC2047encode(&Subject, FlatSubject); - } - - if (msg->cm_fields['U'] != NULL) - free (msg->cm_fields['U']); - msg->cm_fields['U'] = SmashStrBuf(&Subject); - FreeStrBuf(&FlatSubject); - - /* else we won't modify the buffer, since the - * roomname is already here. - */ + CtdlMsgSetCM_Fields(msg, eListID, SKEY(sc->Users[roommailalias])); /* if there is no other recipient, Set the recipient * of the list message to the email address of the * room itself. */ - if ((msg->cm_fields['R'] == NULL) || - IsEmptyStr(msg->cm_fields['R'])) + if ((msg->cm_fields[eRecipient] == NULL) || + IsEmptyStr(msg->cm_fields[eRecipient])) { - if (msg->cm_fields['R'] != NULL) - free(msg->cm_fields['R']); - - msg->cm_fields['R'] = malloc(256); - snprintf(msg->cm_fields['R'], 256, - "room_%s@%s", CC->room.QRname, - config.c_fqdn); - for (i=0; msg->cm_fields['R'][i]; ++i) { - if (isspace(msg->cm_fields['R'][i])) { - msg->cm_fields['R'][i] = '_'; - } - } + CtdlMsgSetCM_Fields(msg, eRecipient, SKEY(sc->Users[roommailalias])); } + /* Set the 'List-ID' header */ + CtdlMsgSetCM_Fields(msg, eListID, SKEY(sc->ListID)); + + + /* Prepend "[List name]" to the subject */ + ListCalculateSubject(msg); + /* Handle delivery */ network_deliver_list(msg, sc, CC->room.QRname); CtdlFreeMessage(msg); @@ -391,29 +356,21 @@ void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *dele */ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char *RoomName) { - StrBuf *recps = NULL; - char *precps = NULL; struct recptypes *valid; char bounce_to[256]; /* Don't do this if there were no recipients! */ - if (sc->RNCfg->NetConfigs[listrecp] == NULL) return; + if (sc->Users[listrecp] == NULL) + return; /* Now generate the delivery instructions */ - /* - * Figure out how big a buffer we need to allocate - */ - aggregate_recipients(&recps, listrecp, sc->RNCfg); - /* Where do we want bounces and other noise to be heard? * Surely not the list members! */ snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", config.c_fqdn); /* Now submit the message */ - precps = SmashStrBuf(&recps); - valid = validate_recipients(precps, NULL, 0); - free(precps); + valid = validate_recipients(ChrPtr(sc->Users[listrecp]), NULL, 0); if (valid != NULL) { valid->bounce_to = strdup(bounce_to); valid->envelope_from = strdup(bounce_to); @@ -428,7 +385,6 @@ void network_deliver_list(struct CtdlMessage *msg, SpoolControl *sc, const char void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { struct CtdlMessage *msg = NULL; - int i; int ok_to_participate = 0; StrBuf *Buf = NULL; struct recptypes *valid; @@ -436,7 +392,7 @@ void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, lon /* * Process client-side list participations for this room */ - if (sc->RNCfg->NetConfigs[participate] == NULL) + if (sc->Users[participate] == NULL) return; msg = CtdlDuplicateMessage(omsg); @@ -447,13 +403,13 @@ void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, lon * is rude... */ ok_to_participate = 0; - if (msg->cm_fields['N'] != NULL) { - if (!strcasecmp(msg->cm_fields['N'], + if (msg->cm_fields[eNodeName] != NULL) { + if (!strcasecmp(msg->cm_fields[eNodeName], config.c_nodename)) { ok_to_participate = 1; } - Buf = NewStrBufPlain(msg->cm_fields['N'], -1); + Buf = NewStrBufPlain(msg->cm_fields[eNodeName], -1); if (CtdlIsValidNode(NULL, NULL, Buf, @@ -465,36 +421,16 @@ void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, lon } if (ok_to_participate) { - StrBuf *recps = NULL; - char *precps; - - if (msg->cm_fields['F'] != NULL) { - free(msg->cm_fields['F']); - } - msg->cm_fields['F'] = malloc(SIZ); /* Replace the Internet email address of the * actual author with the email address of the * room itself, so the remote listserv doesn't * reject us. - * FIXME I want to be able to pick any address */ - snprintf(msg->cm_fields['F'], SIZ, - "room_%s@%s", CC->room.QRname, - config.c_fqdn); - for (i=0; msg->cm_fields['F'][i]; ++i) { - if (isspace(msg->cm_fields['F'][i])) { - msg->cm_fields['F'][i] = '_'; - } - } - - aggregate_recipients(&recps, participate, sc->RNCfg); - precps = SmashStrBuf(&recps); - valid = validate_recipients(precps, NULL, 0); + CtdlMsgSetCM_Fields(msg, erFc822Addr, SKEY(sc->Users[roommailalias])); - if (msg->cm_fields['R'] != NULL) { - free(msg->cm_fields['R']); - }/* TODO: check whether 'R' is set appropriate later. */ + valid = validate_recipients(ChrPtr(sc->Users[participate]) , NULL, 0); + CtdlMsgSetCM_Fields(msg, eRecipient, SKEY(sc->Users[roommailalias])); CtdlSubmitMsg(msg, valid, "", 0); free_recipients(valid); } @@ -504,6 +440,9 @@ void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, lon void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { + StrBuf *Recipient; + StrBuf *RemoteRoom; + const char *Pos = NULL; struct CtdlMessage *msg = NULL; struct CitContext *CCC = CC; struct ser_ret sermsg; @@ -512,14 +451,14 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long FILE *fp; size_t newpath_len; char *newpath = NULL; - RoomNetCfgLine* mptr; StrBuf *Buf = NULL; int i; int bang = 0; int send = 1; - if (sc->RNCfg->NetConfigs[ignet_push_share] == NULL) + if (sc->Users[ignet_push_share] == NULL) return; + /* * Process IGnet push shares */ @@ -528,35 +467,37 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long /* Prepend our node name to the Path field whenever * sending a message to another IGnet node */ - if (msg->cm_fields['P'] == NULL) + if (msg->cm_fields[eMessagePath] == NULL) { - msg->cm_fields['P'] = strdup("username"); + msg->cm_fields[eMessagePath] = strdup("username"); } - newpath_len = strlen(msg->cm_fields['P']) + + newpath_len = strlen(msg->cm_fields[eMessagePath]) + strlen(config.c_nodename) + 2; newpath = malloc(newpath_len); snprintf(newpath, newpath_len, "%s!%s", - config.c_nodename, msg->cm_fields['P']); - free(msg->cm_fields['P']); - msg->cm_fields['P'] = newpath; + config.c_nodename, msg->cm_fields[eMessagePath]); + free(msg->cm_fields[eMessagePath]); + msg->cm_fields[eMessagePath] = newpath; /* * Determine if this message is set to be deleted * after sending out on the network */ - if (msg->cm_fields['S'] != NULL) { - if (!strcasecmp(msg->cm_fields['S'], "CANCEL")) { + if (msg->cm_fields[eSpecialField] != NULL) { + if (!strcasecmp(msg->cm_fields[eSpecialField], "CANCEL")) { *delete_after_send = 1; } } /* Now send it to every node */ - for (mptr = sc->RNCfg->NetConfigs[ignet_push_share]; - mptr != NULL; - mptr = mptr->next) + Recipient = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share])); + RemoteRoom = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share])); + while ((Pos != StrBufNOTNULL) && + StrBufExtract_NextToken(Recipient, sc->Users[ignet_push_share], &Pos, ',')) { + StrBufExtract_NextToken(RemoteRoom, sc->Users[ignet_push_share], &Pos, ','); send = 1; - NewStrBufDupAppendFlush(&Buf, mptr->Value[0], NULL, 1); + NewStrBufDupAppendFlush(&Buf, Recipient, NULL, 1); /* Check for valid node name */ if (CtdlIsValidNode(NULL, @@ -567,33 +508,33 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long { QN_syslog(LOG_ERR, "Invalid node <%s>\n", - ChrPtr(mptr->Value[0])); + ChrPtr(Recipient)); send = 0; } /* Check for split horizon */ - QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields['P']); - bang = num_tokens(msg->cm_fields['P'], '!'); + QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields[eMessagePath]); + bang = num_tokens(msg->cm_fields[eMessagePath], '!'); if (bang > 1) { for (i=0; i<(bang-1); ++i) { extract_token(buf, - msg->cm_fields['P'], + msg->cm_fields[eMessagePath], i, '!', sizeof buf); QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", - buf, ChrPtr(mptr->Value[0])) ; - if (!strcasecmp(buf, ChrPtr(mptr->Value[0]))) { + buf, ChrPtr(Recipient)) ; + if (!strcasecmp(buf, ChrPtr(Recipient))) { send = 0; break; } } QN_syslog(LOG_INFO, - "%sSending to %s\n", + " %sSending to %s\n", (send)?"":"Not ", - ChrPtr(mptr->Value[0])); + ChrPtr(Recipient)); } /* Send the message */ @@ -604,15 +545,15 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long * room on the far end by setting the C field * correctly */ - if (msg->cm_fields['C'] != NULL) { - free(msg->cm_fields['C']); + if (msg->cm_fields[eRemoteRoom] != NULL) { + free(msg->cm_fields[eRemoteRoom]); } - if (StrLength(mptr->Value[0]) > 0) { - msg->cm_fields['C'] = - strdup(ChrPtr(mptr->Value[0])); + if (StrLength(RemoteRoom) > 0) { + msg->cm_fields[eRemoteRoom] = + strdup(ChrPtr(RemoteRoom)); } else { - msg->cm_fields['C'] = + msg->cm_fields[eRemoteRoom] = strdup(CC->room.QRname); } @@ -625,7 +566,7 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long sizeof(filename), "%s/%s@%lx%x", ctdl_netout_dir, - ChrPtr(mptr->Value[0]), + ChrPtr(Recipient), time(NULL), rand() ); @@ -653,6 +594,8 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long } } FreeStrBuf(&Buf); + FreeStrBuf(&Recipient); + FreeStrBuf(&RemoteRoom); CtdlFreeMessage(msg); } @@ -663,6 +606,7 @@ void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long void network_spool_msg(long msgnum, void *userdata) { + struct CitContext *CCC = CC; struct CtdlMessage *msg = NULL; long delete_after_send = 0; /* Set to 1 to delete after spooling */ SpoolControl *sc; @@ -671,6 +615,13 @@ void network_spool_msg(long msgnum, msg = CtdlFetchMessage(msgnum, 1); + if (msg == NULL) + { + QN_syslog(LOG_ERR, + "failed to load Message <%ld> from disk\n", + msgnum); + return; + } network_process_list(sc, msg, &delete_after_send); network_process_digest(sc, msg, &delete_after_send); network_process_participate(sc, msg, &delete_after_send);