/* * Destructor for recptypes */ void free_recipients(recptypes *valid) { if (valid == NULL) { return; } if (valid->recptypes_magic != RECPTYPES_MAGIC) { struct CitContext *CCC = CC; MSGM_syslog(LOG_EMERG, "Attempt to call free_recipients() on some other data type!\n"); abort(); } if (valid->errormsg != NULL) free(valid->errormsg); if (valid->recp_local != NULL) free(valid->recp_local); if (valid->recp_internet != NULL) free(valid->recp_internet); if (valid->recp_ignet != NULL) free(valid->recp_ignet); if (valid->recp_room != NULL) free(valid->recp_room); if (valid->recp_orgroom != NULL) free(valid->recp_orgroom); if (valid->display_recp != NULL) free(valid->display_recp); if (valid->bounce_to != NULL) free(valid->bounce_to); if (valid->envelope_from != NULL) free(valid->envelope_from); if (valid->sending_room != NULL) free(valid->sending_room); free(valid); }
int smtp_aftersave(struct CtdlMessage *msg, recptypes *recps) { /* For internet mail, generate delivery instructions. * Yes, this is recursive. Deal with it. Infinite recursion does * not happen because the delivery instructions message does not * contain a recipient. */ if ((recps != NULL) && (recps->num_internet > 0)) { struct CtdlMessage *imsg = NULL; char recipient[SIZ]; CitContext *CCC = MyContext(); StrBuf *SpoolMsg = NewStrBuf(); long nTokens; int i; MSGM_syslog(LOG_DEBUG, "Generating delivery instructions\n"); StrBufPrintf(SpoolMsg, "Content-type: "SPOOLMIME"\n" "\n" "msgid|%s\n" "submitted|%ld\n" "bounceto|%s\n", msg->cm_fields[eVltMsgNum], (long)time(NULL), recps->bounce_to); if (recps->envelope_from != NULL) { StrBufAppendBufPlain(SpoolMsg, HKEY("envelope_from|"), 0); StrBufAppendBufPlain(SpoolMsg, recps->envelope_from, -1, 0); StrBufAppendBufPlain(SpoolMsg, HKEY("\n"), 0); } if (recps->sending_room != NULL) { StrBufAppendBufPlain(SpoolMsg, HKEY("source_room|"), 0); StrBufAppendBufPlain(SpoolMsg, recps->sending_room, -1, 0); StrBufAppendBufPlain(SpoolMsg, HKEY("\n"), 0); } nTokens = num_tokens(recps->recp_internet, '|'); for (i = 0; i < nTokens; i++) { long len; len = extract_token(recipient, recps->recp_internet, i, '|', sizeof recipient); if (len > 0) { StrBufAppendBufPlain(SpoolMsg, HKEY("remote|"), 0); StrBufAppendBufPlain(SpoolMsg, recipient, len, 0); StrBufAppendBufPlain(SpoolMsg, HKEY("|0||\n"), 0); } } imsg = malloc(sizeof(struct CtdlMessage)); memset(imsg, 0, sizeof(struct CtdlMessage)); imsg->cm_magic = CTDLMESSAGE_MAGIC; imsg->cm_anon_type = MES_NORMAL; imsg->cm_format_type = FMT_RFC822; CM_SetField(imsg, eMsgSubject, HKEY("QMSG")); CM_SetField(imsg, eAuthor, HKEY("Citadel")); CM_SetField(imsg, eJournal, HKEY("do not journal")); CM_SetAsFieldSB(imsg, eMesageText, &SpoolMsg); CtdlSubmitMsg(imsg, NULL, SMTP_SPOOLOUT_ROOM, QP_EADDR); CM_Free(imsg); } return 0; }
/* * Validate recipients, count delivery types and errors, and handle aliasing * FIXME check for dupes!!!!! * * Returns 0 if all addresses are ok, ret->num_error = -1 if no addresses * were specified, or the number of addresses found invalid. * * Caller needs to free the result using free_recipients() */ recptypes *validate_recipients(const char *supplied_recipients, const char *RemoteIdentifier, int Flags) { struct CitContext *CCC = CC; recptypes *ret; char *recipients = NULL; char *org_recp; char this_recp[256]; char this_recp_cooked[256]; char append[SIZ]; long len; int num_recps = 0; int i, j; int mailtype; int invalid; struct ctdluser tempUS; struct ctdlroom tempQR; struct ctdlroom tempQR2; int err = 0; char errmsg[SIZ]; int in_quotes = 0; /* Initialize */ ret = (recptypes *) malloc(sizeof(recptypes)); if (ret == NULL) return(NULL); /* Set all strings to null and numeric values to zero */ memset(ret, 0, sizeof(recptypes)); if (supplied_recipients == NULL) { recipients = strdup(""); } else { recipients = strdup(supplied_recipients); } /* Allocate some memory. Yes, this allocates 500% more memory than we will * actually need, but it's healthier for the heap than doing lots of tiny * realloc() calls instead. */ len = strlen(recipients) + 1024; ret->errormsg = malloc(len); ret->recp_local = malloc(len); ret->recp_internet = malloc(len); ret->recp_ignet = malloc(len); ret->recp_room = malloc(len); ret->display_recp = malloc(len); ret->recp_orgroom = malloc(len); org_recp = malloc(len); ret->errormsg[0] = 0; ret->recp_local[0] = 0; ret->recp_internet[0] = 0; ret->recp_ignet[0] = 0; ret->recp_room[0] = 0; ret->recp_orgroom[0] = 0; ret->display_recp[0] = 0; ret->recptypes_magic = RECPTYPES_MAGIC; /* Change all valid separator characters to commas */ for (i=0; !IsEmptyStr(&recipients[i]); ++i) { if ((recipients[i] == ';') || (recipients[i] == '|')) { recipients[i] = ','; } } /* Now start extracting recipients... */ while (!IsEmptyStr(recipients)) { for (i=0; i<=strlen(recipients); ++i) { if (recipients[i] == '\"') in_quotes = 1 - in_quotes; if ( ( (recipients[i] == ',') && (!in_quotes) ) || (recipients[i] == 0) ) { safestrncpy(this_recp, recipients, i+1); this_recp[i] = 0; if (recipients[i] == ',') { strcpy(recipients, &recipients[i+1]); } else { strcpy(recipients, ""); } break; } } striplt(this_recp); if (IsEmptyStr(this_recp)) break; MSG_syslog(LOG_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp); ++num_recps; strcpy(org_recp, this_recp); alias(this_recp); alias(this_recp); mailtype = alias(this_recp); for (j = 0; !IsEmptyStr(&this_recp[j]); ++j) { if (this_recp[j]=='_') { this_recp_cooked[j] = ' '; } else { this_recp_cooked[j] = this_recp[j]; } } this_recp_cooked[j] = '\0'; invalid = 0; errmsg[0] = 0; switch(mailtype) { case MES_LOCAL: if (!strcasecmp(this_recp, "sysop")) { ++ret->num_room; strcpy(this_recp, CtdlGetConfigStr("c_aideroom")); if (!IsEmptyStr(ret->recp_room)) { strcat(ret->recp_room, "|"); } strcat(ret->recp_room, this_recp); } else if ( (!strncasecmp(this_recp, "room_", 5)) && (!CtdlGetRoom(&tempQR, &this_recp_cooked[5])) ) { /* Save room so we can restore it later */ tempQR2 = CCC->room; CCC->room = tempQR; /* Check permissions to send mail to this room */ err = CtdlDoIHavePermissionToPostInThisRoom( errmsg, sizeof errmsg, RemoteIdentifier, Flags, 0 /* 0 = not a reply */ ); if (err) { ++ret->num_error; invalid = 1; } else { ++ret->num_room; if (!IsEmptyStr(ret->recp_room)) { strcat(ret->recp_room, "|"); } strcat(ret->recp_room, &this_recp_cooked[5]); if (!IsEmptyStr(ret->recp_orgroom)) { strcat(ret->recp_orgroom, "|"); } strcat(ret->recp_orgroom, org_recp); } /* Restore room in case something needs it */ CCC->room = tempQR2; } else if (CtdlGetUser(&tempUS, this_recp) == 0) { ++ret->num_local; strcpy(this_recp, tempUS.fullname); if (!IsEmptyStr(ret->recp_local)) { strcat(ret->recp_local, "|"); } strcat(ret->recp_local, this_recp); } else if (CtdlGetUser(&tempUS, this_recp_cooked) == 0) { ++ret->num_local; strcpy(this_recp, tempUS.fullname); if (!IsEmptyStr(ret->recp_local)) { strcat(ret->recp_local, "|"); } strcat(ret->recp_local, this_recp); } else { ++ret->num_error; invalid = 1; } break; case MES_INTERNET: /* Yes, you're reading this correctly: if the target * domain points back to the local system or an attached * Citadel directory, the address is invalid. That's * because if the address were valid, we would have * already translated it to a local address by now. */ if (IsDirectory(this_recp, 0)) { ++ret->num_error; invalid = 1; } else { ++ret->num_internet; if (!IsEmptyStr(ret->recp_internet)) { strcat(ret->recp_internet, "|"); } strcat(ret->recp_internet, this_recp); } break; case MES_IGNET: ++ret->num_ignet; if (!IsEmptyStr(ret->recp_ignet)) { strcat(ret->recp_ignet, "|"); } strcat(ret->recp_ignet, this_recp); break; case MES_ERROR: ++ret->num_error; invalid = 1; break; } if (invalid) { if (IsEmptyStr(errmsg)) { snprintf(append, sizeof append, "Invalid recipient: %s", this_recp); } else { snprintf(append, sizeof append, "%s", errmsg); } if ( (strlen(ret->errormsg) + strlen(append) + 3) < SIZ) { if (!IsEmptyStr(ret->errormsg)) { strcat(ret->errormsg, "; "); } strcat(ret->errormsg, append); } } else { if (IsEmptyStr(ret->display_recp)) { strcpy(append, this_recp); } else { snprintf(append, sizeof append, ", %s", this_recp); } if ( (strlen(ret->display_recp)+strlen(append)) < SIZ) { strcat(ret->display_recp, append); } } } free(org_recp); if ((ret->num_local + ret->num_internet + ret->num_ignet + ret->num_room + ret->num_error) == 0) { ret->num_error = (-1); strcpy(ret->errormsg, "No recipients specified."); } MSGM_syslog(LOG_DEBUG, "validate_recipients()\n"); MSG_syslog(LOG_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); MSG_syslog(LOG_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); MSG_syslog(LOG_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); MSG_syslog(LOG_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); MSG_syslog(LOG_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); free(recipients); return(ret); }