Пример #1
0
int
readmail(struct queue *queue, int nodot, int recp_from_header)
{
	struct parse_state parse_state;
	char line[1000];	/* by RFC2822 */
	size_t linelen;
	size_t error;
	int had_headers = 0;
	int had_from = 0;
	int had_messagid = 0;
	int had_date = 0;
	int had_last_line = 0;
	int nocopy = 0;

	parse_state.state = NONE;

	error = fprintf(queue->mailf,
		"Received: from %s (uid %d)\n"
		"\t(envelope-from %s)\n"
		"\tid %s\n"
		"\tby %s (%s);\n"
		"\t%s\n",
		username, useruid,
		queue->sender,
		queue->id,
		hostname(), VERSION,
		rfc822date());
	if ((ssize_t)error < 0)
		return (-1);

	while (!feof(stdin)) {
		if (fgets(line, sizeof(line) - 1, stdin) == NULL)
			break;
		if (had_last_line)
			errlogx(1, "bad mail input format:"
				" from %s (uid %d) (envelope-from %s)",
				username, useruid, queue->sender);
		linelen = strlen(line);
		if (linelen == 0 || line[linelen - 1] != '\n') {
			/*
			 * This line did not end with a newline character.
			 * If we fix it, it better be the last line of
			 * the file.
			 */
			line[linelen] = '\n';
			line[linelen + 1] = 0;
			had_last_line = 1;
		}
		if (!had_headers) {
			/*
			 * Unless this is a continuation, switch of
			 * the Bcc: nocopy flag.
			 */
			if (!(line[0] == ' ' || line[0] == '\t'))
				nocopy = 0;

			if (strprefixcmp(line, "Date:") == 0)
				had_date = 1;
			else if (strprefixcmp(line, "Message-Id:") == 0)
				had_messagid = 1;
			else if (strprefixcmp(line, "From:") == 0)
				had_from = 1;
			else if (strprefixcmp(line, "Bcc:") == 0)
				nocopy = 1;

			if (parse_state.state != NONE) {
				if (parse_addrs(&parse_state, line, queue) < 0) {
					errlogx(1, "invalid address in header\n");
					/* NOTREACHED */
				}
			}

			if (recp_from_header && (
					strprefixcmp(line, "To:") == 0 ||
					strprefixcmp(line, "Cc:") == 0 ||
					strprefixcmp(line, "Bcc:") == 0)) {
				parse_state.state = START;
				if (parse_addrs(&parse_state, line, queue) < 0) {
					errlogx(1, "invalid address in header\n");
					/* NOTREACHED */
				}
			}
		}

		if (strcmp(line, "\n") == 0 && !had_headers) {
			had_headers = 1;
			while (!had_date || !had_messagid || !had_from) {
				if (!had_date) {
					had_date = 1;
					snprintf(line, sizeof(line), "Date: %s\n", rfc822date());
				} else if (!had_messagid) {
					/* XXX msgid, assign earlier and log? */
					had_messagid = 1;
					snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
						 (uintmax_t)time(NULL),
						 queue->id,
						 (uintmax_t)random(),
						 hostname());
				} else if (!had_from) {
					had_from = 1;
					snprintf(line, sizeof(line), "From: <%s>\n", queue->sender);
				}
				if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
					return (-1);
			}
			strcpy(line, "\n");
		}
		if (!nodot && linelen == 2 && line[0] == '.')
			break;
		if (!nocopy) {
			if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
				return (-1);
		}
	}

	return (0);
}
Пример #2
0
int
readmail(struct queue *queue, int nodot, int recp_from_header)
{
	struct parse_state parse_state;
	char *line = NULL;
	ssize_t linelen;
	size_t linecap = 0;
	char newline[MAX_LINE_RFC822];
	size_t error;
	int had_headers = 0;
	int had_from = 0;
	int had_messagid = 0;
	int had_date = 0;
	int nocopy = 0;
	int ret = -1;

	parse_state.state = NONE;

	error = fprintf(queue->mailf,
		"Received: from %s (uid %d)\n"
		"\t(envelope-from %s)\n"
		"\tid %s\n"
		"\tby %s (%s);\n"
		"\t%s\n",
		username, useruid,
		queue->sender,
		queue->id,
		hostname(), VERSION,
		rfc822date());
	if ((ssize_t)error < 0)
		return (-1);

	while (!feof(stdin)) {
		newline[0] = '\0';
		if ((linelen = getline(&line, &linecap, stdin)) <= 0)
			break;

		if (!had_headers) {
			if (linelen > MAX_LINE_RFC822) {
				/* XXX also split headers */
				errlogx(EX_DATAERR, "bad mail input format:"
				    " from %s (uid %d) (envelope-from %s)",
				    username, useruid, queue->sender);
			}
			/*
			 * Unless this is a continuation, switch of
			 * the Bcc: nocopy flag.
			 */
			if (!(line[0] == ' ' || line[0] == '\t'))
				nocopy = 0;

			if (strprefixcmp(line, "Date:") == 0)
				had_date = 1;
			else if (strprefixcmp(line, "Message-Id:") == 0)
				had_messagid = 1;
			else if (strprefixcmp(line, "From:") == 0)
				had_from = 1;
			else if (strprefixcmp(line, "Bcc:") == 0)
				nocopy = 1;

			if (parse_state.state != NONE) {
				if (parse_addrs(&parse_state, line, queue) < 0) {
					errlogx(EX_DATAERR, "invalid address in header\n");
					/* NOTREACHED */
				}
			}

			if (recp_from_header && (
					strprefixcmp(line, "To:") == 0 ||
					strprefixcmp(line, "Cc:") == 0 ||
					strprefixcmp(line, "Bcc:") == 0)) {
				parse_state.state = START;
				if (parse_addrs(&parse_state, line, queue) < 0) {
					errlogx(EX_DATAERR, "invalid address in header\n");
					/* NOTREACHED */
				}
			}
		}

		if (strcmp(line, "\n") == 0 && !had_headers) {
			had_headers = 1;
			while (!had_date || !had_messagid || !had_from) {
				if (!had_date) {
					had_date = 1;
					snprintf(newline, sizeof(newline), "Date: %s\n", rfc822date());
				} else if (!had_messagid) {
					/* XXX msgid, assign earlier and log? */
					had_messagid = 1;
					snprintf(newline, sizeof(newline), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
						 (uintmax_t)time(NULL),
						 queue->id,
						 (uintmax_t)random(),
						 hostname());
				} else if (!had_from) {
					had_from = 1;
					snprintf(newline, sizeof(newline), "From: <%s>\n", queue->sender);
				}
				if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
					goto fail;
			}
			strlcpy(newline, "\n", sizeof(newline));
		}
		if (!nodot && linelen == 2 && line[0] == '.')
			break;
		if (!nocopy) {
			if (newline[0]) {
				if (fwrite(newline, strlen(newline), 1, queue->mailf) != 1)
					goto fail;
			} else {
				if (writeline(queue, line, linelen) != 0)
					goto fail;
			}
		}
	}

	ret = 0;
fail:
	free(line);
	return (ret);
}