Пример #1
0
/*
 * 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);
}
Пример #2
0
/*
 * 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;
		}
	}
}
Пример #3
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;
}
Пример #4
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);
}
Пример #5
0
/*
 * 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);
}
Пример #6
0
/*
 * 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");
}
Пример #7
0
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);
}
Пример #8
0
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);
}
Пример #9
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;
}
Пример #10
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);
}
Пример #11
0
/*
 * 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);
}