masqmail

changeset 388:aa40710f09fe

Refactoring and code layouting.
author markus schnalke <meillo@marmaro.de>
date Sat, 18 Feb 2012 13:37:40 +0100
parents a408411ff8df
children bc9a7845b53a
files src/accept.c
diffstat 1 files changed, 280 insertions(+), 227 deletions(-) [+]
line diff
     1.1 --- a/src/accept.c	Sat Feb 18 12:35:12 2012 +0100
     1.2 +++ b/src/accept.c	Sat Feb 18 13:37:40 2012 +0100
     1.3 @@ -32,7 +32,8 @@
     1.4  static gchar*
     1.5  string_base62(gchar *res, guint value, gchar len)
     1.6  {
     1.7 -	static gchar base62_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     1.8 +	static gchar base62_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     1.9 +			"abcdefghijklmnopqrstuvwxyz";
    1.10  	gchar *p = res + len;
    1.11  	*p = '\0';
    1.12  	while (p > res) {
    1.13 @@ -49,7 +50,6 @@
    1.14  **  The -t option: With the ACC_RCPT_FROM_HEAD flag the addrs found found
    1.15  **  in To/Cc/Bcc headers are added to the recipient list.
    1.16  */
    1.17 -
    1.18  accept_error
    1.19  accept_message_stream(FILE *in, message *msg, guint flags)
    1.20  {
    1.21 @@ -60,14 +60,14 @@
    1.22  	gint line_cnt = 0, data_size = 0;
    1.23  
    1.24  	line = g_malloc(line_size);
    1.25 -	line[0] = '\0';
    1.26 +	*line = '\0';
    1.27  
    1.28 -	while (TRUE) {
    1.29 -		int len = read_sockline1(in, &line, &line_size, 5 * 60, READSOCKL_CVT_CRLF);
    1.30 -
    1.31 +	while (1) {
    1.32 +		int len = read_sockline1(in, &line, &line_size, 5 * 60,
    1.33 +				READSOCKL_CVT_CRLF);
    1.34  		line1 = line;
    1.35  
    1.36 -		if ((line[0] == '.') && (!(flags & ACC_DOT_IGNORE))) {
    1.37 +		if ((*line == '.') && (!(flags & ACC_DOT_IGNORE))) {
    1.38  			if (line[1] == '\n') {
    1.39  				g_free(line);
    1.40  				break;
    1.41 @@ -75,17 +75,17 @@
    1.42  			line1++;
    1.43  		}
    1.44  
    1.45 -		if ((len == -1) && (flags & (ACC_DOT_IGNORE | ACC_NODOT_RELAX))) {
    1.46 -			/* we got an EOF, and the last line was not terminated by a CR */
    1.47 +		if (len==-1 && (flags & (ACC_DOT_IGNORE | ACC_NODOT_RELAX))) {
    1.48 +			/* at EOF but last line was not terminated by CR */
    1.49 +			/* some MUAs allow unterminated lines */
    1.50  			gint len1 = strlen(line1);
    1.51 -			if (len1 > 0) {  /* == 0 is 'normal' (EOF after a CR) */
    1.52 -				if (line1[len1 - 1] != '\n') {  /* some mail clients allow unterminated lines */
    1.53 -					line1[len1] = '\n';
    1.54 -					line1[len1 + 1] = '\0';
    1.55 -					msg->data_list = g_list_prepend(msg->data_list, g_strdup(line1));
    1.56 -					data_size += strlen(line1);
    1.57 -					line_cnt++;
    1.58 -				}
    1.59 +			if (len1 > 0 && line1[len1-1] != '\n') {
    1.60 +				line1[len1] = '\n';
    1.61 +				line1[len1+1] = '\0';
    1.62 +				msg->data_list = g_list_prepend(msg->data_list,
    1.63 +						g_strdup(line1));
    1.64 +				data_size += strlen(line1);
    1.65 +				line_cnt++;
    1.66  			}
    1.67  			break;
    1.68  
    1.69 @@ -111,45 +111,44 @@
    1.70  		}
    1.71  
    1.72  		if (in_headers) {
    1.73 -
    1.74  			/* some pop servers send the 'From ' line, skip it: */
    1.75 -			if (!msg->hdr_list && strncmp(line1, "From ", 5) == 0) {
    1.76 +			if (!msg->hdr_list && strncmp(line1, "From ", 5)==0) {
    1.77  				continue;
    1.78  			}
    1.79  
    1.80 -			if (line1[0] == ' ' || line1[0] == '\t') {
    1.81 +			if (*line1 == ' ' || *line1 == '\t') {
    1.82  				/* continuation of 'folded' header: */
    1.83  				if (hdr) {
    1.84  					char *cp;
    1.85 -					cp = g_strconcat(hdr->header, line1, NULL);
    1.86 -					hdr->value = cp + (hdr->value - hdr->header);
    1.87 +					cp = g_strconcat(hdr->header, line1,
    1.88 +							NULL);
    1.89 +					hdr->value = cp + (hdr->value -
    1.90 +							hdr->header);
    1.91  					free(hdr->header);
    1.92  					hdr->header = cp;
    1.93  				}
    1.94 -
    1.95 -			} else if (line1[0] == '\n') {
    1.96 +			} else if (*line1 == '\n') {
    1.97  				/* an empty line marks end of headers */
    1.98  				in_headers = FALSE;
    1.99 +
   1.100 +			} else if ((hdr = get_header(line1))) {
   1.101 +				/* another header */
   1.102 +				msg->hdr_list = g_list_append(msg->hdr_list, hdr);
   1.103  			} else {
   1.104 -				/* in all other cases we expect another header */
   1.105 -				if ((hdr = get_header(line1))) {
   1.106 -					msg->hdr_list = g_list_append(msg->hdr_list, hdr);
   1.107 -				} else {
   1.108 -					/*
   1.109 -					**  if get_header() returns NULL,
   1.110 -					**  no header was recognized,
   1.111 -					**  so this seems to be the first
   1.112 -					**  data line of a broken mailer
   1.113 -					**  which does not send an empty
   1.114 -					**  line after the headers
   1.115 -					*/
   1.116 -					in_headers = FALSE;
   1.117 -					msg->data_list = g_list_prepend(msg->data_list, g_strdup(line1));
   1.118 -				}
   1.119 +				/*
   1.120 +				**  Should be another header but none was
   1.121 +				**  recognized, so this seems to be the first
   1.122 +				**  data line of a broken mailer which does
   1.123 +				**  not add an empty line after the headers.
   1.124 +				*/
   1.125 +				in_headers = FALSE;
   1.126 +				msg->data_list = g_list_prepend(msg->data_list,
   1.127 +						g_strdup(line1));
   1.128  			}
   1.129  		} else {
   1.130  			/* message body */
   1.131 -			msg->data_list = g_list_prepend(msg->data_list, g_strdup(line1));
   1.132 +			msg->data_list = g_list_prepend(msg->data_list,
   1.133 +					g_strdup(line1));
   1.134  			data_size += strlen(line1);
   1.135  			line_cnt++;
   1.136  		}
   1.137 @@ -160,18 +159,17 @@
   1.138  			                data_size, conf.max_msg_size);
   1.139  			return AERR_SIZE;
   1.140  		}
   1.141 -
   1.142  	}
   1.143 -
   1.144 -	DEBUG(4) debugf("received %d lines of data (%d bytes)\n", line_cnt, data_size);
   1.145 +	DEBUG(4) debugf("received %d lines of data (%d bytes)\n",
   1.146 +			line_cnt, data_size);
   1.147  
   1.148  	if (!msg->data_list) {
   1.149 -		/* make sure data list is not NULL: */
   1.150 +		/* make sure data list is not NULL */
   1.151  		msg->data_list = g_list_append(NULL, g_strdup(""));
   1.152  	}
   1.153  	msg->data_list = g_list_reverse(msg->data_list);
   1.154  
   1.155 -	/* we get here after we succesfully received the mail data */
   1.156 +	/* we have succesfully received the mail data */
   1.157  
   1.158  	msg->data_size = data_size;
   1.159  	msg->received_time = time(NULL);
   1.160 @@ -179,17 +177,239 @@
   1.161  	return AERR_OK;
   1.162  }
   1.163  
   1.164 +static void
   1.165 +ensure_return_path(message *msg)
   1.166 +{
   1.167 +	GList *hdr_list;
   1.168 +	header *hdr;
   1.169 +	gchar *addr;
   1.170 +
   1.171 +	if (msg->return_path) {
   1.172 +		return;
   1.173 +	}
   1.174 +
   1.175 +	DEBUG(3) debugf("return_path == NULL\n");
   1.176 +
   1.177 +	hdr_list = find_header(msg->hdr_list, HEAD_SENDER, NULL);
   1.178 +	if (!hdr_list) {
   1.179 +		hdr_list = find_header(msg->hdr_list, HEAD_FROM, NULL);
   1.180 +	}
   1.181 +	if (hdr_list) {
   1.182 +		hdr = (header *) (g_list_first(hdr_list)->data);
   1.183 +
   1.184 +		DEBUG(5) debugf("hdr->value = '%s'\n", hdr->value);
   1.185 +
   1.186 +		addr = g_strdup(hdr->value);
   1.187 +		g_strchomp(addr);
   1.188 +		msg->return_path = create_address_qualified(addr,
   1.189 +				FALSE, msg->received_host);
   1.190 +		if (msg->return_path) {
   1.191 +			DEBUG(3) debugf("setting return_path to %s\n",
   1.192 +					addr_string(msg->return_path));
   1.193 +			msg->hdr_list = g_list_append(msg->hdr_list,
   1.194 +					create_header(HEAD_UNKNOWN,
   1.195 +					"X-Warning: return path set from %s "
   1.196 +					"address\n",
   1.197 +					(hdr->id == HEAD_SENDER) ?
   1.198 +					"Sender:" : "From:"));
   1.199 +		}
   1.200 +		g_free(addr);
   1.201 +	}
   1.202 +	if (!msg->return_path) {
   1.203 +		/* no Sender: or From: or create_address_qualified failed */
   1.204 +		msg->return_path = create_address_qualified("postmaster",
   1.205 +				TRUE, conf.host_name);
   1.206 +		DEBUG(3) debugf("setting return_path to %s\n",
   1.207 +				addr_string(msg->return_path));
   1.208 +		msg->hdr_list = g_list_append(msg->hdr_list,
   1.209 +				create_header(HEAD_UNKNOWN,
   1.210 +				"X-Warning: real return path is unknown\n"));
   1.211 +	}
   1.212 +}
   1.213 +
   1.214 +static accept_error
   1.215 +scan_headers(message *msg, guint flags)
   1.216 +{
   1.217 +	gboolean has_id = FALSE;
   1.218 +	gboolean has_date = FALSE;
   1.219 +	gboolean has_sender = FALSE;
   1.220 +	gboolean has_from = FALSE;
   1.221 +	gboolean has_to_or_cc = FALSE;
   1.222 +	GList *hdr_node, *hdr_node_next;
   1.223 +	header *hdr;
   1.224 +
   1.225 +	for (hdr_node = g_list_first(msg->hdr_list); hdr_node;
   1.226 +			hdr_node = hdr_node_next) {
   1.227 +		hdr_node_next = g_list_next(hdr_node);
   1.228 +		hdr = ((header *) (hdr_node->data));
   1.229 +		DEBUG(5) debugf("scanning headers: %s", hdr->header);
   1.230 +		switch (hdr->id) {
   1.231 +		case HEAD_MESSAGE_ID:
   1.232 +			has_id = TRUE;
   1.233 +			break;
   1.234 +		case HEAD_DATE:
   1.235 +			has_date = TRUE;
   1.236 +			break;
   1.237 +		case HEAD_FROM:
   1.238 +			has_from = TRUE;
   1.239 +			break;
   1.240 +		case HEAD_SENDER:
   1.241 +			has_sender = TRUE;
   1.242 +			break;
   1.243 +		case HEAD_TO:
   1.244 +		case HEAD_CC:
   1.245 +			has_to_or_cc = TRUE;
   1.246 +			/* fall through */
   1.247 +		case HEAD_BCC:
   1.248 +			if (flags & ACC_RCPT_FROM_HEAD) {
   1.249 +				/* -t option (see comment above) */
   1.250 +				DEBUG(5) debugf("hdr->value = %s\n",
   1.251 +						hdr->value);
   1.252 +				if (hdr->value) {
   1.253 +					msg->rcpt_list = addr_list_append_rfc822(msg->rcpt_list, hdr->value, conf.host_name);
   1.254 +				}
   1.255 +			}
   1.256 +			if (hdr->id == HEAD_BCC) {
   1.257 +				DEBUG(3) debugf("removing 'Bcc' header\n");
   1.258 +				msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node);
   1.259 +				g_list_free_1(hdr_node);
   1.260 +				destroy_header(hdr);
   1.261 +			}
   1.262 +			break;
   1.263 +		case HEAD_ENVELOPE_TO:
   1.264 +			if (flags & ACC_SAVE_ENVELOPE_TO) {
   1.265 +				DEBUG(3) debugf("creating 'X-Orig-Envelope-To' header\n");
   1.266 +				msg->hdr_list = g_list_prepend(msg->hdr_list,
   1.267 +						create_header(HEAD_UNKNOWN,
   1.268 +						"X-Orig-Envelope-To: %s",
   1.269 +						hdr->value));
   1.270 +			}
   1.271 +			DEBUG(3) debugf("removing 'Envelope-To' header\n");
   1.272 +			msg->hdr_list = g_list_remove_link(msg->hdr_list,
   1.273 +					hdr_node);
   1.274 +			g_list_free_1(hdr_node);
   1.275 +			destroy_header(hdr);
   1.276 +			break;
   1.277 +		case HEAD_RETURN_PATH:
   1.278 +			if (flags & ACC_MAIL_FROM_HEAD) {
   1.279 +				/* usually POP3 accept */
   1.280 +				msg->return_path = create_address_qualified(hdr->value, TRUE, msg->received_host);
   1.281 +				DEBUG(3) debugf("setting return_path to %s\n",
   1.282 +						addr_string(msg->return_path));
   1.283 +			}
   1.284 +			DEBUG(3) debugf("removing 'Return-Path' header\n");
   1.285 +			msg->hdr_list = g_list_remove_link(msg->hdr_list,
   1.286 +					hdr_node);
   1.287 +			g_list_free_1(hdr_node);
   1.288 +			destroy_header(hdr);
   1.289 +			break;
   1.290 +		default:
   1.291 +			break;  /* make compiler happy */
   1.292 +		}
   1.293 +	}
   1.294 +
   1.295 +	/*
   1.296 +	**  TODO: do we still need this as we don't fetch
   1.297 +	**        mail anymore?
   1.298 +	**  This can happen for pop3 accept only and if no
   1.299 +	**  Return-Path: header was given
   1.300 +	*/
   1.301 +	ensure_return_path(msg);
   1.302 +
   1.303 +	/* here we should have our recipients, fail if not: */
   1.304 +	if (!msg->rcpt_list) {
   1.305 +		logwrite(LOG_WARNING, "no recipients found in message\n");
   1.306 +		return AERR_NORCPT;
   1.307 +	}
   1.308 +
   1.309 +	if (!has_sender && !has_from) {
   1.310 +		DEBUG(3) debugf("adding 'From:' header\n");
   1.311 +		if (msg->full_sender_name) {
   1.312 +			msg->hdr_list = g_list_append(msg->hdr_list,
   1.313 +					create_header(HEAD_FROM,
   1.314 +					"From: \"%s\" <%s@%s>\n",
   1.315 +					msg->full_sender_name,
   1.316 +					msg->return_path->local_part,
   1.317 +					msg->return_path->domain));
   1.318 +		} else {
   1.319 +			msg->hdr_list = g_list_append(msg->hdr_list,
   1.320 +					create_header(HEAD_FROM,
   1.321 +					"From: <%s@%s>\n",
   1.322 +					msg->return_path->local_part,
   1.323 +					msg->return_path->domain));
   1.324 +		}
   1.325 +	}
   1.326 +	if (!has_to_or_cc) {
   1.327 +		DEBUG(3) debugf("no To: or Cc: header, hence adding "
   1.328 +				"`To: undisclosed recipients:;'\n");
   1.329 +		msg->hdr_list = g_list_append(msg->hdr_list,
   1.330 +				create_header(HEAD_TO,
   1.331 +				"To: undisclosed-recipients:;\n"));
   1.332 +	}
   1.333 +	if (!has_date) {
   1.334 +		DEBUG(3) debugf("adding 'Date:' header\n");
   1.335 +		msg->hdr_list = g_list_append(msg->hdr_list,
   1.336 +				create_header(HEAD_DATE, "Date: %s\n",
   1.337 +				rec_timestamp()));
   1.338 +	}
   1.339 +	if (!has_id) {
   1.340 +		DEBUG(3) debugf("adding 'Message-ID:' header\n");
   1.341 +		msg->hdr_list = g_list_append(msg->hdr_list,
   1.342 +				create_header(HEAD_MESSAGE_ID,
   1.343 +				"Message-ID: <%s@%s>\n",
   1.344 +				msg->uid, conf.host_name));
   1.345 +	}
   1.346 +
   1.347 +	return AERR_OK;
   1.348 +}
   1.349 +
   1.350 +static void
   1.351 +add_received_hdr(message *msg)
   1.352 +{
   1.353 +	gchar *for_string = NULL;
   1.354 +	header *hdr = NULL;
   1.355 +	address *addr;
   1.356 +
   1.357 +	DEBUG(3) debugf("adding 'Received:' header\n");
   1.358 +	if (g_list_length(msg->rcpt_list) == 1) {
   1.359 +		/* The `for' part only if exactly one rcpt is present */
   1.360 +		addr = (address *) (g_list_first(msg->rcpt_list)->data);
   1.361 +		for_string = g_strdup_printf("\n\tfor %s", addr_string(addr));
   1.362 +	}
   1.363 +	if (!msg->received_host) {
   1.364 +		/* received locally */
   1.365 +		hdr = create_header(HEAD_RECEIVED,
   1.366 +				"Received: by %s (%s %s, from userid %d)\n"
   1.367 +				"\tid %s%s; %s\n",
   1.368 +				conf.host_name, PACKAGE, VERSION, geteuid(),
   1.369 +				msg->uid,
   1.370 +				for_string ? for_string : "", rec_timestamp());
   1.371 +	} else {
   1.372 +		/* received from remote */
   1.373 +		DEBUG(5) debugf("adding 'Received:' header (5)\n");
   1.374 +		hdr = create_header(HEAD_RECEIVED,
   1.375 +				"Received: from %s\n"
   1.376 +				"\tby %s with %s (%s %s)\n"
   1.377 +				"\tid %s%s; %s\n",
   1.378 +				msg->received_host, conf.host_name,
   1.379 +				prot_names[msg->received_prot], PACKAGE,
   1.380 +				VERSION, msg->uid,
   1.381 +				for_string ? for_string : "", rec_timestamp());
   1.382 +	}
   1.383 +	msg->hdr_list = g_list_prepend(msg->hdr_list, hdr);
   1.384 +	if (for_string) {
   1.385 +		g_free(for_string);
   1.386 +	}
   1.387 +}
   1.388 +
   1.389  accept_error
   1.390  accept_message_prepare(message *msg, guint flags)
   1.391  {
   1.392 -	struct passwd *passwd = NULL;
   1.393 -	time_t rec_time = time(NULL);
   1.394 -
   1.395  	DEBUG(5) debugf("accept_message_prepare()\n");
   1.396  
   1.397 -	/* create unique message id */
   1.398 +	/* generate unique message id */
   1.399  	msg->uid = g_malloc(14);
   1.400 -	string_base62(msg->uid, rec_time, 6);
   1.401 +	string_base62(msg->uid, time(NULL), 6);
   1.402  	msg->uid[6] = '-';
   1.403  	string_base62(msg->uid + 7, getpid(), 3);
   1.404  	msg->uid[10] = '-';
   1.405 @@ -198,193 +418,26 @@
   1.406  
   1.407  	/* if local, get password entry and set return path if missing */
   1.408  	if (!msg->received_host) {
   1.409 +		struct passwd *passwd = NULL;
   1.410 +
   1.411  		passwd = g_memdup(getpwuid(geteuid()), sizeof(struct passwd));
   1.412  		msg->ident = g_strdup(passwd->pw_name);
   1.413  		if (!msg->return_path) {
   1.414 -			gchar *path = g_strdup_printf("<%s@%s>", passwd->pw_name, conf.host_name);
   1.415 -			DEBUG(3) debugf("setting return_path for local accept: %s\n", path);
   1.416 +			gchar *path = g_strdup_printf("<%s@%s>",
   1.417 +					passwd->pw_name, conf.host_name);
   1.418 +			DEBUG(3) debugf("setting return_path for local "
   1.419 +					"accept: %s\n", path);
   1.420  			msg->return_path = create_address(path, TRUE);
   1.421  			g_free(path);
   1.422  		}
   1.423  	}
   1.424  
   1.425 -	/* scan headers */
   1.426 -	{
   1.427 -		gboolean has_id = FALSE;
   1.428 -		gboolean has_date = FALSE;
   1.429 -		gboolean has_sender = FALSE;
   1.430 -		gboolean has_from = FALSE;
   1.431 -		gboolean has_to_or_cc = FALSE;
   1.432 -		GList *hdr_node, *hdr_node_next;
   1.433 -		header *hdr;
   1.434 -
   1.435 -		for (hdr_node = g_list_first(msg->hdr_list);
   1.436 -		     hdr_node;
   1.437 -		     hdr_node = hdr_node_next) {
   1.438 -			hdr_node_next = g_list_next(hdr_node);
   1.439 -			hdr = ((header *) (hdr_node->data));
   1.440 -			DEBUG(5) debugf("scanning headers: %s", hdr->header);
   1.441 -			switch (hdr->id) {
   1.442 -			case HEAD_MESSAGE_ID:
   1.443 -				has_id = TRUE;
   1.444 -				break;
   1.445 -			case HEAD_DATE:
   1.446 -				has_date = TRUE;
   1.447 -				break;
   1.448 -			case HEAD_FROM:
   1.449 -				has_from = TRUE;
   1.450 -				break;
   1.451 -			case HEAD_SENDER:
   1.452 -				has_sender = TRUE;
   1.453 -				break;
   1.454 -			case HEAD_TO:
   1.455 -			case HEAD_CC:
   1.456 -				has_to_or_cc = TRUE;
   1.457 -				/* fall through */
   1.458 -			case HEAD_BCC:
   1.459 -				if (flags & ACC_RCPT_FROM_HEAD) {
   1.460 -					/* -t option (see comment above) */
   1.461 -					DEBUG(5) debugf("hdr->value = %s\n", hdr->value);
   1.462 -					if (hdr->value) {
   1.463 -						msg->rcpt_list = addr_list_append_rfc822(msg->rcpt_list, hdr->value, conf.host_name);
   1.464 -					}
   1.465 -				}
   1.466 -				if (hdr->id == HEAD_BCC) {
   1.467 -					DEBUG(3) debugf("removing 'Bcc' header\n");
   1.468 -					msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node);
   1.469 -					g_list_free_1(hdr_node);
   1.470 -					destroy_header(hdr);
   1.471 -				}
   1.472 -				break;
   1.473 -			case HEAD_ENVELOPE_TO:
   1.474 -				if (flags & ACC_SAVE_ENVELOPE_TO) {
   1.475 -					DEBUG(3) debugf("creating 'X-Orig-Envelope-To' header\n");
   1.476 -					msg->hdr_list = g_list_prepend(msg->hdr_list, create_header(HEAD_UNKNOWN,
   1.477 -					                               "X-Orig-Envelope-To: %s", hdr->value));
   1.478 -				}
   1.479 -				DEBUG(3) debugf("removing 'Envelope-To' header\n");
   1.480 -				msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node);
   1.481 -				g_list_free_1(hdr_node);
   1.482 -				destroy_header(hdr);
   1.483 -				break;
   1.484 -			case HEAD_RETURN_PATH:
   1.485 -				if (flags & ACC_MAIL_FROM_HEAD) {
   1.486 -					/* usually POP3 accept */
   1.487 -					msg->return_path = create_address_qualified(hdr->value, TRUE, msg->received_host);
   1.488 -					DEBUG(3) debugf("setting return_path to %s\n", addr_string(msg->return_path));
   1.489 -				}
   1.490 -				DEBUG(3) debugf("removing 'Return-Path' header\n");
   1.491 -				msg->hdr_list = g_list_remove_link(msg->hdr_list, hdr_node);
   1.492 -				g_list_free_1(hdr_node);
   1.493 -				destroy_header(hdr);
   1.494 -				break;
   1.495 -			default:
   1.496 -				break;  /* make compiler happy */
   1.497 -			}
   1.498 -		}
   1.499 -
   1.500 -		if (!msg->return_path) {
   1.501 -			/*
   1.502 -			**  TODO: do we still need this as we don't fetch
   1.503 -			**        mail anymore?
   1.504 -			**  This can happen for pop3 accept only and if no
   1.505 -			**  Return-Path: header was given
   1.506 -			*/
   1.507 -			GList *hdr_list;
   1.508 -			header *hdr;
   1.509 -
   1.510 -			DEBUG(3) debugf("return_path == NULL\n");
   1.511 -
   1.512 -			hdr_list = find_header(msg->hdr_list, HEAD_SENDER, NULL);
   1.513 -			if (!hdr_list) {
   1.514 -				hdr_list = find_header(msg->hdr_list, HEAD_FROM, NULL);
   1.515 -			}
   1.516 -			if (hdr_list) {
   1.517 -				gchar *addr;
   1.518 -				hdr = (header *) (g_list_first(hdr_list)->data);
   1.519 -
   1.520 -				DEBUG(5) debugf("hdr->value = '%s'\n", hdr->value);
   1.521 -
   1.522 -				addr = g_strdup(hdr->value);
   1.523 -				g_strchomp(addr);
   1.524 -
   1.525 -				msg->return_path = create_address_qualified(addr, FALSE, msg->received_host);
   1.526 -				if (msg->return_path) {
   1.527 -					DEBUG(3) debugf("setting return_path to %s\n", addr_string(msg->return_path));
   1.528 -					msg->hdr_list = g_list_append( msg->hdr_list, create_header(HEAD_UNKNOWN, "X-Warning: return path set from %s address\n", hdr->id == HEAD_SENDER ? "Sender:" : "From:"));
   1.529 -				}
   1.530 -				g_free(addr);
   1.531 -			}
   1.532 -			if (!msg->return_path) {
   1.533 -				/* no Sender: or From: or
   1.534 -				   create_address_qualified failed */
   1.535 -				msg->return_path = create_address_qualified("postmaster", TRUE, conf.host_name);
   1.536 -				DEBUG(3) debugf("setting return_path to %s\n", addr_string(msg->return_path));
   1.537 -				msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_UNKNOWN, "X-Warning: real return path is unknown\n"));
   1.538 -			}
   1.539 -		}
   1.540 -
   1.541 -		/* here we should have our recipients, fail if not: */
   1.542 -		if (!msg->rcpt_list) {
   1.543 -			logwrite(LOG_WARNING, "no recipients found in message\n");
   1.544 -			return AERR_NORCPT;
   1.545 -		}
   1.546 -
   1.547 -		if (!has_sender && !has_from) {
   1.548 -			DEBUG(3) debugf("adding 'From:' header\n");
   1.549 -			if (msg->full_sender_name) {
   1.550 -				msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_FROM, "From: \"%s\" <%s@%s>\n", msg->full_sender_name, msg->return_path->local_part, msg->return_path->domain));
   1.551 -			} else {
   1.552 -				msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_FROM, "From: <%s@%s>\n", msg->return_path->local_part, msg->return_path->domain));
   1.553 -			}
   1.554 -		}
   1.555 -		if (!has_to_or_cc) {
   1.556 -			DEBUG(3) debugf("no To: or Cc: header, hence adding `To: undisclosed recipients:;'\n");
   1.557 -			msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_TO, "To: undisclosed-recipients:;\n"));
   1.558 -		}
   1.559 -		if (!has_date) {
   1.560 -			DEBUG(3) debugf("adding 'Date:' header\n");
   1.561 -			msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_DATE, "Date: %s\n", rec_timestamp()));
   1.562 -		}
   1.563 -		if (!has_id) {
   1.564 -			DEBUG(3) debugf("adding 'Message-ID:' header\n");
   1.565 -			msg->hdr_list = g_list_append(msg->hdr_list, create_header(HEAD_MESSAGE_ID, "Message-ID: <%s@%s>\n", msg->uid, conf.host_name));
   1.566 -		}
   1.567 +	if (scan_headers(msg, flags) == AERR_NORCPT) {
   1.568 +		return AERR_NORCPT;
   1.569  	}
   1.570  
   1.571 -	/* Received header: */
   1.572 -	/* At this point because we have to know the rcpts for the 'for' part */
   1.573 -	/* The `for' part will only be used if exactly one rcpt is present. */
   1.574 -	gchar *for_string = NULL;
   1.575 -	header *hdr = NULL;
   1.576 -
   1.577 -	DEBUG(3) debugf("adding 'Received:' header\n");
   1.578 -
   1.579 -	if (g_list_length(msg->rcpt_list) == 1) {
   1.580 -		address *addr = (address *) (g_list_first(msg->rcpt_list)->data);
   1.581 -		for_string = g_strdup_printf("\n\tfor %s", addr_string(addr));
   1.582 -	}
   1.583 -
   1.584 -	if (!msg->received_host) {
   1.585 -		/* received locally */
   1.586 -		hdr = create_header(HEAD_RECEIVED,
   1.587 -		    "Received: by %s (%s %s, from userid %d)\n\tid %s%s; %s\n",
   1.588 -		    conf.host_name, PACKAGE, VERSION, geteuid(),
   1.589 -		    msg->uid, for_string ? for_string : "", rec_timestamp());
   1.590 -	} else {
   1.591 -		/* received from remote */
   1.592 -		DEBUG(5) debugf("adding 'Received:' header (5)\n");
   1.593 -		hdr = create_header(HEAD_RECEIVED,
   1.594 -		    "Received: from %s\n\tby %s with %s (%s %s)\n\tid %s%s; %s\n",
   1.595 -		    msg->received_host,
   1.596 -		    conf.host_name, prot_names[msg->received_prot], PACKAGE,
   1.597 -		    VERSION, msg->uid, for_string ? for_string : "",
   1.598 -		    rec_timestamp());
   1.599 -	}
   1.600 -	msg->hdr_list = g_list_prepend(msg->hdr_list, hdr);
   1.601 -
   1.602 -	if (for_string)
   1.603 -		g_free(for_string);
   1.604 +	/* after the hdrs are scanned because we need to know the rcpts */
   1.605 +	add_received_hdr(msg);
   1.606  
   1.607  	return AERR_OK;
   1.608  }