/* * Convert FN (Friendly Name) into N (Name) * * vname Supplied friendly-name * n Target buffer to store Name * vname_size Size of buffer */ void vcard_fn_to_n(char *vname, char *n, size_t vname_size) { char lastname[256]; char firstname[256]; char middlename[256]; char honorific_prefixes[256]; char honorific_suffixes[256]; char buf[256]; safestrncpy(buf, n, sizeof buf); /* Try to intelligently convert the screen name to a * fully expanded vCard name based on the number of * words in the name */ safestrncpy(lastname, "", sizeof lastname); safestrncpy(firstname, "", sizeof firstname); safestrncpy(middlename, "", sizeof middlename); safestrncpy(honorific_prefixes, "", sizeof honorific_prefixes); safestrncpy(honorific_suffixes, "", sizeof honorific_suffixes); /* Honorific suffixes */ if (num_tokens(buf, ',') > 1) { extract_token(honorific_suffixes, buf, (num_tokens(buf, ' ') - 1), ',', sizeof honorific_suffixes); remove_token(buf, (num_tokens(buf, ',') - 1), ','); } /* Find a last name */ extract_token(lastname, buf, (num_tokens(buf, ' ') - 1), ' ', sizeof lastname); remove_token(buf, (num_tokens(buf, ' ') - 1), ' '); /* Find honorific prefixes */ if (num_tokens(buf, ' ') > 2) { extract_token(honorific_prefixes, buf, 0, ' ', sizeof honorific_prefixes); remove_token(buf, 0, ' '); } /* Find a middle name */ if (num_tokens(buf, ' ') > 1) { extract_token(middlename, buf, (num_tokens(buf, ' ') - 1), ' ', sizeof middlename); remove_token(buf, (num_tokens(buf, ' ') - 1), ' '); } /* Anything left is probably the first name */ safestrncpy(firstname, buf, sizeof firstname); striplt(firstname); /* Compose the structured name */ snprintf(vname, vname_size, "%s;%s;%s;%s;%s", lastname, firstname, middlename, honorific_prefixes, honorific_suffixes); }
/* * Remove the "charset=" attribute from a vCard property name * */ void remove_charset_attribute(char *strbuf) { int i, t; char compare[256]; t = num_tokens(strbuf, ';'); for (i=0; i<t; ++i) { extract_token(compare, strbuf, i, ';', sizeof compare); striplt(compare); if (!strncasecmp(compare, "charset=", 8)) { remove_token(strbuf, i, ';'); } } if (!IsEmptyStr(strbuf)) { if (strbuf[strlen(strbuf)-1] == ';') { strbuf[strlen(strbuf)-1] = 0; } } }
/* If the last item in a list of recipients was truncated to a partial address, * remove it completely in order to avoid choking libSieve */ void sanitize_truncated_recipient(char *str) { if (!str) return; if (num_tokens(str, ',') < 2) return; int len = strlen(str); if (len < 900) return; if (len > 998) str[998] = 0; char *cptr = strrchr(str, ','); if (!cptr) return; char *lptr = strchr(cptr, '<'); char *rptr = strchr(cptr, '>'); if ( (lptr) && (rptr) && (rptr > lptr) ) return; *cptr = 0; }
/* * Return nonzero if the supplied name is an alias for this host. */ int CtdlHostAlias(char *fqdn) { int config_lines; int i; char buf[256]; char host[256], type[256]; int found = 0; if (fqdn == NULL) return(hostalias_nomatch); if (IsEmptyStr(fqdn)) return(hostalias_nomatch); if (!strcasecmp(fqdn, "localhost")) return(hostalias_localhost); if (!strcasecmp(fqdn, CtdlGetConfigStr("c_fqdn"))) return(hostalias_localhost); if (!strcasecmp(fqdn, CtdlGetConfigStr("c_nodename"))) return(hostalias_localhost); if (inetcfg == NULL) return(hostalias_nomatch); config_lines = num_tokens(inetcfg, '\n'); for (i=0; i<config_lines; ++i) { extract_token(buf, inetcfg, i, '\n', sizeof buf); extract_token(host, buf, 0, '|', sizeof host); extract_token(type, buf, 1, '|', sizeof type); found = 0; /* Process these in a specific order, in case there are multiple matches. * We want directory to override masq, for example. */ if ( (!strcasecmp(type, "masqdomain")) && (!strcasecmp(fqdn, host))) { found = hostalias_masq; } if ( (!strcasecmp(type, "localhost")) && (!strcasecmp(fqdn, host))) { found = hostalias_localhost; } if ( (!strcasecmp(type, "directory")) && (!strcasecmp(fqdn, host))) { found = hostalias_directory; } if (found) return(found); } return(hostalias_nomatch); }
/* * Look up an Internet e-mail address in the directory. * On success: returns 0, and Citadel address stored in 'target' * On failure: returns nonzero */ int CtdlDirectoryLookup(char *target, char *internet_addr, size_t targbuflen) { struct cdbdata *cdbrec; char key[SIZ]; /* Dump it in there unchanged, just for kicks */ safestrncpy(target, internet_addr, targbuflen); /* Only do lookups for addresses with hostnames in them */ if (num_tokens(internet_addr, '@') != 2) return(-1); /* Only do lookups for domains in the directory */ if (IsDirectory(internet_addr, 0) == 0) return(-1); directory_key(key, internet_addr); cdbrec = cdb_fetch(CDB_DIRECTORY, key, strlen(key) ); if (cdbrec != NULL) { safestrncpy(target, cdbrec->ptr, targbuflen); cdb_free(cdbrec); return(0); } return(-1); }
/* * smtp_do_bounce() is caled by smtp_do_procmsg() to scan a set of delivery * instructions for "5" codes (permanent fatal errors) and produce/deliver * a "bounce" message (delivery status notification). */ void smtp_do_bounce(char *instr, StrBuf *OMsgTxt) { int i; int lines; int status; char buf[1024]; char key[1024]; char addr[1024]; char dsn[1024]; char bounceto[1024]; StrBuf *boundary; int num_bounces = 0; int bounce_this = 0; time_t submitted = 0L; struct CtdlMessage *bmsg = NULL; int give_up = 0; recptypes *valid; int successful_bounce = 0; static int seq = 0; StrBuf *BounceMB; long omsgid = (-1); syslog(LOG_DEBUG, "smtp_do_bounce() called\n"); strcpy(bounceto, ""); boundary = NewStrBufPlain(HKEY("=_Citadel_Multipart_")); StrBufAppendPrintf(boundary, "%s_%04x%04x", CtdlGetConfigStr("c_fqdn"), getpid(), ++seq); lines = num_tokens(instr, '\n'); /* See if it's time to give up on delivery of this message */ for (i=0; i<lines; ++i) { extract_token(buf, instr, i, '\n', sizeof buf); extract_token(key, buf, 0, '|', sizeof key); extract_token(addr, buf, 1, '|', sizeof addr); if (!strcasecmp(key, "submitted")) { submitted = atol(addr); } } if ( (time(NULL) - submitted) > SMTP_GIVE_UP ) { give_up = 1; } /* Start building our bounce message */ bmsg = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage)); if (bmsg == NULL) return; memset(bmsg, 0, sizeof(struct CtdlMessage)); BounceMB = NewStrBufPlain(NULL, 1024); bmsg->cm_magic = CTDLMESSAGE_MAGIC; bmsg->cm_anon_type = MES_NORMAL; bmsg->cm_format_type = FMT_RFC822; CM_SetField(bmsg, eAuthor, HKEY("Citadel")); CM_SetField(bmsg, eOriginalRoom, HKEY(MAILROOM)); CM_SetField(bmsg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename"))); CM_SetField(bmsg, eMsgSubject, HKEY("Delivery Status Notification (Failure)")); StrBufAppendBufPlain(BounceMB, HKEY("Content-type: multipart/mixed; boundary=\""), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("\"\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("MIME-Version: 1.0\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("X-Mailer: " CITADEL "\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("\r\nThis is a multipart message in MIME format." "\r\n\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("Content-type: text/plain\r\n\r\n"), 0); if (give_up) { StrBufAppendBufPlain( BounceMB, HKEY("A message you sent could not be delivered " "to some or all of its recipients\ndue to " "prolonged unavailability of its destination(s).\n" "Giving up on the following addresses:\n\n"), 0); } else { StrBufAppendBufPlain( BounceMB, HKEY("A message you sent could not be delivered " "to some or all of its recipients.\n" "The following addresses were undeliverable:\n\n" ), 0); } /* * Now go through the instructions checking for stuff. */ for (i=0; i<lines; ++i) { long addrlen; long dsnlen; extract_token(buf, instr, i, '\n', sizeof buf); extract_token(key, buf, 0, '|', sizeof key); addrlen = extract_token(addr, buf, 1, '|', sizeof addr); status = extract_int(buf, 2); dsnlen = extract_token(dsn, buf, 3, '|', sizeof dsn); bounce_this = 0; syslog(LOG_DEBUG, "key=<%s> addr=<%s> status=%d dsn=<%s>\n", key, addr, status, dsn); if (!strcasecmp(key, "bounceto")) { strcpy(bounceto, addr); } if (!strcasecmp(key, "msgid")) { omsgid = atol(addr); } if (!strcasecmp(key, "remote")) { if (status == 5) bounce_this = 1; if (give_up) bounce_this = 1; } if (bounce_this) { ++num_bounces; StrBufAppendBufPlain(BounceMB, addr, addrlen, 0); StrBufAppendBufPlain(BounceMB, HKEY(": "), 0); StrBufAppendBufPlain(BounceMB, dsn, dsnlen, 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); remove_token(instr, i, '\n'); --i; --lines; } } /* Attach the original message */ if (omsgid >= 0) { StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("Content-type: message/rfc822\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("Content-Transfer-Encoding: 7bit\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("Content-Disposition: inline\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); if (OMsgTxt == NULL) { CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); CtdlOutputMsg(omsgid, MT_RFC822, HEADERS_ALL, 0, 1, NULL, 0, NULL, NULL, NULL); StrBufAppendBuf(BounceMB, CC->redirect_buffer, 0); FreeStrBuf(&CC->redirect_buffer); } else { StrBufAppendBuf(BounceMB, OMsgTxt, 0); } } /* Close the multipart MIME scope */ StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("--\r\n"), 0); CM_SetAsFieldSB(bmsg, eMesageText, &BounceMB); /* Deliver the bounce if there's anything worth mentioning */ syslog(LOG_DEBUG, "num_bounces = %d\n", num_bounces); if (num_bounces > 0) { /* First try the user who sent the message */ if (IsEmptyStr(bounceto)) syslog(LOG_ERR, "No bounce address specified\n"); else syslog(LOG_DEBUG, "bounce to user <%s>\n", bounceto); /* Can we deliver the bounce to the original sender? */ valid = validate_recipients(bounceto, smtp_get_Recipients (), 0); if (valid != NULL) { if (valid->num_error == 0) { CtdlSubmitMsg(bmsg, valid, "", QP_EADDR); successful_bounce = 1; } } /* If not, post it in the Aide> room */ if (successful_bounce == 0) { CtdlSubmitMsg(bmsg, NULL, CtdlGetConfigStr("c_aideroom"), QP_EADDR); } /* Free up the memory we used */ if (valid != NULL) { free_recipients(valid); } } FreeStrBuf(&boundary); CM_Free(bmsg); syslog(LOG_DEBUG, "Done processing bounces\n"); }
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; char buf[SIZ]; char filename[PATH_MAX]; FILE *fp; StrBuf *Buf = NULL; int i; int bang = 0; int send = 1; if (sc->Users[ignet_push_share] == NULL) return; /* * Process IGnet push shares */ msg = CM_Duplicate(omsg); /* Prepend our node name to the Path field whenever * sending a message to another IGnet node */ Netmap_AddMe(msg, HKEY("username")); /* * Determine if this message is set to be deleted * after sending out on the network */ if (!CM_IsEmpty(msg, eSpecialField)) { if (!strcasecmp(msg->cm_fields[eSpecialField], "CANCEL")) { *delete_after_send = 1; } } /* Now send it to every node */ 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, Recipient, NULL, 1); /* Check for valid node name */ if (CtdlIsValidNode(NULL, NULL, Buf, sc->working_ignetcfg, sc->the_netmap) != 0) { QN_syslog(LOG_ERR, "Invalid node <%s>\n", ChrPtr(Recipient)); send = 0; } /* Check for split horizon */ 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[eMessagePath], i, '!', sizeof buf); QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", buf, ChrPtr(Recipient)) ; if (!strcasecmp(buf, ChrPtr(Recipient))) { send = 0; break; } } QN_syslog(LOG_INFO, " %sSending to %s\n", (send)?"":"Not ", ChrPtr(Recipient)); } /* Send the message */ if (send == 1) { /* * Force the message to appear in the correct * room on the far end by setting the C field * correctly */ if (StrLength(RemoteRoom) > 0) { CM_SetField(msg, eRemoteRoom, SKEY(RemoteRoom)); } else { CM_SetField(msg, eRemoteRoom, CCC->room.QRname, strlen(CCC->room.QRname)); } /* serialize it for transmission */ CtdlSerializeMessage(&sermsg, msg); if (sermsg.len > 0) { /* write it to a spool file */ snprintf(filename, sizeof(filename), "%s/%s@%lx%x", ctdl_netout_dir, ChrPtr(Recipient), time(NULL), rand() ); QN_syslog(LOG_DEBUG, "Appending to %s\n", filename); fp = fopen(filename, "ab"); if (fp != NULL) { fwrite(sermsg.ser, sermsg.len, 1, fp); fclose(fp); } else { QN_syslog(LOG_ERR, "%s: %s\n", filename, strerror(errno)); } /* free the serialized version */ free(sermsg.ser); } } } FreeStrBuf(&Buf); FreeStrBuf(&Recipient); FreeStrBuf(&RemoteRoom); CM_Free(msg); }
int main(int argc, char **argv) { char buf[1024]; char fromline[1024]; FILE *fp; int i; struct passwd *pw; int from_header = 0; int in_body = 0; int relh=0; int home=0; char relhome[PATH_MAX]=""; char ctdldir[PATH_MAX]=CTDLDIR; char *sp, *ep; char hostname[256]; char **recipients = NULL; int num_recipients = 0; int to_or_cc = 0; int read_recipients_from_headers = 0; char *add_these_recipients = NULL; for (i=1; i<argc; ++i) { if (!strcmp(argv[i], "-d")) { debug = 1; } else if (!strcmp(argv[i], "-t")) { read_recipients_from_headers = 1; } else if (argv[i][0] != '-') { ++num_recipients; recipients = realloc(recipients, (num_recipients * sizeof (char *))); recipients[num_recipients - 1] = strdup(argv[i]); } } /* TODO: should we be able to calculate relative dirs? */ calc_dirs_n_files(relh, home, relhome, ctdldir, 0); pw = getpwuid(getuid()); fp = tmpfile(); if (fp == NULL) return(errno); serv_sock = uds_connectsock(file_lmtp_socket); /* FIXME: if called as 'sendmail' connect to file_lmtp_unfiltered_socket */ serv_gets(buf); if (buf[0] != '2') { fprintf(stderr, "%s\n", &buf[4]); if (debug) fprintf(stderr, "citmail: could not connect to LMTP socket.\n"); cleanup(1); } sp = strchr (buf, ' '); if (sp == NULL) { if (debug) fprintf(stderr, "citmail: could not calculate hostname.\n"); cleanup(2); } sp ++; ep = strchr (sp, ' '); if (ep == NULL) { if (debug) fprintf(stderr, "citmail: error parsing hostname\n"); cleanup(3); } else *ep = '\0'; strncpy(hostname, sp, sizeof hostname); snprintf(fromline, sizeof fromline, "From: %s@%s", pw->pw_name, hostname); while (fgets(buf, 1024, stdin) != NULL) { if ( ( (buf[0] == 13) || (buf[0] == 10)) && (in_body == 0) ) { in_body = 1; if (from_header == 0) { fprintf(fp, "%s%s", fromline, buf); } } if (in_body == 0 && !strncasecmp(buf, "From:", 5)) { strcpy(fromline, buf); from_header = 1; } if (read_recipients_from_headers) { add_these_recipients = NULL; if ((isspace(buf[0])) && (to_or_cc)) { add_these_recipients = buf; } else { if ((!strncasecmp(buf, "To:", 3)) || (!strncasecmp(buf, "Cc:", 3))) { to_or_cc = 1; } else { to_or_cc = 0; } if (to_or_cc) { add_these_recipients = &buf[3]; } } if (add_these_recipients) { int num_recp_on_this_line; char this_recp[256]; num_recp_on_this_line = num_tokens(add_these_recipients, ','); for (i=0; i<num_recp_on_this_line; ++i) { extract_token(this_recp, add_these_recipients, i, ',', sizeof this_recp); striplt(this_recp); if (!IsEmptyStr(this_recp)) { ++num_recipients; recipients = realloc(recipients, (num_recipients * sizeof (char *))); recipients[num_recipients - 1] = strdup(this_recp); } } } } fprintf(fp, "%s", buf); } strip_trailing_nonprint(fromline); sprintf(buf, "LHLO %s", hostname); serv_puts(buf); do { serv_gets(buf); strcat(buf, " "); } while (buf[3] == '-'); if (buf[0] != '2') { if (debug) fprintf(stderr, "citmail: LHLO command failed\n"); cleanup(4); } snprintf(buf, sizeof buf, "MAIL %s", fromline); serv_puts(buf); serv_gets(buf); if (buf[0] != '2') { if (debug) fprintf(stderr, "citmail: MAIL command failed\n"); cleanup(5); } for (i=0; i<num_recipients; ++i) { snprintf(buf, sizeof buf, "RCPT To: %s", recipients[i]); serv_puts(buf); serv_gets(buf); free(recipients[i]); } free(recipients); serv_puts("DATA"); serv_gets(buf); if (buf[0]!='3') { if (debug) fprintf(stderr, "citmail: DATA command failed\n"); cleanup(6); } rewind(fp); while (fgets(buf, sizeof buf, fp) != NULL) { strip_trailing_nonprint(buf); serv_puts(buf); } serv_puts("."); serv_gets(buf); if (buf[0] != '2') { fprintf(stderr, "%s\n", &buf[4]); cleanup(7); } else { cleanup(0); } /* We won't actually reach this statement but the compiler will * display a spurious warning about an invalid return type if * we don't return an int. */ return(0); }
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; }
/* * Aliasing for network mail. * (Error messages have been commented out, because this is a server.) */ int alias(char *name) { /* process alias and routing info for mail */ struct CitContext *CCC = CC; FILE *fp; int a, i; char aaa[SIZ], bbb[SIZ]; char *ignetcfg = NULL; char *ignetmap = NULL; int at = 0; char node[64]; char testnode[64]; char buf[SIZ]; char original_name[256]; safestrncpy(original_name, name, sizeof original_name); striplt(name); remove_any_whitespace_to_the_left_or_right_of_at_symbol(name); stripallbut(name, '<', '>'); fp = fopen(file_mail_aliases, "r"); if (fp == NULL) { fp = fopen("/dev/null", "r"); } if (fp == NULL) { return (MES_ERROR); } strcpy(aaa, ""); strcpy(bbb, ""); while (fgets(aaa, sizeof aaa, fp) != NULL) { while (isspace(name[0])) strcpy(name, &name[1]); aaa[strlen(aaa) - 1] = 0; strcpy(bbb, ""); for (a = 0; aaa[a] != '\0'; ++a) { if (aaa[a] == ',') { strcpy(bbb, &aaa[a + 1]); aaa[a] = 0; break; } } if (!strcasecmp(name, aaa)) strcpy(name, bbb); } fclose(fp); /* Hit the Global Address Book */ if (CtdlDirectoryLookup(aaa, name, sizeof aaa) == 0) { strcpy(name, aaa); } if (strcasecmp(original_name, name)) { MSG_syslog(LOG_INFO, "%s is being forwarded to %s\n", original_name, name); } /* Change "user @ xxx" to "user" if xxx is an alias for this host */ for (a=0; name[a] != '\0'; ++a) { if (name[a] == '@') { if (CtdlHostAlias(&name[a+1]) == hostalias_localhost) { name[a] = 0; MSG_syslog(LOG_INFO, "Changed to <%s>\n", name); break; } } } /* determine local or remote type, see citadel.h */ at = haschar(name, '@'); if (at == 0) return(MES_LOCAL); /* no @'s - local address */ if (at > 1) return(MES_ERROR); /* >1 @'s - invalid address */ remove_any_whitespace_to_the_left_or_right_of_at_symbol(name); /* figure out the delivery mode */ extract_token(node, name, 1, '@', sizeof node); /* If there are one or more dots in the nodename, we assume that it * is an FQDN and will attempt SMTP delivery to the Internet. */ if (haschar(node, '.') > 0) { return(MES_INTERNET); } /* Otherwise we look in the IGnet maps for a valid Citadel node. * Try directly-connected nodes first... */ ignetcfg = CtdlGetSysConfig(IGNETCFG); for (i=0; i<num_tokens(ignetcfg, '\n'); ++i) { extract_token(buf, ignetcfg, i, '\n', sizeof buf); extract_token(testnode, buf, 0, '|', sizeof testnode); if (!strcasecmp(node, testnode)) { free(ignetcfg); return(MES_IGNET); } } free(ignetcfg); /* * Then try nodes that are two or more hops away. */ ignetmap = CtdlGetSysConfig(IGNETMAP); for (i=0; i<num_tokens(ignetmap, '\n'); ++i) { extract_token(buf, ignetmap, i, '\n', sizeof buf); extract_token(testnode, buf, 0, '|', sizeof testnode); if (!strcasecmp(node, testnode)) { free(ignetmap); return(MES_IGNET); } } free(ignetmap); /* If we get to this point it's an invalid node name */ return (MES_ERROR); }
/* * Harvest any email addresses that someone might want to have in their * "collected addresses" book. */ char *harvest_collected_addresses(struct CtdlMessage *msg) { char *coll = NULL; char addr[256]; char user[256], node[256], name[256]; int is_harvestable; int i, j, h; eMsgField field = 0; if (msg == NULL) return(NULL); is_harvestable = 1; strcpy(addr, ""); if (!CM_IsEmpty(msg, eAuthor)) { strcat(addr, msg->cm_fields[eAuthor]); } if (!CM_IsEmpty(msg, erFc822Addr)) { strcat(addr, " <"); strcat(addr, msg->cm_fields[erFc822Addr]); strcat(addr, ">"); if (IsDirectory(msg->cm_fields[erFc822Addr], 0)) { is_harvestable = 0; } } if (is_harvestable) { coll = strdup(addr); } else { coll = strdup(""); } if (coll == NULL) return(NULL); /* Scan both the R (To) and Y (CC) fields */ for (i = 0; i < 2; ++i) { if (i == 0) field = eRecipient; if (i == 1) field = eCarbonCopY; if (!CM_IsEmpty(msg, field)) { for (j=0; j<num_tokens(msg->cm_fields[field], ','); ++j) { extract_token(addr, msg->cm_fields[field], j, ',', sizeof addr); if (strstr(addr, "=?") != NULL) utf8ify_rfc822_string(addr); process_rfc822_addr(addr, user, node, name); h = CtdlHostAlias(node); if ( (h != hostalias_localhost) && (h != hostalias_directory) ) { coll = realloc(coll, strlen(coll) + strlen(addr) + 4); if (coll == NULL) return(NULL); if (!IsEmptyStr(coll)) { strcat(coll, ","); } striplt(addr); strcat(coll, addr); } } } } if (IsEmptyStr(coll)) { free(coll); return(NULL); } return(coll); }