コード例 #1
0
int     qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
{
    const char *myname = "qmgr_active_feed";
    QMGR_MESSAGE *message;
    struct stat st;
    const char *path;

    if (strcmp(scan_info->queue, MAIL_QUEUE_ACTIVE) == 0)
	msg_panic("%s: bad queue %s", myname, scan_info->queue);
    if (msg_verbose)
	msg_info("%s: queue %s", myname, scan_info->queue);

    /*
     * Make sure this is something we are willing to open.
     */
    if (mail_open_ok(scan_info->queue, queue_id, &st, &path) == MAIL_OPEN_NO)
	return (0);

    if (msg_verbose)
	msg_info("%s: %s", myname, path);

    /*
     * Skip files that have time stamps into the future. They need to cool
     * down. Incoming and deferred files can have future time stamps.
     */
    if ((scan_info->flags & QMGR_SCAN_ALL) == 0
	&& st.st_mtime > time((time_t *) 0) + 1) {
	if (msg_verbose)
	    msg_info("%s: skip %s (%ld seconds)", myname, queue_id,
		     (long) (st.st_mtime - event_time()));
	return (0);
    }

    /*
     * Move the message to the active queue. File access errors are fatal.
     */
    if (mail_queue_rename(queue_id, scan_info->queue, MAIL_QUEUE_ACTIVE)) {
	if (errno != ENOENT)
	    msg_fatal("%s: %s: rename from %s to %s: %m", myname,
		      queue_id, scan_info->queue, MAIL_QUEUE_ACTIVE);
	msg_warn("%s: %s: rename from %s to %s: %m", myname,
		 queue_id, scan_info->queue, MAIL_QUEUE_ACTIVE);
	return (0);
    }

    /*
     * Extract envelope information: sender and recipients. At this point,
     * mail addresses have been processed by the cleanup service so they
     * should be in canonical form. Generate requests to deliver this
     * message.
     * 
     * Throwing away queue files seems bad, especially when they made it this
     * far into the mail system. Therefore we save bad files to a separate
     * directory for further inspection.
     * 
     * After queue manager restart it is possible that a queue file is still
     * being delivered. In that case (the file is locked), defer delivery by
     * a minimal amount of time.
     */
#define QMGR_FLUSH_AFTER	(QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP)

    if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id,
				 (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
				      scan_info->flags | QMGR_FLUSH_AFTER :
				      scan_info->flags,
				 (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
				  st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE :
				      0)) == 0) {
	qmgr_active_corrupt(queue_id);
	return (0);
    } else if (message == QMGR_MESSAGE_LOCKED) {
	qmgr_active_defer(MAIL_QUEUE_ACTIVE, queue_id, MAIL_QUEUE_INCOMING, 60);
	return (0);
    } else {

	/*
	 * Special case if all recipients were already delivered. Send any
	 * bounces and clean up.
	 */
	if (message->refcount == 0)
	    qmgr_active_done(message);
	return (1);
    }
}
コード例 #2
0
static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
{
    const char *path;
    struct stat st;

    /*
     * A delivery agent marks a queue file as corrupt by changing its
     * attributes, and by pretending that delivery was deferred.
     */
    if (message->flags
	&& mail_open_ok(MAIL_QUEUE_ACTIVE, message->queue_id, &st, &path) == MAIL_OPEN_NO) {
	qmgr_active_corrupt(message->queue_id);
	qmgr_message_free(message);
	return;
    }

    /*
     * If we did not read all recipients from this file, go read some more,
     * but remember whether some recipients have to be tried again.
     * 
     * Throwing away queue files seems bad, especially when they made it this
     * far into the mail system. Therefore we save bad files to a separate
     * directory for further inspection by a human being.
     */
    if (message->rcpt_offset > 0) {
	if (qmgr_message_realloc(message) == 0) {
	    qmgr_active_corrupt(message->queue_id);
	    qmgr_message_free(message);
	} else {
	    if (message->refcount == 0)
		qmgr_active_done(message);	/* recurse for consistency */
	}
	return;
    }

    /*
     * XXX With multi-recipient mail, some recipients may have NOTIFY=SUCCESS
     * and others not. Depending on what subset of recipients are delivered,
     * a trace file may or may not be created. Even when the last partial
     * delivery attempt had no NOTIFY=SUCCESS recipients, a trace file may
     * still exist from a previous partial delivery attempt. So as long as
     * any recipient has NOTIFY=SUCCESS we have to always look for the trace
     * file and be prepared for the file not to exist.
     * 
     * See also comments in bounce/bounce_notify_util.c.
     */
    if ((message->tflags & (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD))
	|| (message->rflags & QMGR_READ_FLAG_NOTIFY_SUCCESS)) {
	atrace_flush(message->tflags,
		     message->queue_name,
		     message->queue_id,
		     message->encoding,
		     message->sender,
		     message->dsn_envid,
		     message->dsn_ret,
		     qmgr_active_done_25_trace_flush,
		     (char *) message);
	return;
    }

    /*
     * Asynchronous processing does not reach this point.
     */
    qmgr_active_done_25_generic(message);
}
コード例 #3
0
ファイル: qmgr_active.c プロジェクト: TonyChengTW/Rmail
static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
{
    char   *myname = "qmgr_active_done_2_generic";
    const char *path;
    struct stat st;
    int     status;

    /*
     * A delivery agent marks a queue file as corrupt by changing its
     * attributes, and by pretending that delivery was deferred.
     */
    if (message->flags
	&& mail_open_ok(MAIL_QUEUE_ACTIVE, message->queue_id, &st, &path) == MAIL_OPEN_NO) {
	qmgr_active_corrupt(message->queue_id);
	qmgr_message_free(message);
	return;
    }

    /*
     * If we did not read all recipients from this file, go read some more,
     * but remember whether some recipients have to be tried again.
     * 
     * Throwing away queue files seems bad, especially when they made it this
     * far into the mail system. Therefore we save bad files to a separate
     * directory for further inspection by a human being.
     */
    if (message->rcpt_offset > 0) {
	if (qmgr_message_realloc(message) == 0) {
	    qmgr_active_corrupt(message->queue_id);
	    qmgr_message_free(message);
	} else {
	    if (message->refcount == 0)
		qmgr_active_done(message);	/* recurse for consistency */
	}
	return;
    }

    /*
     * As a temporary implementation, synchronously inform the sender of
     * trace information. This will block for 10 seconds when the qmgr FIFO
     * is full.
     */
    if (message->tflags & (DEL_REQ_FLAG_EXPAND | DEL_REQ_FLAG_RECORD)) {
	status = trace_flush(message->tflags,
			     message->queue_name,
			     message->queue_id,
			     message->encoding,
			     message->sender);
	if (status == 0 && message->tflags_offset)
	    qmgr_message_kill_record(message, message->tflags_offset);
	message->flags |= status;
    }

    /*
     * If we get to this point we have tried all recipients for this message.
     * If the message is too old, try to bounce it.
     * 
     * Bounces are sent asynchronously to avoid stalling while the cleanup
     * daemon waits for the qmgr to accept the "new mail" trigger.
     */
    if (message->flags) {
	if (event_time() >= message->arrival_time +
	    (*message->sender ? var_max_queue_time : var_dsn_queue_time)) {
	    msg_info("%s: from=<%s>, status=expired, returned to sender",
		     message->queue_id, message->sender);
	    if (message->verp_delims == 0 || var_verp_bounce_off)
		adefer_flush(BOUNCE_FLAG_KEEP,
			     message->queue_name,
			     message->queue_id,
			     message->encoding,
			     message->errors_to,
			     qmgr_active_done_3_defer_flush,
			     (char *) message);
	    else
		adefer_flush_verp(BOUNCE_FLAG_KEEP,
				  message->queue_name,
				  message->queue_id,
				  message->encoding,
				  message->errors_to,
				  message->verp_delims,
				  qmgr_active_done_3_defer_flush,
				  (char *) message);
	    return;
	} else if (message->warn_time > 0
		   && event_time() > message->warn_time) {
	    if (msg_verbose)
		msg_info("%s: sending defer warning for %s", myname, message->queue_id);
	    adefer_warn(BOUNCE_FLAG_KEEP,
			message->queue_name,
			message->queue_id,
			message->encoding,
			message->errors_to,
			qmgr_active_done_3_defer_warn,
			(char *) message);
	    return;
	}
    }

    /*
     * Asynchronous processing does not reach this point.
     */
    qmgr_active_done_3_generic(message);
}