/* * Fetch the "mortuary" - a list of dead buddies which we keep around forever * so we can remove them from any client's roster that still has them listed */ void xmpp_store_mortuary(HashList *mortuary) { HashPos *HashPos; long len; void *Value; const char *Key; StrBuf *themsg; themsg = NewStrBuf(); StrBufPrintf(themsg, "Content-type: " XMPPMORTUARY "\n" "Content-transfer-encoding: 7bit\n" "\n" ); HashPos = GetNewHashPos(mortuary, 0); while (GetNextHashPos(mortuary, HashPos, &len, &Key, &Value) != 0) { StrBufAppendPrintf(themsg, "%s\n", (char *)Value); } DeleteHashPos(&HashPos); /* Delete the old mortuary */ CtdlDeleteMessages(USERCONFIGROOM, NULL, 0, XMPPMORTUARY); /* And save the new one to disk */ quickie_message("Citadel", NULL, NULL, USERCONFIGROOM, ChrPtr(themsg), 4, "XMPP Mortuary"); FreeStrBuf(&themsg); }
/* * Spools out one message from the list. */ 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; sc = (SpoolControl *)userdata; 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); network_process_ignetpush(sc, msg, &delete_after_send); CM_Free(msg); /* update lastsent */ sc->lastsent = msgnum; /* Delete this message if delete-after-send is set */ if (delete_after_send) { CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, ""); } }
/* * Second phase of message purge -- read list of msgs from temp file and * delete them. */ void DoPurgeMessages(FILE *purgelist) { char roomname[ROOMNAMELEN]; long msgnum; char buf[SIZ]; rewind(purgelist); strcpy(roomname, "nonexistent room ___ ___"); while (fgets(buf, sizeof buf, purgelist) != NULL) { buf[strlen(buf)-1]=0; if (!strncasecmp(buf, "r=", 2)) { strcpy(roomname, &buf[2]); } if (!strncasecmp(buf, "m=", 2)) { msgnum = atol(&buf[2]); if (msgnum > 0L) { CtdlDeleteMessages(roomname, &msgnum, 1, ""); } } } }
/****************************************************************************** * So, we're finished with sending (regardless of success or failure) * * This Message might be referenced by several Queue-Items, if we're the last,* * we need to free the memory and send bounce messages (on terminal failure) * * else we just free our SMTP-Message struct. * ******************************************************************************/ eNextState FinalizeMessageSend_DB(AsyncIO *IO) { const char *Status; SmtpOutMsg *Msg = IO->Data; StrBuf *StatusMessage; if (Msg->MyQEntry->AllStatusMessages != NULL) StatusMessage = Msg->MyQEntry->AllStatusMessages; else StatusMessage = Msg->MyQEntry->StatusMessage; if (Msg->MyQEntry->Status == 2) { SetSMTPState(IO, eSTMPfinished); Status = "Delivery successful."; } else if (Msg->MyQEntry->Status == 5) { SetSMTPState(IO, eSMTPFailTotal); Status = "Delivery failed permanently; giving up."; } else { SetSMTPState(IO, eSMTPFailTemporary); Status = "Delivery failed temporarily; will retry later."; } EVS_syslog(LOG_INFO, "%s Time[%fs] Recipient <%s> @ <%s> (%s) Status message: %s\n", Status, Msg->IO.Now - Msg->IO.StartIO, Msg->user, Msg->node, Msg->name, ChrPtr(StatusMessage)); Msg->IDestructQueItem = DecreaseQReference(Msg->MyQItem); Msg->nRemain = CountActiveQueueEntries(Msg->MyQItem, 0); if (Msg->MyQEntry->Active && !Msg->MyQEntry->StillActive && CheckQEntryIsBounce(Msg->MyQEntry)) { /* are we casue for a bounce mail? */ Msg->MyQItem->SendBounceMail |= (1<<Msg->MyQEntry->Status); } if ((Msg->nRemain > 0) || Msg->IDestructQueItem) Msg->QMsgData = SerializeQueueItem(Msg->MyQItem); else Msg->QMsgData = NULL; /* * Uncompleted delivery instructions remain, so delete the old * instructions and replace with the updated ones. */ EVS_syslog(LOG_DEBUG, "%ld", Msg->MyQItem->QueMsgID); CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, &Msg->MyQItem->QueMsgID, 1, ""); Msg->MyQItem->QueMsgID = -1; if (Msg->IDestructQueItem) smtpq_do_bounce(Msg->MyQItem, Msg->msgtext, Msg->pCurrRelay); if (Msg->nRemain > 0) { struct CtdlMessage *msg; msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); msg->cm_magic = CTDLMESSAGE_MAGIC; msg->cm_anon_type = MES_NORMAL; msg->cm_format_type = FMT_RFC822; CM_SetAsFieldSB(msg, eMesageText, &Msg->QMsgData); CM_SetField(msg, eMsgSubject, HKEY("QMSG")); Msg->MyQItem->QueMsgID = CtdlSubmitMsg(msg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR); EVS_syslog(LOG_DEBUG, "%ld", Msg->MyQItem->QueMsgID); CM_Free(msg); } else { CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, &Msg->MyQItem->MessageID, 1, ""); FreeStrBuf(&Msg->QMsgData); } RemoveContext(Msg->IO.CitContext); return eAbort; }