19991126
- Bugfix: TXT records now have string lengths before text
+ Bugfix: DNS TXT records now have string lengths before text
(Mark Martinec @ nsc.ijs.si).
+
+19991127
+
+ Update: the LDAP client code now supports escapes as per
+ RFC2254 (John Hensley).
+
+19991207
+
+ Performance: the queue manager now frees in-memory recipients
+ as soon as a message is delivered to one destination, rather
+ than waiting until all in-memory recipients of that message
+ have been tried. This means that one message with many
+ recipients no longer stops other mail from being delivered.
+ Patch by Patrik Rak @ ein.cz. Files: qmgr/qmgr_entry.c,
+ qmgr/qmgr_message.c.
+
+ Performance: when delivering a huge list of recipients,
+ the queue manager now reads new recipients from queue file
+ before delivery concurrency starts dropping. Files:
+ qmgr/qmgr_entry.c, qmgr/qmgr_message.c.
Linux RedHat 5.x
Linux RedHat 6.x
Linux Slackware 3.5
+ Linux Slackware 4.0
+ Linux Slackware 7.0
Linux SuSE 5.x
Linux SuSE 6.x
Mac OS X server
-Incompatible changes with snapshot 19991123
+Incompatible changes with snapshot 19991127
===========================================
- In an SMTPD access map, an all-numeric right-hand side now means
need to add a "domain.name local:" entry in your transport_maps.
See the html/faq.html sections for firewalls and intranets.
-Major changes with snapshot 19991123
+Major changes with snapshot 19991127
====================================
- It is now relatively safe to configure 550 status codes for the
# a name matches a lookup key. Continue long lines by starting the
# next line with whitespace.
#
-# DO NOT LIST VIRTUAL DOMAINS HERE. INSTEAD LIST $VIRTUAL_MAPS AS AN
-# AUTHORIZED DESTINATION IN RELAY_DOMAINS.
+# DO NOT LIST VIRTUAL DOMAINS HERE. LIST THEM IN THE VIRTUAL FILE
+# INSTEAD. BE SURE TO READ THE ENTIRE VIRTUAL MANUAL PAGE.
#
#mydestination = $myhostname, localhost.$mydomain
#mydestination = $myhostname, localhost.$mydomain $mydomain
# recipient addresses that SMTP clients can send in RCPT TO commands.
#
# The default is to permit any destination from clients that match
-# $mynetworks, and to otherwise permit only mail from or to domains
-# listed in $relay_domains.
+# $mynetworks, and to otherwise permit only mail from clients or to
+# domains that match $relay_domains or a subdomain thereof.
#
# The following restrictions are available:
#
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19991123"
+#define DEF_MAIL_VERSION "Snapshot-19991207"
extern char *var_mail_version;
/* LICENSE
<p>
-Do not omit the entry that routes mail for the local machine to
-the local delivery agent.
+Do not omit the entry that routes mail for <i>thishost.my.domain</i>
+to the local delivery agent, or else mail for the local machine will
+go into a loop.
<p>
</ul>
-<p>
-
-Unfortunately, the solution cannot use the transport table, because
-that table is ignored for destinations that match <b>$mydestination</b>.
-That's an implementation error, and it will be removed.
-
<hr>
<a name="dialup"><h2>Running Postfix on a dialup machine</h2></a>
<dt> <b>check_relay_domains</b> <dd> Permit the request when the
client hostname matches <a href="#relay_domains">$relay_domains</a>,
-or when the resolved destination address matches the the local
-machine or <a href="#relay_domains"> $relay_domains</a>, otherwise
+or when the resolved destination address matches <a
+href="basic.html#mydestination">$mydestination</a>, the machine IP
+addresses, or <a href="#relay_domains"> $relay_domains</a>, otherwise
reject the request. The <b>relay_domains_reject_code</b> parameter
specifies the response code for rejected requests (default:
<b>554</b>).
<dt> <b>permit_auth_destination</b> <dd> Ignore the client hostname.
Permit the request when the resolved destination address matches
-the local machine or <a href="#relay_domains"> $relay_domains</a>.
+the <a href="basic.html#mydestination">$mydestination</a>, the
+machine IP addresses, or <a href="#relay_domains"> $relay_domains</a>.
<p>
<dt> <b>reject_unauth_destination</b> <dd> Ignore the client
hostname. Reject the request when the resolved destination address
-does not match the local machine or <a href="#relay_domains">
-$relay_domains</a>. The <b>relay_domains_reject_code</b> parameter
-specifies the response code for rejected requests (default:
-<b>554</b>).
+does not match <a href="basic.html#mydestination">$mydestination</a>,
+the machine IP addresses, or <a href="#relay_domains"> $relay_domains</a>.
+The <b>relay_domains_reject_code</b> parameter specifies the response
+code for rejected requests (default: <b>554</b>).
<p>
/* of messages that the queue manager is actually working on.
/* The active queue is limited in size. Messages are drained
/* from the active queue by allocating a delivery process and
-/* by delivering mail via that process. Message leak into the
+/* by delivering mail via that process. Messages leak into the
/* active queue only when the active queue is small enough.
/* Damaged message files are saved to the "corrupt" directory.
/*
} else {
msg_panic("qmgr_entry_done: bad queue spec: %d", which);
}
+
+ /*
+ * Free the recipient list and decrease in-core recipient count
+ * accordingly.
+ */
+ qmgr_recipient_count -= entry->rcpt_list.len;
+ qmgr_rcpt_list_free(&entry->rcpt_list);
+
myfree((char *) entry);
/*
/*
* Update the in-core message reference count. When the in-core message
- * structure has no more references, dispose of the message.
+ * structure has no more references, dispose of the message. When the
+ * in-core recipient count falls below some threshold and this message
+ * has more recipients, read them from disk before concurrency starts to
+ * drop.
*/
message->refcount--;
if (message->refcount == 0)
qmgr_active_done(message);
+ else if (message->rcpt_offset > 0
+ && qmgr_recipient_count < var_qmgr_rcpt_limit / 2)
+ qmgr_message_realloc(message);
}
/* qmgr_entry_create - create queue todo entry */
entry = (QMGR_ENTRY *) mymalloc(sizeof(QMGR_ENTRY));
entry->stream = 0;
entry->message = message;
- entry->rcpt_list.len = 0;
- entry->rcpt_list.info = 0;
+ qmgr_rcpt_list_init(&entry->rcpt_list);
message->refcount++;
entry->queue = queue;
QMGR_LIST_APPEND(queue->todo, entry);
long extra_offset;
int rec_type;
long curr_offset;
+ long save_offset = message->rcpt_offset; /* save a flag */
char *start;
struct stat st;
* already looked at, and reset the in-core recipient address list.
*/
if (message->rcpt_offset) {
+ if (message->rcpt_list.len)
+ msg_panic("%s: recipient list not empty on recipient reload", message->queue_id);
if (vstream_fseek(message->fp, message->rcpt_offset, SEEK_SET) < 0)
msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
message->rcpt_offset = 0;
- qmgr_recipient_count -= message->rcpt_list.len;
- qmgr_rcpt_list_free(&message->rcpt_list);
- qmgr_rcpt_list_init(&message->rcpt_list);
}
/*
}
} while (rec_type > 0 && rec_type != REC_TYPE_END);
- qmgr_recipient_count += message->rcpt_list.len;
-
/*
* If there is no size record, use the queue file size instead.
*/
msg_warn("%s: envelope records out of order", message->queue_id);
return (-1);
} else {
+ message->rcpt_offset = save_offset; /* restore flag */
return (0);
}
}
/*
* Try to bundle as many recipients in a delivery request as we can. When
* the recipient resolves to the same site and transport as the previous
- * recipient, do not create a new queue entry, just bump the count of
- * recipients for the existing queue entry. All this provided that we do
- * not exceed the transport-specific limit on the number of recipients
- * per transaction. Skip recipients with a dead transport or destination.
+ * recipient, do not create a new queue entry, just move that recipient
+ * to the recipient list of the existing queue entry. All this provided
+ * that we do not exceed the transport-specific limit on the number of
+ * recipients per transaction. Skip recipients with a dead transport or
+ * destination.
*/
#define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
|| !LIMIT_OK(entry->queue->transport->recipient_limit,
entry->rcpt_list.len)) {
entry = qmgr_entry_create(queue, message);
- entry->rcpt_list.info = recipient;
- entry->rcpt_list.len = 1;
- } else {
- entry->rcpt_list.len++;
}
+ qmgr_rcpt_list_add(&entry->rcpt_list, recipient->offset, recipient->address);
+ qmgr_recipient_count++;
}
}
+ qmgr_rcpt_list_free(&message->rcpt_list);
+ qmgr_rcpt_list_init(&message->rcpt_list);
}
/* qmgr_message_free - release memory for in-core message structure */
myfree(message->errors_to);
if (message->return_receipt)
myfree(message->return_receipt);
- qmgr_recipient_count -= message->rcpt_list.len;
qmgr_rcpt_list_free(&message->rcpt_list);
qmgr_message_count--;
myfree((char *) message);
}
/*
- * Report trouble.
+ * Report trouble. Log a warning only if we are going to sleep+reject.
*/
- if (naddr != 1) { /* sorry, no can do */
+ if (naddr != 1
+ || (var_strict_rfc821_env && (non_addr || *STR(arg->vstrval) != '<'))) {
msg_warn("Illegal address syntax from %s in %s command: %s",
state->namaddr, state->where, STR(arg->vstrval));
err = "501 Bad address syntax";
- } else if (non_addr > 0) { /* it works with Sendmail... */
- msg_warn("Illegal address syntax from %s in %s command: %s",
- state->namaddr, state->where, STR(arg->vstrval));
- err = (var_strict_rfc821_env ? "501 Bad address syntax" : 0);
}
/*
myname, dict_ldap->ldapsource);
}
}
+
/*
* Prepare the query.
*/
LDAP_SCOPE_SUBTREE,
vstring_str(filter_buf),
0, 0, &tv, &res)) == LDAP_SUCCESS) {
+
/*
* Search worked; extract the requested result_attribute.
*/
msg_warn("%s: entry doesn't have any values for %s", myname, dict_ldap->result_attribute);
continue;
}
+
/*
* Append each returned address to the result list.
*/
if (msg_verbose)
msg_info("%s: after ldap_open", myname);
+
/*
* If this server requires a bind, do so.
*/