Beispiel #1
0
int smtp_resolve_recipients(SmtpOutMsg *Msg)
{
	AsyncIO *IO = &Msg->IO;
	const char *ptr;
	char buf[1024];
	int scan_done;
	int lp, rp;
	int i;

	EVNCS_syslog(LOG_DEBUG, "%s\n", __FUNCTION__);

	if ((Msg==NULL) ||
	    (Msg->MyQEntry == NULL) ||
	    (StrLength(Msg->MyQEntry->Recipient) == 0)) {
		return 0;
	}

	/* Parse out the host portion of the recipient address */
	process_rfc822_addr(ChrPtr(Msg->MyQEntry->Recipient),
			    Msg->user,
			    Msg->node,
			    Msg->name);

	EVNCS_syslog(LOG_DEBUG,
		     "Attempting delivery to <%s> @ <%s> (%s)\n",
		     Msg->user,
		     Msg->node,
		     Msg->name);

	/* If no envelope_from is supplied, extract one from the message */
	Msg->envelope_from = ChrPtr(Msg->MyQItem->EnvelopeFrom);
	if ( (Msg->envelope_from == NULL) ||
	     (IsEmptyStr(Msg->envelope_from)) ) {
		Msg->mailfrom[0] = '\0';
		scan_done = 0;
		ptr = ChrPtr(Msg->msgtext);
		do {
			if (ptr = cmemreadline(ptr, buf, sizeof buf), *ptr == 0)
			{
				scan_done = 1;
			}
			if (!strncasecmp(buf, "From:", 5))
			{
				safestrncpy(Msg->mailfrom,
					    &buf[5],
					    sizeof Msg->mailfrom);

				striplt(Msg->mailfrom);
				for (i=0; Msg->mailfrom[i]; ++i) {
					if (!isprint(Msg->mailfrom[i]))
					{
						strcpy(&Msg->mailfrom[i],
						       &Msg->mailfrom[i+1]);
						i=0;
					}
				}

				/* Strip out parenthesized names */
				lp = (-1);
				rp = (-1);
				for (i=0;
				     !IsEmptyStr(Msg->mailfrom + i);
				     ++i)
				{
					if (Msg->mailfrom[i] == '(') lp = i;
					if (Msg->mailfrom[i] == ')') rp = i;
				}
				if ((lp>0)&&(rp>lp))
				{
					strcpy(&Msg->mailfrom[lp-1],
					       &Msg->mailfrom[rp+1]);
				}

				/* Prefer brokketized names */
				lp = (-1);
				rp = (-1);
				for (i=0;
				     !IsEmptyStr(Msg->mailfrom + i);
				     ++i)
				{
					if (Msg->mailfrom[i] == '<') lp = i;
					if (Msg->mailfrom[i] == '>') rp = i;
				}
				if ( (lp>=0) && (rp>lp) ) {
					Msg->mailfrom[rp] = 0;
					memmove(Msg->mailfrom,
						&Msg->mailfrom[lp + 1],
						rp - lp);
				}

				scan_done = 1;
			}
		} while (scan_done == 0);
		if (IsEmptyStr(Msg->mailfrom))
			strcpy(Msg->mailfrom, "*****@*****.**");

		stripallbut(Msg->mailfrom, '<', '>');
		Msg->envelope_from = Msg->mailfrom;
	}

	return 1;
}
/*
 * 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);
}
Beispiel #3
0
static long parse_MimeHeaders(interesting_mime_headers *m, 
			      char** pcontent_start, 
			      char *content_end)
{
	char buf[SIZ];
	char header[SIZ];
	long headerlen;
	char *ptr, *pch;
	int buflen = 0;
	int i;

	/* Learn interesting things from the headers */
	ptr = *pcontent_start;
	*header = '\0';
	headerlen = 0;
	do {
		ptr = memreadlinelen(ptr, buf, SIZ, &buflen);

		for (i = 0; i < buflen; ++i) {
			if (isspace(buf[i])) {
				buf[i] = ' ';
			}
		}

		if (!isspace(buf[0]) && (headerlen > 0)) {
			if (!strncasecmp(header, "Content-type:", 13)) {
				memcpy (m->b[content_type].Key, &header[13], headerlen - 12);
				m->b[content_type].Key[headerlen - 12] = '\0';
				m->b[content_type].len = striplt (m->b[content_type].Key);

				m->b[content_type_name].len = extract_key(m->b[content_type_name].Key, CKEY(m->b[content_type]), HKEY("name"), '=');
				m->b[charset].len           = extract_key(m->b[charset].Key,           CKEY(m->b[content_type]), HKEY("charset"), '=');
				m->b[boundary].len          = extract_key(m->b[boundary].Key,          header,       headerlen,  HKEY("boundary"), '=');

				/* Deal with weird headers */
				pch = strchr(m->b[content_type].Key, ' ');
				if (pch != NULL) {
					*pch = '\0';
					m->b[content_type].len = m->b[content_type].Key - pch;
				}
				pch = strchr(m->b[content_type].Key, ';');
				if (pch != NULL) {
					*pch = '\0';
					m->b[content_type].len = m->b[content_type].Key - pch;
				}
			}
			else if (!strncasecmp(header, "Content-Disposition:", 20)) {
				memcpy (m->b[disposition].Key, &header[20], headerlen - 19);
				m->b[disposition].Key[headerlen - 19] = '\0';
				m->b[disposition].len = striplt(m->b[disposition].Key);

				m->b[content_disposition_name].len = extract_key(m->b[content_disposition_name].Key, CKEY(m->b[disposition]), HKEY("name"), '=');
				m->b[filename].len                 = extract_key(m->b[filename].Key,                 CKEY(m->b[disposition]), HKEY("filename"), '=');
				pch = strchr(m->b[disposition].Key, ';');
				if (pch != NULL) *pch = '\0';
				m->b[disposition].len = striplt(m->b[disposition].Key);
			}
			else if (!strncasecmp(header, "Content-ID:", 11)) {
				memcpy(m->b[id].Key, &header[11], headerlen - 11);
				m->b[id].Key[headerlen - 11] = '\0';
				striplt(m->b[id].Key);
				m->b[id].len = stripallbut(m->b[id].Key, '<', '>');
			}
			else if (!strncasecmp(header, "Content-length: ", 15)) {
				char *clbuf;
				clbuf = &header[15];
				while (isspace(*clbuf))
					clbuf ++;
				m->content_length = (size_t) atol(clbuf);
			}
			else if (!strncasecmp(header, "Content-transfer-encoding: ", 26)) {
				memcpy(m->b[encoding].Key, &header[26], headerlen - 26);
				m->b[encoding].Key[headerlen - 26] = '\0';
				m->b[encoding].len = striplt(m->b[encoding].Key);
			}
			*header = '\0';
			headerlen = 0;
		}
		if ((headerlen + buflen + 2) < SIZ) {
			memcpy(&header[headerlen], buf, buflen);
			headerlen += buflen;
			header[headerlen] = '\0';
		}
		if (ptr >= content_end) {
			return -1;
		}
	} while ((!IsEmptyStr(buf)) && (*ptr != 0));

	m->is_multipart = m->b[boundary].len != 0;
	*pcontent_start = ptr;

	return 0;
}
/*
 * Split an RFC822-style address into userid, host, and full name
 *
 */
