1/*	$NetBSD: qmgr_message.c,v 1.4 2022/10/08 16:12:46 christos Exp $	*/
2
3/*++
4/* NAME
5/*	qmgr_message 3
6/* SUMMARY
7/*	in-core message structures
8/* SYNOPSIS
9/*	#include "qmgr.h"
10/*
11/*	int	qmgr_message_count;
12/*	int	qmgr_recipient_count;
13/*	int	qmgr_vrfy_pend_count;
14/*
15/*	QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
16/*	const char *class;
17/*	const char *name;
18/*	int	qflags;
19/*	mode_t	mode;
20/*
21/*	QMGR_MESSAGE *qmgr_message_realloc(message)
22/*	QMGR_MESSAGE *message;
23/*
24/*	void	qmgr_message_free(message)
25/*	QMGR_MESSAGE *message;
26/*
27/*	void	qmgr_message_update_warn(message)
28/*	QMGR_MESSAGE *message;
29/*
30/*	void	qmgr_message_kill_record(message, offset)
31/*	QMGR_MESSAGE *message;
32/*	long	offset;
33/* DESCRIPTION
34/*	This module performs en-gross operations on queue messages.
35/*
36/*	qmgr_message_count is a global counter for the total number
37/*	of in-core message structures (i.e. the total size of the
38/*	`active' message queue).
39/*
40/*	qmgr_recipient_count is a global counter for the total number
41/*	of in-core recipient structures (i.e. the sum of all recipients
42/*	in all in-core message structures).
43/*
44/*	qmgr_vrfy_pend_count is a global counter for the total
45/*	number of in-core message structures that are associated
46/*	with an address verification request. Requests that exceed
47/*	the address_verify_pending_limit are deferred immediately.
48/*	This is a backup mechanism for a more refined enforcement
49/*	mechanism in the verify(8) daemon.
50/*
51/*	qmgr_message_alloc() creates an in-core message structure
52/*	with sender and recipient information taken from the named queue
53/*	file. A null result means the queue file could not be read or
54/*	that the queue file contained incorrect information. A result
55/*	QMGR_MESSAGE_LOCKED means delivery must be deferred. The number
56/*	of recipients read from a queue file is limited by the global
57/*	var_qmgr_rcpt_limit configuration parameter. When the limit
58/*	is reached, the \fIrcpt_offset\fR structure member is set to
59/*	the position where the read was terminated. Recipients are
60/*	run through the resolver, and are assigned to destination
61/*	queues. Recipients that cannot be assigned are deferred or
62/*	bounced. Mail that has bounced twice is silently absorbed.
63/*	A non-zero mode means change the queue file permissions.
64/*
65/*	qmgr_message_realloc() resumes reading recipients from the queue
66/*	file, and updates the recipient list and \fIrcpt_offset\fR message
67/*	structure members. A null result means that the file could not be
68/*	read or that the file contained incorrect information.
69/*
70/*	qmgr_message_free() destroys an in-core message structure and makes
71/*	the resources available for reuse. It is an error to destroy
72/*	a message structure that is still referenced by queue entry structures.
73/*
74/*	qmgr_message_update_warn() takes a closed message, opens it, updates
75/*	the warning field, and closes it again.
76/*
77/*	qmgr_message_kill_record() takes a closed message, opens it, updates
78/*	the record type at the given offset to "killed", and closes the file.
79/*	A killed envelope record is ignored. Killed records are not allowed
80/*	inside the message content.
81/* DIAGNOSTICS
82/*	Warnings: malformed message file. Fatal errors: out of memory.
83/* SEE ALSO
84/*	envelope(3) message envelope parser
85/* LICENSE
86/* .ad
87/* .fi
88/*	The Secure Mailer license must be distributed with this software.
89/* AUTHOR(S)
90/*	Wietse Venema
91/*	IBM T.J. Watson Research
92/*	P.O. Box 704
93/*	Yorktown Heights, NY 10598, USA
94/*
95/*	Wietse Venema
96/*	Google, Inc.
97/*	111 8th Avenue
98/*	New York, NY 10011, USA
99/*--*/
100
101/* System library. */
102
103#include <sys_defs.h>
104#include <sys/stat.h>
105#include <stdlib.h>
106#include <stdio.h>			/* sscanf() */
107#include <fcntl.h>
108#include <errno.h>
109#include <unistd.h>
110#include <string.h>
111#include <ctype.h>
112
113/* Utility library. */
114
115#include <msg.h>
116#include <mymalloc.h>
117#include <vstring.h>
118#include <vstream.h>
119#include <split_at.h>
120#include <valid_hostname.h>
121#include <argv.h>
122#include <stringops.h>
123#include <myflock.h>
124
125/* Global library. */
126
127#include <dict.h>
128#include <mail_queue.h>
129#include <mail_params.h>
130#include <canon_addr.h>
131#include <record.h>
132#include <rec_type.h>
133#include <sent.h>
134#include <deliver_completed.h>
135#include <opened.h>
136#include <verp_sender.h>
137#include <mail_proto.h>
138#include <qmgr_user.h>
139#include <split_addr.h>
140#include <dsn_mask.h>
141#include <rec_attr_map.h>
142
143/* Client stubs. */
144
145#include <rewrite_clnt.h>
146#include <resolve_clnt.h>
147
148/* Application-specific. */
149
150#include "qmgr.h"
151
152int     qmgr_message_count;
153int     qmgr_recipient_count;
154int     qmgr_vrfy_pend_count;
155
156/* qmgr_message_create - create in-core message structure */
157
158static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
159				           const char *queue_id, int qflags)
160{
161    QMGR_MESSAGE *message;
162
163    message = (QMGR_MESSAGE *) mymalloc(sizeof(QMGR_MESSAGE));
164    qmgr_message_count++;
165    message->flags = 0;
166    message->qflags = qflags;
167    message->tflags = 0;
168    message->tflags_offset = 0;
169    message->rflags = QMGR_READ_FLAG_DEFAULT;
170    message->fp = 0;
171    message->refcount = 0;
172    message->single_rcpt = 0;
173    message->arrival_time.tv_sec = message->arrival_time.tv_usec = 0;
174    message->create_time = 0;
175    GETTIMEOFDAY(&message->active_time);
176    message->data_offset = 0;
177    message->queue_id = mystrdup(queue_id);
178    message->queue_name = mystrdup(queue_name);
179    message->encoding = 0;
180    message->sender = 0;
181    message->dsn_envid = 0;
182    message->dsn_ret = 0;
183    message->smtputf8 = 0;
184    message->filter_xport = 0;
185    message->inspect_xport = 0;
186    message->redirect_addr = 0;
187    message->data_size = 0;
188    message->cont_length = 0;
189    message->warn_offset = 0;
190    message->warn_time = 0;
191    message->rcpt_offset = 0;
192    message->verp_delims = 0;
193    message->client_name = 0;
194    message->client_addr = 0;
195    message->client_port = 0;
196    message->client_proto = 0;
197    message->client_helo = 0;
198    message->sasl_method = 0;
199    message->sasl_username = 0;
200    message->sasl_sender = 0;
201    message->log_ident = 0;
202    message->rewrite_context = 0;
203    recipient_list_init(&message->rcpt_list, RCPT_LIST_INIT_QUEUE);
204    return (message);
205}
206
207/* qmgr_message_close - close queue file */
208
209static void qmgr_message_close(QMGR_MESSAGE *message)
210{
211    vstream_fclose(message->fp);
212    message->fp = 0;
213}
214
215/* qmgr_message_open - open queue file */
216
217static int qmgr_message_open(QMGR_MESSAGE *message)
218{
219
220    /*
221     * Sanity check.
222     */
223    if (message->fp)
224	msg_panic("%s: queue file is open", message->queue_id);
225
226    /*
227     * Open this queue file. Skip files that we cannot open. Back off when
228     * the system appears to be running out of resources.
229     */
230    if ((message->fp = mail_queue_open(message->queue_name,
231				       message->queue_id,
232				       O_RDWR, 0)) == 0) {
233	if (errno != ENOENT)
234	    msg_fatal("open %s %s: %m", message->queue_name, message->queue_id);
235	msg_warn("open %s %s: %m", message->queue_name, message->queue_id);
236	return (-1);
237    }
238    return (0);
239}
240
241/* qmgr_message_oldstyle_scan - support for Postfix < 1.0 queue files */
242
243static void qmgr_message_oldstyle_scan(QMGR_MESSAGE *message)
244{
245    VSTRING *buf;
246    long    orig_offset, extra_offset;
247    int     rec_type;
248    char   *start;
249
250    /*
251     * Initialize. No early returns or we have a memory leak.
252     */
253    buf = vstring_alloc(100);
254    if ((orig_offset = vstream_ftell(message->fp)) < 0)
255	msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
256
257    /*
258     * Rewind to the very beginning to make sure we see all records.
259     */
260    if (vstream_fseek(message->fp, 0, SEEK_SET) < 0)
261	msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
262
263    /*
264     * Scan through the old style queue file. Count the total number of
265     * recipients and find the data/extra sections offsets. Note that the new
266     * queue files require that data_size equals extra_offset - data_offset,
267     * so we set data_size to this as well and ignore the size record itself
268     * completely.
269     */
270    for (;;) {
271	rec_type = rec_get(message->fp, buf, 0);
272	if (rec_type <= 0)
273	    /* Report missing end record later. */
274	    break;
275	start = vstring_str(buf);
276	if (msg_verbose > 1)
277	    msg_info("old-style scan record %c %s", rec_type, start);
278	if (rec_type == REC_TYPE_END)
279	    break;
280	if (rec_type == REC_TYPE_MESG) {
281	    if (message->data_offset == 0) {
282		if ((message->data_offset = vstream_ftell(message->fp)) < 0)
283		    msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
284		if ((extra_offset = atol(start)) <= message->data_offset)
285		    msg_fatal("bad extra offset %s file %s",
286			      start, VSTREAM_PATH(message->fp));
287		if (vstream_fseek(message->fp, extra_offset, SEEK_SET) < 0)
288		    msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
289		message->data_size = extra_offset - message->data_offset;
290	    }
291	    continue;
292	}
293    }
294
295    /*
296     * Clean up.
297     */
298    if (vstream_fseek(message->fp, orig_offset, SEEK_SET) < 0)
299	msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
300    vstring_free(buf);
301
302    /*
303     * Sanity checks. Verify that all required information was found,
304     * including the queue file end marker.
305     */
306    if (message->data_offset == 0 || rec_type != REC_TYPE_END)
307	msg_fatal("%s: envelope records out of order", message->queue_id);
308}
309
310/* qmgr_message_read - read envelope records */
311
312static int qmgr_message_read(QMGR_MESSAGE *message)
313{
314    VSTRING *buf;
315    int     rec_type;
316    long    curr_offset;
317    long    save_offset = message->rcpt_offset;	/* save a flag */
318    char   *start;
319    int     nrcpt = 0;
320    const char *error_text;
321    char   *name;
322    char   *value;
323    char   *orig_rcpt = 0;
324    int     count;
325    int     dsn_notify = 0;
326    char   *dsn_orcpt = 0;
327    int     n;
328    int     have_log_client_attr = 0;
329    static const char env_rec_types[] = REC_TYPE_ENVELOPE REC_TYPE_EXTRACT;
330    static const char extra_rec_type[] = {REC_TYPE_XTRA, 0};
331    const char *expected_rec_types;
332
333    /*
334     * Initialize. No early returns or we have a memory leak.
335     */
336    buf = vstring_alloc(100);
337
338    /*
339     * If we re-open this file, skip over on-file recipient records that we
340     * already looked at, and refill the in-core recipient address list.
341     */
342    if (message->rcpt_offset) {
343	if (message->rcpt_list.len)
344	    msg_panic("%s: recipient list not empty on recipient reload",
345		      message->queue_id);
346	if (vstream_fseek(message->fp, message->rcpt_offset, SEEK_SET) < 0)
347	    msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
348	message->rcpt_offset = 0;
349    }
350
351    /*
352     * Read envelope records. XXX Rely on the front-end programs to enforce
353     * record size limits. Read up to var_qmgr_rcpt_limit recipients from the
354     * queue file, to protect against memory exhaustion. Recipient records
355     * may appear before or after the message content, so we keep reading
356     * from the queue file until we have enough recipients (rcpt_offset != 0)
357     * and until we know all the non-recipient information.
358     *
359     * When reading recipients from queue file, stop reading when we reach a
360     * per-message in-core recipient limit rather than a global in-core
361     * recipient limit. Use the global recipient limit only in order to stop
362     * opening queue files. The purpose is to achieve equal delay for
363     * messages with recipient counts up to var_qmgr_rcpt_limit recipients.
364     *
365     * If we would read recipients up to a global recipient limit, the average
366     * number of in-core recipients per message would asymptotically approach
367     * (global recipient limit)/(active queue size limit), which gives equal
368     * delay per recipient rather than equal delay per message.
369     *
370     * On the first open, we must examine all non-recipient records.
371     *
372     * Optimization: when we know that recipient records are not mixed with
373     * non-recipient records, as is typical with mailing list mail, then we
374     * can avoid having to examine all the queue file records before we can
375     * start deliveries. This avoids some file system thrashing with huge
376     * mailing lists.
377     */
378    for (;;) {
379	expected_rec_types = env_rec_types;
380	if ((curr_offset = vstream_ftell(message->fp)) < 0)
381	    msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
382	if (curr_offset == message->data_offset && curr_offset > 0) {
383	    if (vstream_fseek(message->fp, message->data_size, SEEK_CUR) < 0)
384		msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
385	    curr_offset += message->data_size;
386	    expected_rec_types = extra_rec_type;
387	}
388	rec_type = rec_get_raw(message->fp, buf, 0, REC_FLAG_NONE);
389	start = vstring_str(buf);
390	if (msg_verbose > 1)
391	    msg_info("record %c %s", rec_type, start);
392	if (rec_type == REC_TYPE_PTR) {
393	    if ((rec_type = rec_goto(message->fp, start)) == REC_TYPE_ERROR)
394		break;
395	    /* Need to update curr_offset after pointer jump. */
396	    continue;
397	}
398	if (rec_type <= 0) {
399	    msg_warn("%s: message rejected: missing end record",
400		     message->queue_id);
401	    break;
402	}
403	if (strchr(expected_rec_types, rec_type) == 0) {
404	    msg_warn("Unexpected record type '%c' at offset %ld",
405		     rec_type, (long) curr_offset);
406	    rec_type = REC_TYPE_ERROR;
407	    break;
408	}
409	if (rec_type == REC_TYPE_END) {
410	    message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
411	    break;
412	}
413
414	/*
415	 * Map named attributes to pseudo record types, so that we don't have
416	 * to pollute the queue file with records that are incompatible with
417	 * past Postfix versions. Preferably, people should be able to back
418	 * out from an upgrade without losing mail.
419	 */
420	if (rec_type == REC_TYPE_ATTR) {
421	    if ((error_text = split_nameval(start, &name, &value)) != 0) {
422		msg_warn("%s: bad attribute record: %s: %.200s",
423			 message->queue_id, error_text, start);
424		rec_type = REC_TYPE_ERROR;
425		break;
426	    }
427	    if ((n = rec_attr_map(name)) != 0) {
428		start = value;
429		rec_type = n;
430	    }
431	}
432
433	/*
434	 * Process recipient records.
435	 */
436	if (rec_type == REC_TYPE_RCPT) {
437	    /* See also below for code setting orig_rcpt etc. */
438#define FUDGE(x)	((x) * (var_qmgr_fudge / 100.0))
439	    if (message->rcpt_offset == 0) {
440		recipient_list_add(&message->rcpt_list, curr_offset,
441				   dsn_orcpt ? dsn_orcpt : "",
442				   dsn_notify ? dsn_notify : 0,
443				   orig_rcpt ? orig_rcpt : "", start);
444		if (dsn_orcpt) {
445		    myfree(dsn_orcpt);
446		    dsn_orcpt = 0;
447		}
448		if (orig_rcpt) {
449		    myfree(orig_rcpt);
450		    orig_rcpt = 0;
451		}
452		if (dsn_notify)
453		    dsn_notify = 0;
454		if (message->rcpt_list.len >= FUDGE(var_qmgr_rcpt_limit)) {
455		    if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0)
456			msg_fatal("vstream_ftell %s: %m",
457				  VSTREAM_PATH(message->fp));
458		    if (message->rflags & QMGR_READ_FLAG_SEEN_ALL_NON_RCPT)
459			/* We already examined all non-recipient records. */
460			break;
461		    if (message->rflags & QMGR_READ_FLAG_MIXED_RCPT_OTHER)
462			/* Examine all remaining non-recipient records. */
463			continue;
464		    /* Optimizations for "pure recipient" record sections. */
465		    if (curr_offset > message->data_offset) {
466			/* We already examined all non-recipient records. */
467			message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
468			break;
469		    }
470
471		    /*
472		     * Examine non-recipient records in the extracted
473		     * segment. Note that this skips to the message start
474		     * record, because the handler for that record changes
475		     * the expectations for allowed record types.
476		     */
477		    if (vstream_fseek(message->fp, message->data_offset,
478				      SEEK_SET) < 0)
479			msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
480		    continue;
481		}
482	    }
483	    continue;
484	}
485	if (rec_type == REC_TYPE_DONE || rec_type == REC_TYPE_DRCP) {
486	    if (message->rcpt_offset == 0) {
487		if (dsn_orcpt) {
488		    myfree(dsn_orcpt);
489		    dsn_orcpt = 0;
490		}
491		if (orig_rcpt) {
492		    myfree(orig_rcpt);
493		    orig_rcpt = 0;
494		}
495		if (dsn_notify)
496		    dsn_notify = 0;
497	    }
498	    continue;
499	}
500	if (rec_type == REC_TYPE_DSN_ORCPT) {
501	    /* See also above for code clearing dsn_orcpt. */
502	    if (dsn_orcpt != 0) {
503		msg_warn("%s: ignoring out-of-order DSN original recipient address <%.200s>",
504			 message->queue_id, dsn_orcpt);
505		myfree(dsn_orcpt);
506		dsn_orcpt = 0;
507	    }
508	    if (message->rcpt_offset == 0)
509		dsn_orcpt = mystrdup(start);
510	    continue;
511	}
512	if (rec_type == REC_TYPE_DSN_NOTIFY) {
513	    /* See also above for code clearing dsn_notify. */
514	    if (dsn_notify != 0) {
515		msg_warn("%s: ignoring out-of-order DSN notify flags <%d>",
516			 message->queue_id, dsn_notify);
517		dsn_notify = 0;
518	    }
519	    if (message->rcpt_offset == 0) {
520		if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_NOTIFY_OK(n))
521		    msg_warn("%s: ignoring malformed DSN notify flags <%.200s>",
522			     message->queue_id, start);
523		else
524		    dsn_notify = n;
525		continue;
526	    }
527	}
528	if (rec_type == REC_TYPE_ORCP) {
529	    /* See also above for code clearing orig_rcpt. */
530	    if (orig_rcpt != 0) {
531		msg_warn("%s: ignoring out-of-order original recipient <%.200s>",
532			 message->queue_id, orig_rcpt);
533		myfree(orig_rcpt);
534		orig_rcpt = 0;
535	    }
536	    if (message->rcpt_offset == 0)
537		orig_rcpt = mystrdup(start);
538	    continue;
539	}
540
541	/*
542	 * Process non-recipient records.
543	 */
544	if (message->rflags & QMGR_READ_FLAG_SEEN_ALL_NON_RCPT)
545	    /* We already examined all non-recipient records. */
546	    continue;
547	if (rec_type == REC_TYPE_SIZE) {
548	    if (message->data_offset == 0) {
549		if ((count = sscanf(start, "%ld %ld %d %d %ld %d",
550				 &message->data_size, &message->data_offset,
551				    &nrcpt, &message->rflags,
552				    &message->cont_length,
553				    &message->smtputf8)) >= 3) {
554		    /* Postfix >= 1.0 (a.k.a. 20010228). */
555		    if (message->data_offset <= 0 || message->data_size <= 0) {
556			msg_warn("%s: invalid size record: %.100s",
557				 message->queue_id, start);
558			rec_type = REC_TYPE_ERROR;
559			break;
560		    }
561		    if (message->rflags & ~QMGR_READ_FLAG_USER) {
562			msg_warn("%s: invalid flags in size record: %.100s",
563				 message->queue_id, start);
564			rec_type = REC_TYPE_ERROR;
565			break;
566		    }
567		} else if (count == 1) {
568		    /* Postfix < 1.0 (a.k.a. 20010228). */
569		    qmgr_message_oldstyle_scan(message);
570		} else {
571		    /* Can't happen. */
572		    msg_warn("%s: message rejected: weird size record",
573			     message->queue_id);
574		    rec_type = REC_TYPE_ERROR;
575		    break;
576		}
577	    }
578	    /* Postfix < 2.4 compatibility. */
579	    if (message->cont_length == 0) {
580		message->cont_length = message->data_size;
581	    } else if (message->cont_length < 0) {
582		msg_warn("%s: invalid size record: %.100s",
583			 message->queue_id, start);
584		rec_type = REC_TYPE_ERROR;
585		break;
586	    }
587	    continue;
588	}
589	if (rec_type == REC_TYPE_TIME) {
590	    if (message->arrival_time.tv_sec == 0)
591		REC_TYPE_TIME_SCAN(start, message->arrival_time);
592	    continue;
593	}
594	if (rec_type == REC_TYPE_CTIME) {
595	    if (message->create_time == 0)
596		message->create_time = atol(start);
597	    continue;
598	}
599	if (rec_type == REC_TYPE_FILT) {
600	    if (message->filter_xport != 0)
601		myfree(message->filter_xport);
602	    message->filter_xport = mystrdup(start);
603	    continue;
604	}
605	if (rec_type == REC_TYPE_INSP) {
606	    if (message->inspect_xport != 0)
607		myfree(message->inspect_xport);
608	    message->inspect_xport = mystrdup(start);
609	    continue;
610	}
611	if (rec_type == REC_TYPE_RDR) {
612	    if (message->redirect_addr != 0)
613		myfree(message->redirect_addr);
614	    message->redirect_addr = mystrdup(start);
615	    continue;
616	}
617	if (rec_type == REC_TYPE_FROM) {
618	    if (message->sender == 0) {
619		message->sender = mystrdup(start);
620		opened(message->queue_id, message->sender,
621		       message->cont_length, nrcpt,
622		       "queue %s", message->queue_name);
623	    }
624	    continue;
625	}
626	if (rec_type == REC_TYPE_DSN_ENVID) {
627	    /* Allow Milter override. */
628	    if (message->dsn_envid != 0)
629		myfree(message->dsn_envid);
630	    message->dsn_envid = mystrdup(start);
631	}
632	if (rec_type == REC_TYPE_DSN_RET) {
633	    /* Allow Milter override. */
634	    if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n))
635		msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s",
636			 message->queue_id, start);
637	    else
638		message->dsn_ret = n;
639	}
640	if (rec_type == REC_TYPE_ATTR) {
641	    /* Allow extra segment to override envelope segment info. */
642	    if (strcmp(name, MAIL_ATTR_ENCODING) == 0) {
643		if (message->encoding != 0)
644		    myfree(message->encoding);
645		message->encoding = mystrdup(value);
646	    }
647
648	    /*
649	     * Backwards compatibility. Before Postfix 2.3, the logging
650	     * attributes were called client_name, etc. Now they are called
651	     * log_client_name. etc., and client_name is used for the actual
652	     * client information. To support old queue files, we accept both
653	     * names for the purpose of logging; the new name overrides the
654	     * old one.
655	     *
656	     * XXX Do not use the "legacy" client_name etc. attribute values for
657	     * initializing the logging attributes, when this file already
658	     * contains the "modern" log_client_name etc. logging attributes.
659	     * Otherwise, logging attributes that are not present in the
660	     * queue file would be set with information from the real client.
661	     */
662	    else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_NAME) == 0) {
663		if (have_log_client_attr == 0 && message->client_name == 0)
664		    message->client_name = mystrdup(value);
665	    } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_ADDR) == 0) {
666		if (have_log_client_attr == 0 && message->client_addr == 0)
667		    message->client_addr = mystrdup(value);
668	    } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) {
669		if (have_log_client_attr == 0 && message->client_port == 0)
670		    message->client_port = mystrdup(value);
671	    } else if (strcmp(name, MAIL_ATTR_ACT_PROTO_NAME) == 0) {
672		if (have_log_client_attr == 0 && message->client_proto == 0)
673		    message->client_proto = mystrdup(value);
674	    } else if (strcmp(name, MAIL_ATTR_ACT_HELO_NAME) == 0) {
675		if (have_log_client_attr == 0 && message->client_helo == 0)
676		    message->client_helo = mystrdup(value);
677	    }
678	    /* Original client attributes. */
679	    else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_NAME) == 0) {
680		if (message->client_name != 0)
681		    myfree(message->client_name);
682		message->client_name = mystrdup(value);
683		have_log_client_attr = 1;
684	    } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_ADDR) == 0) {
685		if (message->client_addr != 0)
686		    myfree(message->client_addr);
687		message->client_addr = mystrdup(value);
688		have_log_client_attr = 1;
689	    } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_PORT) == 0) {
690		if (message->client_port != 0)
691		    myfree(message->client_port);
692		message->client_port = mystrdup(value);
693		have_log_client_attr = 1;
694	    } else if (strcmp(name, MAIL_ATTR_LOG_PROTO_NAME) == 0) {
695		if (message->client_proto != 0)
696		    myfree(message->client_proto);
697		message->client_proto = mystrdup(value);
698		have_log_client_attr = 1;
699	    } else if (strcmp(name, MAIL_ATTR_LOG_HELO_NAME) == 0) {
700		if (message->client_helo != 0)
701		    myfree(message->client_helo);
702		message->client_helo = mystrdup(value);
703		have_log_client_attr = 1;
704	    } else if (strcmp(name, MAIL_ATTR_SASL_METHOD) == 0) {
705		if (message->sasl_method == 0)
706		    message->sasl_method = mystrdup(value);
707		else
708		    msg_warn("%s: ignoring multiple %s attribute: %s",
709			   message->queue_id, MAIL_ATTR_SASL_METHOD, value);
710	    } else if (strcmp(name, MAIL_ATTR_SASL_USERNAME) == 0) {
711		if (message->sasl_username == 0)
712		    message->sasl_username = mystrdup(value);
713		else
714		    msg_warn("%s: ignoring multiple %s attribute: %s",
715			 message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
716	    } else if (strcmp(name, MAIL_ATTR_SASL_SENDER) == 0) {
717		if (message->sasl_sender == 0)
718		    message->sasl_sender = mystrdup(value);
719		else
720		    msg_warn("%s: ignoring multiple %s attribute: %s",
721			   message->queue_id, MAIL_ATTR_SASL_SENDER, value);
722	    } else if (strcmp(name, MAIL_ATTR_LOG_IDENT) == 0) {
723		if (message->log_ident == 0)
724		    message->log_ident = mystrdup(value);
725		else
726		    msg_warn("%s: ignoring multiple %s attribute: %s",
727			     message->queue_id, MAIL_ATTR_LOG_IDENT, value);
728	    } else if (strcmp(name, MAIL_ATTR_RWR_CONTEXT) == 0) {
729		if (message->rewrite_context == 0)
730		    message->rewrite_context = mystrdup(value);
731		else
732		    msg_warn("%s: ignoring multiple %s attribute: %s",
733			   message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
734	    }
735
736	    /*
737	     * Optional tracing flags (verify, sendmail -v, sendmail -bv).
738	     * This record is killed after a trace logfile report is sent and
739	     * after the logfile is deleted.
740	     */
741	    else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
742		if (message->tflags == 0) {
743		    message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
744		    if (message->tflags == DEL_REQ_FLAG_RECORD)
745			message->tflags_offset = curr_offset;
746		    else
747			message->tflags_offset = 0;
748		    if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
749			qmgr_vrfy_pend_count++;
750		}
751	    }
752	    continue;
753	}
754	if (rec_type == REC_TYPE_WARN) {
755	    if (message->warn_offset == 0) {
756		message->warn_offset = curr_offset;
757		REC_TYPE_WARN_SCAN(start, message->warn_time);
758	    }
759	    continue;
760	}
761	if (rec_type == REC_TYPE_VERP) {
762	    if (message->verp_delims == 0) {
763		if (message->sender == 0 || message->sender[0] == 0) {
764		    msg_warn("%s: ignoring VERP request for null sender",
765			     message->queue_id);
766		} else if (verp_delims_verify(start) != 0) {
767		    msg_warn("%s: ignoring bad VERP request: \"%.100s\"",
768			     message->queue_id, start);
769		} else {
770		    if (msg_verbose)
771			msg_info("%s: enabling VERP for sender \"%.100s\"",
772				 message->queue_id, message->sender);
773		    message->single_rcpt = 1;
774		    message->verp_delims = mystrdup(start);
775		}
776	    }
777	    continue;
778	}
779    }
780
781    /*
782     * Grr.
783     */
784    if (dsn_orcpt != 0) {
785	if (rec_type > 0)
786	    msg_warn("%s: ignoring out-of-order DSN original recipient <%.200s>",
787		     message->queue_id, dsn_orcpt);
788	myfree(dsn_orcpt);
789    }
790    if (orig_rcpt != 0) {
791	if (rec_type > 0)
792	    msg_warn("%s: ignoring out-of-order original recipient <%.200s>",
793		     message->queue_id, orig_rcpt);
794	myfree(orig_rcpt);
795    }
796
797    /*
798     * After sending a "delayed" warning, request sender notification when
799     * message delivery is completed. While "mail delayed" notifications are
800     * bad enough because they multiply the amount of email traffic, "delay
801     * cleared" notifications are even worse because they come in a sudden
802     * burst when the queue drains after a network outage.
803     */
804    if (var_dsn_delay_cleared && message->warn_time < 0)
805	message->tflags |= DEL_REQ_FLAG_REC_DLY_SENT;
806
807    /*
808     * Avoid clumsiness elsewhere in the program. When sending data across an
809     * IPC channel, sending an empty string is more convenient than sending a
810     * null pointer.
811     */
812    if (message->dsn_envid == 0)
813	message->dsn_envid = mystrdup("");
814    if (message->encoding == 0)
815	message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
816    if (message->client_name == 0)
817	message->client_name = mystrdup("");
818    if (message->client_addr == 0)
819	message->client_addr = mystrdup("");
820    if (message->client_port == 0)
821	message->client_port = mystrdup("");
822    if (message->client_proto == 0)
823	message->client_proto = mystrdup("");
824    if (message->client_helo == 0)
825	message->client_helo = mystrdup("");
826    if (message->sasl_method == 0)
827	message->sasl_method = mystrdup("");
828    if (message->sasl_username == 0)
829	message->sasl_username = mystrdup("");
830    if (message->sasl_sender == 0)
831	message->sasl_sender = mystrdup("");
832    if (message->log_ident == 0)
833	message->log_ident = mystrdup("");
834    if (message->rewrite_context == 0)
835	message->rewrite_context = mystrdup(MAIL_ATTR_RWR_LOCAL);
836    /* Postfix < 2.3 compatibility. */
837    if (message->create_time == 0)
838	message->create_time = message->arrival_time.tv_sec;
839
840    /*
841     * Clean up.
842     */
843    vstring_free(buf);
844
845    /*
846     * Sanity checks. Verify that all required information was found,
847     * including the queue file end marker.
848     */
849    if (rec_type <= 0) {
850	/* Already logged warning. */
851    } else if (message->arrival_time.tv_sec == 0) {
852	msg_warn("%s: message rejected: missing arrival time record",
853		 message->queue_id);
854    } else if (message->sender == 0) {
855	msg_warn("%s: message rejected: missing sender record",
856		 message->queue_id);
857    } else if (message->data_offset == 0) {
858	msg_warn("%s: message rejected: missing size record",
859		 message->queue_id);
860    } else {
861	return (0);
862    }
863    message->rcpt_offset = save_offset;		/* restore flag */
864    return (-1);
865}
866
867/* qmgr_message_update_warn - update the time of next delay warning */
868
869void    qmgr_message_update_warn(QMGR_MESSAGE *message)
870{
871
872    /*
873     * After the "mail delayed" warning, optionally send a "delay cleared"
874     * notification.
875     */
876    if (qmgr_message_open(message)
877	|| vstream_fseek(message->fp, message->warn_offset, SEEK_SET) < 0
878	|| rec_fprintf(message->fp, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
879		       REC_TYPE_WARN_ARG(-1)) < 0
880	|| vstream_fflush(message->fp))
881	msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
882    qmgr_message_close(message);
883}
884
885/* qmgr_message_kill_record - mark one message record as killed */
886
887void    qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
888{
889    if (offset <= 0)
890	msg_panic("qmgr_message_kill_record: bad offset 0x%lx", offset);
891    if (qmgr_message_open(message)
892	|| rec_put_type(message->fp, REC_TYPE_KILL, offset) < 0
893	|| vstream_fflush(message->fp))
894	msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
895    qmgr_message_close(message);
896}
897
898/* qmgr_message_sort_compare - compare recipient information */
899
900static int qmgr_message_sort_compare(const void *p1, const void *p2)
901{
902    RECIPIENT *rcpt1 = (RECIPIENT *) p1;
903    RECIPIENT *rcpt2 = (RECIPIENT *) p2;
904    QMGR_QUEUE *queue1;
905    QMGR_QUEUE *queue2;
906    char   *at1;
907    char   *at2;
908    int     result;
909
910    /*
911     * Compare most significant to least significant recipient attributes.
912     * The comparison function must be transitive, so NULL values need to be
913     * assigned an ordinal (we set NULL last).
914     */
915
916    queue1 = rcpt1->u.queue;
917    queue2 = rcpt2->u.queue;
918    if (queue1 != 0 && queue2 == 0)
919	return (-1);
920    if (queue1 == 0 && queue2 != 0)
921	return (1);
922    if (queue1 != 0 && queue2 != 0) {
923
924	/*
925	 * Compare message transport.
926	 */
927	if ((result = strcmp(queue1->transport->name,
928			     queue2->transport->name)) != 0)
929	    return (result);
930
931	/*
932	 * Compare queue name (nexthop or recipient@nexthop).
933	 */
934	if ((result = strcmp(queue1->name, queue2->name)) != 0)
935	    return (result);
936    }
937
938    /*
939     * Compare recipient domain.
940     */
941    at1 = strrchr(rcpt1->address, '@');
942    at2 = strrchr(rcpt2->address, '@');
943    if (at1 == 0 && at2 != 0)
944	return (1);
945    if (at1 != 0 && at2 == 0)
946	return (-1);
947    if (at1 != 0 && at2 != 0
948	&& (result = strcasecmp_utf8(at1, at2)) != 0)
949	return (result);
950
951    /*
952     * Compare recipient address.
953     */
954    return (strcasecmp_utf8(rcpt1->address, rcpt2->address));
955}
956
957/* qmgr_message_sort - sort message recipient addresses by domain */
958
959static void qmgr_message_sort(QMGR_MESSAGE *message)
960{
961    qsort((void *) message->rcpt_list.info, message->rcpt_list.len,
962	  sizeof(message->rcpt_list.info[0]), qmgr_message_sort_compare);
963    if (msg_verbose) {
964	RECIPIENT_LIST list = message->rcpt_list;
965	RECIPIENT *rcpt;
966
967	msg_info("start sorted recipient list");
968	for (rcpt = list.info; rcpt < list.info + list.len; rcpt++)
969	    msg_info("qmgr_message_sort: %s", rcpt->address);
970	msg_info("end sorted recipient list");
971    }
972}
973
974/* qmgr_resolve_one - resolve or skip one recipient */
975
976static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
977			            const char *addr, RESOLVE_REPLY *reply)
978{
979#define QMGR_REDIRECT(rp, tp, np) do { \
980	(rp)->flags = 0; \
981	vstring_strcpy((rp)->transport, (tp)); \
982	vstring_strcpy((rp)->nexthop, (np)); \
983    } while (0)
984
985    if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) == 0)
986	resolve_clnt_query_from(message->sender, addr, reply);
987    else
988	resolve_clnt_verify_from(message->sender, addr, reply);
989    if (reply->flags & RESOLVE_FLAG_FAIL) {
990	QMGR_REDIRECT(reply, MAIL_SERVICE_RETRY,
991		      "4.3.0 address resolver failure");
992	return (0);
993    } else if (reply->flags & RESOLVE_FLAG_ERROR) {
994	QMGR_REDIRECT(reply, MAIL_SERVICE_ERROR,
995		      "5.1.3 bad address syntax");
996	return (0);
997    } else {
998	return (0);
999    }
1000}
1001
1002/* qmgr_message_resolve - resolve recipients */
1003
1004static void qmgr_message_resolve(QMGR_MESSAGE *message)
1005{
1006    static ARGV *defer_xport_argv;
1007    RECIPIENT_LIST list = message->rcpt_list;
1008    RECIPIENT *recipient;
1009    QMGR_TRANSPORT *transport = 0;
1010    QMGR_QUEUE *queue = 0;
1011    RESOLVE_REPLY reply;
1012    VSTRING *queue_name;
1013    char   *at;
1014    char  **cpp;
1015    char   *nexthop;
1016    ssize_t len;
1017    int     status;
1018    DSN     dsn;
1019    MSG_STATS stats;
1020    DSN    *saved_dsn;
1021
1022#define STREQ(x,y)	(strcmp(x,y) == 0)
1023#define STR		vstring_str
1024#define LEN		VSTRING_LEN
1025
1026    resolve_clnt_init(&reply);
1027    queue_name = vstring_alloc(1);
1028    for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1029
1030	/*
1031	 * Redirect overrides all else. But only once (per entire message).
1032	 * For consistency with the remainder of Postfix, rewrite the address
1033	 * to canonical form before resolving it.
1034	 */
1035	if (message->redirect_addr) {
1036	    if (recipient > list.info) {
1037		recipient->u.queue = 0;
1038		continue;
1039	    }
1040	    message->rcpt_offset = 0;
1041	    rewrite_clnt_internal(REWRITE_CANON, message->redirect_addr,
1042				  reply.recipient);
1043	    RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1044	    if (qmgr_resolve_one(message, recipient,
1045				 recipient->address, &reply) < 0)
1046		continue;
1047	    if (!STREQ(recipient->address, STR(reply.recipient)))
1048		RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1049	}
1050
1051	/*
1052	 * Content filtering overrides the address resolver.
1053	 *
1054	 * XXX Bypass content_filter inspection for user-generated probes
1055	 * (sendmail -bv). MTA-generated probes never have the "please filter
1056	 * me" bits turned on, but we handle them here anyway for the sake of
1057	 * future proofing.
1058	 */
1059#define FILTER_WITHOUT_NEXTHOP(filter, next) \
1060	(((next) = split_at((filter), ':')) == 0 || *(next) == 0)
1061
1062#define RCPT_WITHOUT_DOMAIN(rcpt, next) \
1063	((next = strrchr(rcpt, '@')) == 0 || *++(next) == 0)
1064
1065	else if (message->filter_xport
1066		 && (message->tflags & DEL_REQ_TRACE_ONLY_MASK) == 0) {
1067	    reply.flags = 0;
1068	    vstring_strcpy(reply.transport, message->filter_xport);
1069	    if (FILTER_WITHOUT_NEXTHOP(STR(reply.transport), nexthop)
1070		&& *(nexthop = var_def_filter_nexthop) == 0
1071		&& RCPT_WITHOUT_DOMAIN(recipient->address, nexthop))
1072		nexthop = var_myhostname;
1073	    vstring_strcpy(reply.nexthop, nexthop);
1074	    vstring_strcpy(reply.recipient, recipient->address);
1075	}
1076
1077	/*
1078	 * Resolve the destination to (transport, nexthop, address). The
1079	 * result address may differ from the one specified by the sender.
1080	 */
1081	else {
1082	    if (qmgr_resolve_one(message, recipient,
1083				 recipient->address, &reply) < 0)
1084		continue;
1085	    if (!STREQ(recipient->address, STR(reply.recipient)))
1086		RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1087	}
1088
1089	/*
1090	 * Bounce null recipients. This should never happen, but is most
1091	 * likely the result of a fault in a different program, so aborting
1092	 * the queue manager process does not help.
1093	 */
1094	if (recipient->address[0] == 0) {
1095	    QMGR_REDIRECT(&reply, MAIL_SERVICE_ERROR,
1096			  "5.1.3 null recipient address");
1097	}
1098
1099	/*
1100	 * Redirect a forced-to-expire message without defer log to the retry
1101	 * service, so that its defer log will contain an appropriate reason.
1102	 * Do not redirect such a message to the error service, because if
1103	 * that request fails, a defer log would be created with reason
1104	 * "bounce or trace service failure" which would make no sense. Note
1105	 * that if the bounce service fails to create a defer log, the
1106	 * message will be returned as undeliverable anyway, because it is
1107	 * expired.
1108	 */
1109	if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) {
1110	    QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1111			  "4.7.0 message is administratively expired");
1112	}
1113
1114	/*
1115	 * Discard mail to the local double bounce address here, so this
1116	 * system can run without a local delivery agent. They'd still have
1117	 * to configure something for mail directed to the local postmaster,
1118	 * though, but that is an RFC requirement anyway.
1119	 *
1120	 * XXX This lookup should be done in the resolver, and the mail should
1121	 * be directed to a general-purpose null delivery agent.
1122	 */
1123	if (reply.flags & RESOLVE_CLASS_LOCAL) {
1124	    at = strrchr(STR(reply.recipient), '@');
1125	    len = (at ? (at - STR(reply.recipient))
1126		   : strlen(STR(reply.recipient)));
1127	    if (strncasecmp_utf8(STR(reply.recipient),
1128				 var_double_bounce_sender, len) == 0
1129		&& !var_double_bounce_sender[len]) {
1130		status = sent(message->tflags, message->queue_id,
1131			      QMGR_MSG_STATS(&stats, message), recipient,
1132			      "none", DSN_SIMPLE(&dsn, "2.0.0",
1133			"undeliverable postmaster notification discarded"));
1134		if (status == 0) {
1135		    deliver_completed(message->fp, recipient->offset);
1136#if 0
1137		    /* It's the default verification probe sender address. */
1138		    msg_warn("%s: undeliverable postmaster notification discarded",
1139			     message->queue_id);
1140#endif
1141		} else
1142		    message->flags |= status;
1143		continue;
1144	    }
1145	}
1146
1147	/*
1148	 * Optionally defer deliveries over specific transports, unless the
1149	 * restriction is lifted temporarily.
1150	 */
1151	if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 0) {
1152	    if (defer_xport_argv == 0)
1153		defer_xport_argv = argv_split(var_defer_xports, CHARS_COMMA_SP);
1154	    for (cpp = defer_xport_argv->argv; *cpp; cpp++)
1155		if (strcmp(*cpp, STR(reply.transport)) == 0)
1156		    break;
1157	    if (*cpp) {
1158		QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1159			      "4.3.2 deferred transport");
1160	    }
1161	}
1162
1163	/*
1164	 * Safety: defer excess address verification requests.
1165	 */
1166	if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0
1167	    && qmgr_vrfy_pend_count > var_vrfy_pend_limit)
1168	    QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1169			  "4.3.2 Too many address verification requests");
1170
1171	/*
1172	 * Look up or instantiate the proper transport.
1173	 */
1174	if (transport == 0 || !STREQ(transport->name, STR(reply.transport))) {
1175	    if ((transport = qmgr_transport_find(STR(reply.transport))) == 0)
1176		transport = qmgr_transport_create(STR(reply.transport));
1177	    queue = 0;
1178	}
1179
1180	/*
1181	 * This message is being flushed. If need-be unthrottle the
1182	 * transport.
1183	 */
1184	if ((message->qflags & QMGR_FLUSH_EACH) != 0
1185	    && QMGR_TRANSPORT_THROTTLED(transport))
1186	    qmgr_transport_unthrottle(transport);
1187
1188	/*
1189	 * This transport is dead. Defer delivery to this recipient.
1190	 */
1191	if (QMGR_TRANSPORT_THROTTLED(transport)) {
1192	    saved_dsn = transport->dsn;
1193	    if ((transport = qmgr_error_transport(MAIL_SERVICE_RETRY)) != 0) {
1194		nexthop = qmgr_error_nexthop(saved_dsn);
1195		vstring_strcpy(reply.nexthop, nexthop);
1196		myfree(nexthop);
1197		queue = 0;
1198	    } else {
1199		qmgr_defer_recipient(message, recipient, saved_dsn);
1200		continue;
1201	    }
1202	}
1203
1204	/*
1205	 * The nexthop destination provides the default name for the
1206	 * per-destination queue. When the delivery agent accepts only one
1207	 * recipient per delivery, give each recipient its own queue, so that
1208	 * deliveries to different recipients of the same message can happen
1209	 * in parallel, and so that we can enforce per-recipient concurrency
1210	 * limits and prevent one recipient from tying up all the delivery
1211	 * agent resources. We use recipient@nexthop as queue name rather
1212	 * than the actual recipient domain name, so that one recipient in
1213	 * multiple equivalent domains cannot evade the per-recipient
1214	 * concurrency limit. Split the address on the recipient delimiter if
1215	 * one is defined, so that extended addresses don't get extra
1216	 * delivery slots.
1217	 *
1218	 * Fold the result to lower case so that we don't have multiple queues
1219	 * for the same name.
1220	 *
1221	 * Important! All recipients in a queue must have the same nexthop
1222	 * value. It is OK to have multiple queues with the same nexthop
1223	 * value, but only when those queues are named after recipients.
1224	 *
1225	 * The single-recipient code below was written for local(8) like
1226	 * delivery agents, and assumes that all domains that deliver to the
1227	 * same (transport + nexthop) are aliases for $nexthop. Delivery
1228	 * concurrency is changed from per-domain into per-recipient, by
1229	 * changing the queue name from nexthop into localpart@nexthop.
1230	 *
1231	 * XXX This assumption is incorrect when different destinations share
1232	 * the same (transport + nexthop). In reality, such transports are
1233	 * rarely configured to use single-recipient deliveries. The fix is
1234	 * to decouple the per-destination recipient limit from the
1235	 * per-destination concurrency.
1236	 */
1237	vstring_strcpy(queue_name, STR(reply.nexthop));
1238	if (strcmp(transport->name, MAIL_SERVICE_ERROR) != 0
1239	    && strcmp(transport->name, MAIL_SERVICE_RETRY) != 0
1240	    && transport->recipient_limit == 1) {
1241	    /* Copy the recipient localpart. */
1242	    at = strrchr(STR(reply.recipient), '@');
1243	    len = (at ? (at - STR(reply.recipient))
1244		   : strlen(STR(reply.recipient)));
1245	    vstring_strncpy(queue_name, STR(reply.recipient), len);
1246	    /* Remove the address extension from the recipient localpart. */
1247	    if (*var_rcpt_delim && split_addr(STR(queue_name), var_rcpt_delim))
1248		vstring_truncate(queue_name, strlen(STR(queue_name)));
1249	    /* Assume the recipient domain is equivalent to nexthop. */
1250	    vstring_sprintf_append(queue_name, "@%s", STR(reply.nexthop));
1251	}
1252	lowercase(STR(queue_name));
1253
1254	/*
1255	 * This transport is alive. Find or instantiate a queue for this
1256	 * recipient.
1257	 */
1258	if (queue == 0 || !STREQ(queue->name, STR(queue_name))) {
1259	    if ((queue = qmgr_queue_find(transport, STR(queue_name))) == 0)
1260		queue = qmgr_queue_create(transport, STR(queue_name),
1261					  STR(reply.nexthop));
1262	}
1263
1264	/*
1265	 * This message is being flushed. If need-be unthrottle the queue.
1266	 */
1267	if ((message->qflags & QMGR_FLUSH_EACH) != 0
1268	    && QMGR_QUEUE_THROTTLED(queue))
1269	    qmgr_queue_unthrottle(queue);
1270
1271	/*
1272	 * This queue is dead. Defer delivery to this recipient.
1273	 */
1274	if (QMGR_QUEUE_THROTTLED(queue)) {
1275	    saved_dsn = queue->dsn;
1276	    if ((queue = qmgr_error_queue(MAIL_SERVICE_RETRY, saved_dsn)) == 0) {
1277		qmgr_defer_recipient(message, recipient, saved_dsn);
1278		continue;
1279	    }
1280	}
1281
1282	/*
1283	 * This queue is alive. Bind this recipient to this queue instance.
1284	 */
1285	recipient->u.queue = queue;
1286    }
1287    resolve_clnt_free(&reply);
1288    vstring_free(queue_name);
1289}
1290
1291/* qmgr_message_assign - assign recipients to specific delivery requests */
1292
1293static void qmgr_message_assign(QMGR_MESSAGE *message)
1294{
1295    RECIPIENT_LIST list = message->rcpt_list;
1296    RECIPIENT *recipient;
1297    QMGR_ENTRY *entry = 0;
1298    QMGR_QUEUE *queue;
1299
1300    /*
1301     * Try to bundle as many recipients in a delivery request as we can. When
1302     * the recipient resolves to the same site and transport as the previous
1303     * recipient, do not create a new queue entry, just move that recipient
1304     * to the recipient list of the existing queue entry. All this provided
1305     * that we do not exceed the transport-specific limit on the number of
1306     * recipients per transaction. Skip recipients with a dead transport or
1307     * destination.
1308     */
1309#define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
1310
1311    for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1312	if ((queue = recipient->u.queue) != 0) {
1313	    if (message->single_rcpt || entry == 0 || entry->queue != queue
1314		|| !LIMIT_OK(entry->queue->transport->recipient_limit,
1315			     entry->rcpt_list.len)) {
1316		entry = qmgr_entry_create(queue, message);
1317	    }
1318	    recipient_list_add(&entry->rcpt_list, recipient->offset,
1319			       recipient->dsn_orcpt, recipient->dsn_notify,
1320			       recipient->orig_addr, recipient->address);
1321	    qmgr_recipient_count++;
1322	}
1323    }
1324    recipient_list_free(&message->rcpt_list);
1325    recipient_list_init(&message->rcpt_list, RCPT_LIST_INIT_QUEUE);
1326}
1327
1328/* qmgr_message_free - release memory for in-core message structure */
1329
1330void    qmgr_message_free(QMGR_MESSAGE *message)
1331{
1332    if (message->refcount != 0)
1333	msg_panic("qmgr_message_free: reference len: %d", message->refcount);
1334    if (message->fp)
1335	msg_panic("qmgr_message_free: queue file is open");
1336    myfree(message->queue_id);
1337    myfree(message->queue_name);
1338    if (message->dsn_envid)
1339	myfree(message->dsn_envid);
1340    if (message->encoding)
1341	myfree(message->encoding);
1342    if (message->sender)
1343	myfree(message->sender);
1344    if (message->verp_delims)
1345	myfree(message->verp_delims);
1346    if (message->filter_xport)
1347	myfree(message->filter_xport);
1348    if (message->inspect_xport)
1349	myfree(message->inspect_xport);
1350    if (message->redirect_addr)
1351	myfree(message->redirect_addr);
1352    if (message->client_name)
1353	myfree(message->client_name);
1354    if (message->client_addr)
1355	myfree(message->client_addr);
1356    if (message->client_port)
1357	myfree(message->client_port);
1358    if (message->client_proto)
1359	myfree(message->client_proto);
1360    if (message->client_helo)
1361	myfree(message->client_helo);
1362    if (message->sasl_method)
1363	myfree(message->sasl_method);
1364    if (message->sasl_username)
1365	myfree(message->sasl_username);
1366    if (message->sasl_sender)
1367	myfree(message->sasl_sender);
1368    if (message->log_ident)
1369	myfree(message->log_ident);
1370    if (message->rewrite_context)
1371	myfree(message->rewrite_context);
1372    recipient_list_free(&message->rcpt_list);
1373    qmgr_message_count--;
1374    if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
1375	qmgr_vrfy_pend_count--;
1376    myfree((void *) message);
1377}
1378
1379/* qmgr_message_alloc - create in-core message structure */
1380
1381QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
1382				         int qflags, mode_t mode)
1383{
1384    const char *myname = "qmgr_message_alloc";
1385    QMGR_MESSAGE *message;
1386    struct stat st;
1387
1388    if (msg_verbose)
1389	msg_info("%s: %s %s", myname, queue_name, queue_id);
1390
1391    /*
1392     * Create an in-core message structure.
1393     */
1394    message = qmgr_message_create(queue_name, queue_id, qflags);
1395
1396    /*
1397     * Extract message envelope information: time of arrival, sender address,
1398     * recipient addresses. Skip files with malformed envelope information.
1399     */
1400#define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
1401
1402    if (qmgr_message_open(message) < 0) {
1403	qmgr_message_free(message);
1404	return (0);
1405    }
1406    if (myflock(vstream_fileno(message->fp), INTERNAL_LOCK, QMGR_LOCK_MODE) < 0) {
1407	msg_info("%s: skipped, still being delivered", queue_id);
1408	qmgr_message_close(message);
1409	qmgr_message_free(message);
1410	return (QMGR_MESSAGE_LOCKED);
1411    }
1412    if (qmgr_message_read(message) < 0) {
1413	qmgr_message_close(message);
1414	qmgr_message_free(message);
1415	return (0);
1416    } else {
1417
1418	/*
1419	 * We have validated the queue file content, so it is safe to modify
1420	 * the file properties now.
1421	 */
1422	if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
1423	    msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
1424
1425	/*
1426	 * If this message is forced to expire, use the existing defer
1427	 * logfile records and do not assign any deliveries, leaving the
1428	 * refcount at zero. If this message is forced to expire, but no
1429	 * defer logfile records are available, assign deliveries to the
1430	 * retry transport so that the sender will still find out what
1431	 * recipients are affected and why. Either way, do not assign normal
1432	 * deliveries because that would be undesirable especially with mail
1433	 * that was expired in the 'hold' queue.
1434	 */
1435	if ((message->qflags & QMGR_FORCE_EXPIRE) != 0
1436	    && stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_DEFER,
1437				    queue_id), &st) == 0 && st.st_size > 0) {
1438	    /* Use this defer log; don't assign deliveries (refcount == 0). */
1439	    message->flags = 1;			/* simplify downstream code */
1440	    qmgr_message_close(message);
1441	    return (message);
1442	}
1443
1444	/*
1445	 * Reset the defer log. This code should not be here, but we must
1446	 * reset the defer log *after* acquiring the exclusive lock on the
1447	 * queue file and *before* resolving new recipients. Since all those
1448	 * operations are encapsulated so nicely by this routine, the defer
1449	 * log reset has to be done here as well.
1450	 *
1451	 * Note: it is safe to remove the defer logfile from a previous queue
1452	 * run of this queue file, because the defer log contains information
1453	 * about recipients that still exist in this queue file.
1454	 */
1455	if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
1456	    msg_fatal("%s: %s: remove %s %s: %m", myname,
1457		      queue_id, MAIL_QUEUE_DEFER, queue_id);
1458	qmgr_message_sort(message);
1459	qmgr_message_resolve(message);
1460	qmgr_message_sort(message);
1461	qmgr_message_assign(message);
1462	qmgr_message_close(message);
1463	return (message);
1464    }
1465}
1466
1467/* qmgr_message_realloc - refresh in-core message structure */
1468
1469QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *message)
1470{
1471    const char *myname = "qmgr_message_realloc";
1472
1473    /*
1474     * Sanity checks.
1475     */
1476    if (message->rcpt_offset <= 0)
1477	msg_panic("%s: invalid offset: %ld", myname, message->rcpt_offset);
1478    if (msg_verbose)
1479	msg_info("%s: %s %s offset %ld", myname, message->queue_name,
1480		 message->queue_id, message->rcpt_offset);
1481
1482    /*
1483     * Extract recipient addresses. Skip files with malformed envelope
1484     * information.
1485     */
1486    if (qmgr_message_open(message) < 0)
1487	return (0);
1488    if (qmgr_message_read(message) < 0) {
1489	qmgr_message_close(message);
1490	return (0);
1491    } else {
1492	qmgr_message_sort(message);
1493	qmgr_message_resolve(message);
1494	qmgr_message_sort(message);
1495	qmgr_message_assign(message);
1496	qmgr_message_close(message);
1497	return (message);
1498    }
1499}
1500