void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name)
{
	int a;

	strcpy(user, "");
	strcpy(node, CtdlGetConfigStr("c_fqdn"));
	strcpy(name, "");

	if (rfc822 == NULL) return;

	/* extract full name - first, it's From minus <userid> */
	strcpy(name, rfc822);
	stripout(name, '<', '>');

	/* strip anything to the left of a bang */
	while ((!IsEmptyStr(name)) && (haschar(name, '!') > 0))
		strcpy(name, &name[1]);

	/* and anything to the right of a @ or % */
	for (a = 0; name[a] != '\0'; ++a) {
		if (name[a] == '@') {
			name[a] = 0;
			break;
		}
		if (name[a] == '%') {
			name[a] = 0;
			break;
		}
	}

	/* but if there are parentheses, that changes the rules... */
	if ((haschar(rfc822, '(') == 1) && (haschar(rfc822, ')') == 1)) {
		strcpy(name, rfc822);
		stripallbut(name, '(', ')');
	}

	/* but if there are a set of quotes, that supersedes everything */
	if (haschar(rfc822, 34) == 2) {
		strcpy(name, rfc822);
		while ((!IsEmptyStr(name)) && (name[0] != 34)) {
			strcpy(&name[0], &name[1]);
		}
		strcpy(&name[0], &name[1]);
		for (a = 0; name[a] != '\0'; ++a)
			if (name[a] == 34) {
				name[a] = 0;
				break;
			}
	}
	/* extract user id */
	strcpy(user, rfc822);

	/* first get rid of anything in parens */
	stripout(user, '(', ')');

	/* if there's a set of angle brackets, strip it down to that */
	if ((haschar(user, '<') == 1) && (haschar(user, '>') == 1)) {
		stripallbut(user, '<', '>');
	}

	/* strip anything to the left of a bang */
	while ((!IsEmptyStr(user)) && (haschar(user, '!') > 0))
		strcpy(user, &user[1]);

	/* and anything to the right of a @ or % */
	for (a = 0; user[a] != '\0'; ++a) {
		if (user[a] == '@') {
			user[a] = 0;
			break;
		}
		if (user[a] == '%') {
			user[a] = 0;
			break;
		}
	}


	/* extract node name */
	strcpy(node, rfc822);

	/* first get rid of anything in parens */
	stripout(node, '(', ')');

	/* if there's a set of angle brackets, strip it down to that */
	if ((haschar(node, '<') == 1) && (haschar(node, '>') == 1)) {
		stripallbut(node, '<', '>');
	}

	/* If no node specified, tack ours on instead */
	if (
		(haschar(node, '@')==0)
		&& (haschar(node, '%')==0)
		&& (haschar(node, '!')==0)
	) {
		strcpy(node, CtdlGetConfigStr("c_nodename"));
	}

	else {

		/* strip anything to the left of a @ */
		while ((!IsEmptyStr(node)) && (haschar(node, '@') > 0))
			strcpy(node, &node[1]);
	
		/* strip anything to the left of a % */
		while ((!IsEmptyStr(node)) && (haschar(node, '%') > 0))
			strcpy(node, &node[1]);
	
		/* reduce multiple system bang paths to node!user */
		while ((!IsEmptyStr(node)) && (haschar(node, '!') > 1))
			strcpy(node, &node[1]);
	
		/* now get rid of the user portion of a node!user string */
		for (a = 0; node[a] != '\0'; ++a)
			if (node[a] == '!') {
				node[a] = 0;
				break;
			}
	}

	/* strip leading and trailing spaces in all strings */
	striplt(user);
	striplt(node);
	striplt(name);

	/* If we processed a string that had the address in angle brackets
	 * but no name outside the brackets, we now have an empty name.  In
	 * this case, use the user portion of the address as the name.
	 */
	if ((IsEmptyStr(name)) && (!IsEmptyStr(user))) {
		strcpy(name, user);
	}
}