mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 13:18:12 +00:00
postfix-2.4-20060823
This commit is contained in:
parent
05d7ee7dca
commit
0e961e79a8
@ -12628,9 +12628,10 @@ Apologies for any names omitted.
|
||||
limit in the SMTP server didn't work for size limits close
|
||||
enough to INT_MAX. File: smtpd/smtpd.c.
|
||||
|
||||
Bugfix: after an SMTP client was rejected with "smtpd_delay_reject
|
||||
= no", the SMTP server would panic as it generated spurious
|
||||
Milter requests for unrecognized commands. File: smtpd/smtpd.c.
|
||||
Bugfix (introduced Postfix 2.3): after an SMTP client was
|
||||
rejected with "smtpd_delay_reject = no", the SMTP server
|
||||
would panic as it generated spurious Milter requests for
|
||||
unrecognized commands. File: smtpd/smtpd.c.
|
||||
|
||||
20060727
|
||||
|
||||
@ -12640,8 +12641,9 @@ Apologies for any names omitted.
|
||||
|
||||
20060805
|
||||
|
||||
Bugfix: #ifdef damage caused smtp_sasl_start() to be invoked
|
||||
twice. Reported by C-J Lofstedt. File: smtp/smtp_sasl_proto.c.
|
||||
Bugfix (introduced Postfix 2.3): #ifdef damage caused
|
||||
smtp_sasl_start() to be invoked twice. Reported by C-J
|
||||
Lofstedt. File: smtp/smtp_sasl_proto.c.
|
||||
|
||||
20060806
|
||||
|
||||
@ -12650,8 +12652,63 @@ Apologies for any names omitted.
|
||||
helpdesk service that solves all their email problems.
|
||||
Credits to Jonathan Balester. File: bounce/bounce_templates.c.
|
||||
|
||||
20060807
|
||||
|
||||
Bugfix (introduced Postfix 2.2): when upgrading from Postfix
|
||||
< 2.2 with the third-party TLS patch, the post-install
|
||||
upgrade procedure didn't put a "?" in the existing tlsmgr
|
||||
entry, causing tlsmgr to repeatedly start and exit when TLS
|
||||
support was not compiled in. File: conf/post-install.
|
||||
|
||||
20060812
|
||||
|
||||
Bugfix (introduced < Postfix alpha): safety mechanism in
|
||||
mail_date() didn't work. Found in code review. File:
|
||||
global/mail_date.c.
|
||||
|
||||
20060817
|
||||
|
||||
Test programs for host address->name and name->address
|
||||
lookups to debug name service inconsistencies, typically
|
||||
when the Postfix SMTP server claims that a hostname is
|
||||
"unknown". Files: auxiliary/name-addr-test/*.
|
||||
|
||||
20060822
|
||||
|
||||
Added missing logging for "message to large" etc. Files:
|
||||
smtpd/smtpd.c, cleanup/cleanup_milter.c.
|
||||
|
||||
20060823
|
||||
|
||||
Bugfix (introduced Postfix 2.2): vstream_fdclose() did not
|
||||
flush unwritten output before disconnecting a stream from
|
||||
its file descriptor. File: util/vstream.c.
|
||||
|
||||
Bugfix (introduced Postfix 2.2): segfault when vstream_fclose()
|
||||
attempted to flush unwritten output, after vstream_fdclose()
|
||||
disconnected the stream from its file descriptor. File:
|
||||
util/vstream.c.
|
||||
|
||||
Feature: smtp-sink can capture mail to file, either as one
|
||||
individual message per file, or as multiple messages per
|
||||
file. After an initial implementation by Weidong Cui. File:
|
||||
smtpstone/smtp-sink.c.
|
||||
|
||||
Bugfix (introduced < Postfix alpha): smtp-sink did not
|
||||
correctly recognize DOT-CR-LF immediately after DATA. File:
|
||||
smtpstone/smtp-sink.c.
|
||||
|
||||
Cleanup: smtp-sink now requires that MAIL FROM, RCPT TO and
|
||||
DATA be send in the correct order. This simplified the
|
||||
implementation of the capture to file feature. File:
|
||||
smtpstone/smtp-sink.c.
|
||||
|
||||
Wish list:
|
||||
|
||||
Make null local-part handling configurable: either expand
|
||||
into mailer-daemon (current bahavior) or disallow (strict
|
||||
behavior, currently implemented only in the SMTP server).
|
||||
|
||||
The type of var_message_limit should be changed from int
|
||||
to long or better, to take advantage of LP64 architectures.
|
||||
This also requires checking all expressions in which
|
||||
|
@ -49,10 +49,11 @@ Alternatively, for the D.J.B. version of CDB:
|
||||
"AUXLIBS=$CDB/cdb.a $CDB/alloc.a $CDB/buffer.a $CDB/unix.a $CDB/byte.a"
|
||||
% make
|
||||
|
||||
After postfix has been built with cdb support, you can use "cdb" tables
|
||||
After Postfix has been built with cdb support, you can use "cdb" tables
|
||||
wherever you can use read-only "hash", "btree" or "dbm" tables. However, the
|
||||
"ppoossttmmaapp --ii" (incremental record insertion) and "ppoossttmmaapp --dd" (incremental
|
||||
record deletion) command-line options are not available. For the same reason
|
||||
the "cdb" map type cannot be used to store the persistent address verification
|
||||
cache for the verify(8) service.
|
||||
cache for the verify(8) service, or to store TLS session information for the
|
||||
tlsmgr(8) service.
|
||||
|
||||
|
@ -61,24 +61,23 @@ Needless to say, these commands are not available in earlier Postfix versions.
|
||||
|
||||
BBuuiillddiinngg PPoossttffiixx wwiitthh DDoovveeccoott SSAASSLL ssuuppppoorrtt
|
||||
|
||||
Dovecot SASL support is available in Postfix 2.3 and later. The Dovecot source
|
||||
code is available via http://www.dovecot.org/. At the time of writing, only
|
||||
server-side SASL support is available, so you can't use it to authenticate to
|
||||
your network provider's server. Dovecot uses its own daemon process for
|
||||
authentication. This keeps the Postfix build process simple, because there is
|
||||
no need to link extra libraries into Postfix.
|
||||
Support for the Dovecot version 1 SASL protocol is available in Postfix 2.3 and
|
||||
later. At the time of writing, only server-side SASL support is available, so
|
||||
you can't use it to authenticate to your network provider's server. Dovecot
|
||||
uses its own daemon process for authentication. This keeps the Postfix build
|
||||
process simple, because there is no need to link extra libraries into Postfix.
|
||||
|
||||
To generate the necessary Makefiles, execute the following in the Postfix top-
|
||||
level directory:
|
||||
|
||||
% make makefiles CCARGS='-DUSE_SASL_AUTH -
|
||||
DDEF_SASL_SERVER_TYPE=\"dovecot\"'
|
||||
DDEF_SERVER_SASL_TYPE=\"dovecot\"'
|
||||
|
||||
After this, proceed with "make" as described in the INSTALL document.
|
||||
|
||||
Notes:
|
||||
|
||||
* The "-DDEF_SASL_SERVER_TYPE" stuff is not necessary; it just makes Postfix
|
||||
* The "-DDEF_SERVER_SASL_TYPE" stuff is not necessary; it just makes Postfix
|
||||
configuration a little more convenient because you don't have to specify
|
||||
the SASL plug-in type in the Postfix main.cf file.
|
||||
|
||||
|
64
postfix/auxiliary/name-addr-test/getaddrinfo.c
Normal file
64
postfix/auxiliary/name-addr-test/getaddrinfo.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* getaddrinfo(3) (name->address lookup) tester.
|
||||
*
|
||||
* Compile with:
|
||||
*
|
||||
* cc -o getaddrinfo getaddrinfo.c (BSD, Linux)
|
||||
*
|
||||
* cc -o getaddrinfo getaddrinfo.c -lsocket -lnsl (SunOS 5.x)
|
||||
*
|
||||
* Run as: getaddrinfo hostname
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*
|
||||
* Author: Wietse Venema, IBM T.J. Watson Research, USA.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char hostbuf[NI_MAXHOST]; /* XXX */
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res0;
|
||||
struct addrinfo *res;
|
||||
const char *addr;
|
||||
int err;
|
||||
|
||||
#define NO_SERVICE ((char *) 0)
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s hostname\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
memset((char *) &hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
if ((err = getaddrinfo(argv[1], NO_SERVICE, &hints, &res0)) != 0) {
|
||||
fprintf(stderr, "host %s not found\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
printf("Hostname:\t%s\n", res0->ai_canonname);
|
||||
printf("Addresses:\t");
|
||||
for (res = res0; res != 0; res = res->ai_next) {
|
||||
addr = (res->ai_family == AF_INET ?
|
||||
(char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr :
|
||||
(char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr);
|
||||
if (inet_ntop(res->ai_family, addr, hostbuf, sizeof(hostbuf)) == 0) {
|
||||
perror("inet_ntop:");
|
||||
exit(1);
|
||||
}
|
||||
printf("%s ", hostbuf);
|
||||
}
|
||||
printf("\n");
|
||||
freeaddrinfo(res0);
|
||||
exit(0);
|
||||
}
|
46
postfix/auxiliary/name-addr-test/gethostbyaddr.c
Normal file
46
postfix/auxiliary/name-addr-test/gethostbyaddr.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* gethostbyaddr tester. compile with:
|
||||
*
|
||||
* cc -o gethostbyaddr gethostbyaddr.c (SunOS 4.x)
|
||||
*
|
||||
* cc -o gethostbyaddr gethostbyaddr.c -lnsl (SunOS 5.x)
|
||||
*
|
||||
* run as: gethostbyaddr address
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct hostent *hp;
|
||||
long addr;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s i.p.addres\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
addr = inet_addr(argv[1]);
|
||||
if (hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET)) {
|
||||
printf("Hostname:\t%s\n", hp->h_name);
|
||||
printf("Aliases:\t");
|
||||
while (hp->h_aliases[0])
|
||||
printf("%s ", *hp->h_aliases++);
|
||||
printf("\n");
|
||||
printf("Addresses:\t");
|
||||
while (hp->h_addr_list[0])
|
||||
printf("%s ", inet_ntoa(*(struct in_addr *) * hp->h_addr_list++));
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
fprintf(stderr, "host %s not found\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
44
postfix/auxiliary/name-addr-test/gethostbyname.c
Normal file
44
postfix/auxiliary/name-addr-test/gethostbyname.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* gethostbyname tester. compile with:
|
||||
*
|
||||
* cc -o gethostbyname gethostbyname.c (SunOS 4.x)
|
||||
*
|
||||
* cc -o gethostbyname gethostbyname.c -lnsl (SunOS 5.x)
|
||||
*
|
||||
* run as: gethostbyname hostname
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct hostent *hp;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s hostname\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (hp = gethostbyname(argv[1])) {
|
||||
printf("Hostname:\t%s\n", hp->h_name);
|
||||
printf("Aliases:\t");
|
||||
while (hp->h_aliases[0])
|
||||
printf("%s ", *hp->h_aliases++);
|
||||
printf("\n");
|
||||
printf("Addresses:\t");
|
||||
while (hp->h_addr_list[0])
|
||||
printf("%s ", inet_ntoa(*(struct in_addr *) * hp->h_addr_list++));
|
||||
printf("\n");
|
||||
exit(0);
|
||||
} else {
|
||||
fprintf(stderr, "host %s not found\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
79
postfix/auxiliary/name-addr-test/getnameinfo.c
Normal file
79
postfix/auxiliary/name-addr-test/getnameinfo.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* getnameinfo(3) (address->name lookup) tester.
|
||||
*
|
||||
* Compile with:
|
||||
*
|
||||
* cc -o getnameinfo getnameinfo.c (BSD, Linux)
|
||||
*
|
||||
* cc -o getnameinfo getnameinfo.c -lsocket -lnsl (SunOS 5.x)
|
||||
*
|
||||
* Run as: getnameinfo address
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*
|
||||
* Author: Wietse Venema, IBM T.J. Watson Research, USA.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char hostbuf[NI_MAXHOST]; /* XXX */
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res0;
|
||||
struct addrinfo *res;
|
||||
const char *host;
|
||||
const char *addr;
|
||||
int err;
|
||||
|
||||
#define NO_SERVICE ((char *) 0)
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s ipaddres\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert address to internal form.
|
||||
*/
|
||||
host = argv[1];
|
||||
memset((char *) &hints, 0, sizeof(hints));
|
||||
hints.ai_family = (strchr(host, ':') ? AF_INET6 : AF_INET);
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags |= AI_NUMERICHOST;
|
||||
if ((err = getaddrinfo(host, NO_SERVICE, &hints, &res0)) != 0) {
|
||||
fprintf(stderr, "getaddrinfo %s: %s\n", host, gai_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert host address to name.
|
||||
*/
|
||||
for (res = res0; res != 0; res = res->ai_next) {
|
||||
err = getnameinfo(res->ai_addr, res->ai_addrlen,
|
||||
hostbuf, sizeof(hostbuf),
|
||||
NO_SERVICE, 0, NI_NAMEREQD);
|
||||
if (err) {
|
||||
fprintf(stderr, "getnameinfo %s: %s\n", host, gai_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
printf("Hostname:\t%s\n", hostbuf);
|
||||
addr = (res->ai_family == AF_INET ?
|
||||
(char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr :
|
||||
(char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr);
|
||||
if (inet_ntop(res->ai_family, addr, hostbuf, sizeof(hostbuf)) == 0) {
|
||||
perror("inet_ntop:");
|
||||
exit(1);
|
||||
}
|
||||
printf("Address:\t%s\n", hostbuf);
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
exit(0);
|
||||
}
|
@ -643,6 +643,7 @@ EOF
|
||||
ed $config_directory/master.cf <<EOF || exit 1
|
||||
/^tlsmgr[ ]*fifo[ ]/
|
||||
s/fifo/unix/
|
||||
s/[0-9][0-9]*/&?/
|
||||
p
|
||||
w
|
||||
q
|
||||
|
@ -79,10 +79,11 @@ like: </p>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p> After postfix has been built with cdb support, you can use
|
||||
<p> After Postfix has been built with cdb support, you can use
|
||||
"cdb" tables wherever you can use read-only "hash", "btree" or
|
||||
"dbm" tables. However, the "<b>postmap -i</b>" (incremental record
|
||||
insertion) and "<b>postmap -d</b>" (incremental record deletion)
|
||||
command-line options are not available. For the same reason the
|
||||
"cdb" map type cannot be used to store the persistent address
|
||||
verification cache for the <a href="verify.8.html">verify(8)</a> service. </p>
|
||||
verification cache for the <a href="verify.8.html">verify(8)</a> service, or to store
|
||||
TLS session information for the <a href="tlsmgr.8.html">tlsmgr(8)</a> service. </p>
|
||||
|
@ -113,9 +113,8 @@ Postfix versions. </p>
|
||||
<h2><a name="build_dovecot">Building Postfix with Dovecot SASL
|
||||
support</a></h2>
|
||||
|
||||
<p> Dovecot SASL support is available in Postfix 2.3 and later. The
|
||||
Dovecot source code is available via <a href="http://www.dovecot.org/">http://www.dovecot.org/</a>. At
|
||||
the time
|
||||
<p> Support for the Dovecot version 1 SASL protocol is available
|
||||
in Postfix 2.3 and later. At the time
|
||||
of writing, only server-side SASL support is available, so you can't
|
||||
use it to authenticate to your network provider's server. Dovecot
|
||||
uses its own daemon process for authentication. This keeps the
|
||||
@ -127,7 +126,7 @@ in the Postfix top-level directory: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER_TYPE=\"dovecot\"'
|
||||
% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SERVER_SASL_TYPE=\"dovecot\"'
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@ -138,7 +137,7 @@ in the Postfix top-level directory: </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> The "-DDEF_SASL_SERVER_TYPE" stuff is not necessary; it just
|
||||
<li> <p> The "-DDEF_SERVER_SASL_TYPE" stuff is not necessary; it just
|
||||
makes Postfix configuration a little more convenient because you
|
||||
don't have to specify the SASL plug-in type in the Postfix <a href="postconf.5.html">main.cf</a>
|
||||
file. </p>
|
||||
|
@ -147,8 +147,8 @@ MASTER(5) MASTER(5)
|
||||
mented by connecting to the service and sending a
|
||||
wake up request. A ? at the end of the wake-up
|
||||
time field requests that no wake up events be sent
|
||||
before the service is used. Specify 0 for no auto-
|
||||
matic wake up.
|
||||
before the first time a service is used. Specify 0
|
||||
for no automatic wake up.
|
||||
|
||||
The <a href="pickup.8.html"><b>pickup</b>(8)</a>, <a href="qmgr.8.html"><b>qmgr</b>(8)</a> and <a href="flush.8.html"><b>flush</b>(8)</a> daemons require
|
||||
a wake up timer.
|
||||
|
@ -5508,6 +5508,11 @@ may wish to turn on the policy (UCE and mail relaying) and protocol
|
||||
error (broken mail software) reports.
|
||||
</p>
|
||||
|
||||
<p> NOTE: postmaster notifications may contain confidential information
|
||||
such as SASL passwords or message content. It is the system
|
||||
administrator's responsibility to treat such information with care.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The error classes are:
|
||||
</p>
|
||||
@ -11823,7 +11828,8 @@ message contains no To: or Cc: message header. </p>
|
||||
<p>
|
||||
The numerical Postfix SMTP server response code when a sender or
|
||||
recipient address is rejected by the <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a>
|
||||
or <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
|
||||
or <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction. The response is
|
||||
always 450 in case of a temporary DNS error.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -23,6 +23,12 @@ QMQP-SINK(1) QMQP-SINK(1)
|
||||
and IPv6 are the default. This program is the complement
|
||||
of the <a href="qmqp-source.1.html"><b>qmqp-source</b>(1)</a> program.
|
||||
|
||||
Note: this is an unsupported test program. No attempt is
|
||||
made to maintain compatibility between successive ver-
|
||||
sions.
|
||||
|
||||
Arguments:
|
||||
|
||||
<b>-4</b> Support IPv4 only. This option has no effect when
|
||||
Postfix is built without IPv6 support.
|
||||
|
||||
|
@ -21,7 +21,11 @@ QMQP-SOURCE(1) QMQP-SOURCE(1)
|
||||
protocol. Connections can be made to UNIX-domain and IPv4
|
||||
or IPv6 servers. IPv4 and IPv6 are the default.
|
||||
|
||||
Options:
|
||||
Note: this is an unsupported test program. No attempt is
|
||||
made to maintain compatibility between successive ver-
|
||||
sions.
|
||||
|
||||
Arguments:
|
||||
|
||||
<b>-4</b> Connect to the server with IPv4. This option has no
|
||||
effect when Postfix is built without IPv6 support.
|
||||
|
@ -20,11 +20,21 @@ SMTP-SINK(1) SMTP-SINK(1)
|
||||
away. The purpose is to measure client performance, not
|
||||
protocol compliance.
|
||||
|
||||
<b>smtp-sink</b> may also be configured to capture each mail
|
||||
delivery transaction to file. Since disk latencies are
|
||||
large compared to network delays, this mode of operation
|
||||
can reduce the maximal performance by several orders of
|
||||
magnitude.
|
||||
|
||||
Connections can be accepted on IPv4 or IPv6 endpoints, or
|
||||
on UNIX-domain sockets. IPv4 and IPv6 are the default.
|
||||
This program is the complement of the <a href="smtp-source.1.html"><b>smtp-source</b>(1)</a> pro-
|
||||
gram.
|
||||
|
||||
Note: this is an unsupported test program. No attempt is
|
||||
made to maintain compatibility between successive ver-
|
||||
sions.
|
||||
|
||||
Arguments:
|
||||
|
||||
<b>-4</b> Support IPv4 only. This option has no effect when
|
||||
@ -43,6 +53,30 @@ SMTP-SINK(1) SMTP-SINK(1)
|
||||
|
||||
<b>-C</b> Disable XCLIENT support.
|
||||
|
||||
<b>-d</b> <i>dump-template</i>
|
||||
Dump each mail transaction to a single-message file
|
||||
whose name is created by expanding the <i>dump-tem-</i>
|
||||
<i>plate</i> via strftime(3) and appending a pseudo-random
|
||||
hexadecimal number (example: "%Y%m%d%H/%M." expands
|
||||
into "2006081203/05.809a62e3"). If the template
|
||||
contains "/" characters, missing directories are
|
||||
created automatically. The message dump format is
|
||||
described below.
|
||||
|
||||
Note: this option keeps one capture file open for
|
||||
every mail transaction in progress.
|
||||
|
||||
<b>-D</b> <i>dump-template</i>
|
||||
Append mail transactions to a multi-message dump
|
||||
file whose name is created by expanding the <i>dump-</i>
|
||||
<i>template</i> via strftime(3). If the template contains
|
||||
"/" characters, missing directories are created
|
||||
automatically. The message dump format is
|
||||
described below.
|
||||
|
||||
Note: this option keeps one capture file open for
|
||||
every mail transaction in progress.
|
||||
|
||||
<b>-e</b> Do not announce ESMTP support.
|
||||
|
||||
<b>-E</b> Do not announce ENHANCEDSTATUSCODES support.
|
||||
@ -66,6 +100,13 @@ SMTP-SINK(1) SMTP-SINK(1)
|
||||
|
||||
<b>-L</b> Enable LMTP instead of SMTP.
|
||||
|
||||
<b>-m</b> <i>count</i> (default: 256)
|
||||
An upper bound on the maximal number of simultane-
|
||||
ous connections that <b>smtp-sink</b> will handle. This
|
||||
prevents the process from running out of file
|
||||
descriptors. Excess connections will stay queued in
|
||||
the TCP/IP stack.
|
||||
|
||||
<b>-n</b> <i>count</i>
|
||||
Terminate after <i>count</i> sessions. This is for testing
|
||||
purposes.
|
||||
@ -105,9 +146,19 @@ SMTP-SINK(1) SMTP-SINK(1)
|
||||
and use quotes to protect white space from the
|
||||
shell. Command names are case-insensitive.
|
||||
|
||||
<b>-S start-string</b>
|
||||
An optional string that is prepended to each mes-
|
||||
sage that is written to a dump file (see the dump
|
||||
file format description below). The following C
|
||||
escape sequences are supported: \a (bell), \b
|
||||
(backslace), \f (formfeed), \n (newline), \r (car-
|
||||
riage return), \t (horizontal tab), \v (vertical
|
||||
tab), \<i>ddd</i> (up to three octal digits) and \\ (the
|
||||
backslash character).
|
||||
|
||||
<b>-t</b> <i>timeout</i> (default: 100)
|
||||
Limit the time for receiving a command or sending a
|
||||
response. The time limit is specified in seconds.
|
||||
response. The time limit is specified in seconds.
|
||||
|
||||
<b>-v</b> Show the SMTP conversations.
|
||||
|
||||
@ -116,7 +167,7 @@ SMTP-SINK(1) SMTP-SINK(1)
|
||||
mand.
|
||||
|
||||
[<b>inet:</b>][<i>host</i>]:<i>port</i>
|
||||
Listen on network interface <i>host</i> (default: any
|
||||
Listen on network interface <i>host</i> (default: any
|
||||
interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
|
||||
specified in numeric or symbolic form.
|
||||
|
||||
@ -124,9 +175,76 @@ SMTP-SINK(1) SMTP-SINK(1)
|
||||
Listen on the UNIX-domain socket at <i>pathname</i>.
|
||||
|
||||
<i>backlog</i>
|
||||
The maximum length the queue of pending connec-
|
||||
The maximum length the queue of pending connec-
|
||||
tions, as defined by the <b>listen</b>(2) system call.
|
||||
|
||||
<b>DUMP FILE FORMAT</b>
|
||||
Each dumped message contains a sequence of text lines,
|
||||
terminated with the newline character. The sequence of
|
||||
information is as follows:
|
||||
|
||||
<b>o</b> The optional string specified with the <b>-S</b> option.
|
||||
|
||||
<b>o</b> The <b>smtp-sink</b> generated headers as documented
|
||||
below.
|
||||
|
||||
<b>o</b> The message header and body as received from the
|
||||
SMTP client.
|
||||
|
||||
<b>o</b> An empty line.
|
||||
|
||||
The format of the <b>smtp-sink</b> generated headers is as fol-
|
||||
lows:
|
||||
|
||||
<b>X-Client-Addr:</b> <i>text</i>
|
||||
The client IP address without enclosing []. An IPv6
|
||||
address is prefixed with "ipv6:". This record is
|
||||
always present.
|
||||
|
||||
<b>X-Client-Proto:</b> <i>text</i>
|
||||
The client protocol: SMTP, ESMTP or LMTP. This
|
||||
record is always present.
|
||||
|
||||
<b>X-Helo-Args:</b> <i>text</i>
|
||||
The arguments of the last HELO or EHLO command
|
||||
before this mail delivery transaction. This record
|
||||
is present only if the client sent a recognizable
|
||||
HELO or EHLO command before the DATA command.
|
||||
|
||||
<b>X-Mail-Args:</b> <i>text</i>
|
||||
The arguments, if any, of the MAIL command that
|
||||
started this mail delivery transaction. This record
|
||||
is present only if the client sent a recognizable
|
||||
MAIL command.
|
||||
|
||||
<b>X-Rcpt-Args:</b> <i>text</i>
|
||||
The arguments, if any, of each successive RCPT com-
|
||||
mand within this mail delivery transaction. There
|
||||
may be zero or more of these records. This record
|
||||
is present only if the client sent a recognizable
|
||||
RCPT command.
|
||||
|
||||
<b>Received:</b> <i>text</i>
|
||||
A message header for compatibility with mail pro-
|
||||
cessing software. This three-line header marks the
|
||||
end of the headers provided by <b>smtp-sink</b>, and is
|
||||
formatted as follows:
|
||||
|
||||
<b>from</b> <i>helo</i> <b>([</b><i>addr</i><b>])</b>
|
||||
The HELO or EHLO command argument and client
|
||||
IP address. If the client did not send HELO
|
||||
or EHLO, the client IP address is used
|
||||
instead.
|
||||
|
||||
<b>by</b> <i>host</i> <b>(smtp-sink) with</b> <i>proto</i> <b>id</b> <i>random</i><b>;</b>
|
||||
The hostname specified with the <b>-h</b> option,
|
||||
the client protocol (see <b>X-Client-Proto</b>
|
||||
above), and the pseudo-random portion of the
|
||||
per-message capture file name.
|
||||
|
||||
<i>time-stamp</i>
|
||||
A time stamp as defined in <a href="http://www.faqs.org/rfcs/rfc2822.html">RFC 2822</a>.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
<a href="smtp-source.1.html">smtp-source(1)</a>, SMTP/LMTP message generator
|
||||
|
||||
|
@ -22,6 +22,10 @@ SMTP-SOURCE(1) SMTP-SOURCE(1)
|
||||
UNIX-domain and IPv4 or IPv6 servers. IPv4 and IPv6 are
|
||||
the default.
|
||||
|
||||
Note: this is an unsupported test program. No attempt is
|
||||
made to maintain compatibility between successive ver-
|
||||
sions.
|
||||
|
||||
Arguments:
|
||||
|
||||
<b>-4</b> Connect to the server with IPv4. This option has no
|
||||
|
@ -25,6 +25,11 @@ Connections can be accepted on IPv4 or IPv6 endpoints, or on
|
||||
UNIX-domain sockets.
|
||||
IPv4 and IPv6 are the default.
|
||||
This program is the complement of the \fBqmqp-source\fR(1) program.
|
||||
|
||||
Note: this is an unsupported test program. No attempt is made
|
||||
to maintain compatibility between successive versions.
|
||||
|
||||
Arguments:
|
||||
.IP \fB-4\fR
|
||||
Support IPv4 only. This option has no effect when
|
||||
Postfix is built without IPv6 support.
|
||||
|
@ -21,7 +21,10 @@ or in parallel. The program speaks the QMQP protocol.
|
||||
Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
|
||||
IPv4 and IPv6 are the default.
|
||||
|
||||
Options:
|
||||
Note: this is an unsupported test program. No attempt is made
|
||||
to maintain compatibility between successive versions.
|
||||
|
||||
Arguments:
|
||||
.IP \fB-4\fR
|
||||
Connect to the server with IPv4. This option has no effect when
|
||||
Postfix is built without IPv6 support.
|
||||
|
@ -21,11 +21,19 @@ It takes SMTP messages from the network and throws them away.
|
||||
The purpose is to measure client performance, not protocol
|
||||
compliance.
|
||||
|
||||
\fBsmtp-sink\fR may also be configured to capture each mail
|
||||
delivery transaction to file. Since disk latencies are large
|
||||
compared to network delays, this mode of operation can
|
||||
reduce the maximal performance by several orders of magnitude.
|
||||
|
||||
Connections can be accepted on IPv4 or IPv6 endpoints, or on
|
||||
UNIX-domain sockets.
|
||||
IPv4 and IPv6 are the default.
|
||||
This program is the complement of the \fBsmtp-source\fR(1) program.
|
||||
|
||||
Note: this is an unsupported test program. No attempt is made
|
||||
to maintain compatibility between successive versions.
|
||||
|
||||
Arguments:
|
||||
.IP \fB-4\fR
|
||||
Support IPv4 only. This option has no effect when
|
||||
@ -43,6 +51,27 @@ session ends, a QUIT command is executed, or when "." is
|
||||
received.
|
||||
.IP \fB-C\fR
|
||||
Disable XCLIENT support.
|
||||
.IP "\fB-d \fIdump-template\fR"
|
||||
Dump each mail transaction to a single-message file whose
|
||||
name is created by expanding the \fIdump-template\fR via
|
||||
strftime(3) and appending a pseudo-random hexadecimal number
|
||||
(example: "%Y%m%d%H/%M." expands into "2006081203/05.809a62e3").
|
||||
If the template contains "/" characters, missing directories
|
||||
are created automatically. The message dump format is
|
||||
described below.
|
||||
.sp
|
||||
Note: this option keeps one capture file open for every
|
||||
mail transaction in progress.
|
||||
.IP "\fB-D \fIdump-template\fR"
|
||||
Append mail transactions to a multi-message dump file whose
|
||||
name is created by expanding the \fIdump-template\fR via
|
||||
strftime(3).
|
||||
If the template contains "/" characters, missing directories
|
||||
are created automatically. The message dump format is
|
||||
described below.
|
||||
.sp
|
||||
Note: this option keeps one capture file open for every
|
||||
mail transaction in progress.
|
||||
.IP \fB-e\fR
|
||||
Do not announce ESMTP support.
|
||||
.IP \fB-E\fR
|
||||
@ -62,6 +91,11 @@ Use \fIhostname\fR in the SMTP greeting, in the HELO response,
|
||||
and in the EHLO response. The default hostname is "smtp-sink".
|
||||
.IP \fB-L\fR
|
||||
Enable LMTP instead of SMTP.
|
||||
.IP "\fB-m \fIcount\fR (default: 256)"
|
||||
An upper bound on the maximal number of simultaneous
|
||||
connections that \fBsmtp-sink\fR will handle. This prevents
|
||||
the process from running out of file descriptors. Excess
|
||||
connections will stay queued in the TCP/IP stack.
|
||||
.IP "\fB-n \fIcount\fR"
|
||||
Terminate after \fIcount\fR sessions. This is for testing purposes.
|
||||
.IP \fB-p\fR
|
||||
@ -92,6 +126,14 @@ Examples of commands are CONNECT, HELO, EHLO, LHLO, MAIL, RCPT, VRFY,
|
||||
DATA, ., RSET, NOOP, and QUIT. Separate command names by
|
||||
white space or commas, and use quotes to protect white space
|
||||
from the shell. Command names are case-insensitive.
|
||||
.IP "\fB-S start-string\fR"
|
||||
An optional string that is prepended to each message that is
|
||||
written to a dump file (see the dump file format description
|
||||
below). The following C escape sequences are supported: \ea
|
||||
(bell), \eb (backslace), \ef (formfeed), \en (newline), \er
|
||||
(carriage return), \et (horizontal tab), \ev (vertical tab),
|
||||
\e\fIddd\fR (up to three octal digits) and \e\e (the backslash
|
||||
character).
|
||||
.IP "\fB-t \fItimeout\fR (default: 100)"
|
||||
Limit the time for receiving a command or sending a response.
|
||||
The time limit is specified in seconds.
|
||||
@ -108,6 +150,62 @@ Listen on the UNIX-domain socket at \fIpathname\fR.
|
||||
.IP \fIbacklog\fR
|
||||
The maximum length the queue of pending connections,
|
||||
as defined by the \fBlisten\fR(2) system call.
|
||||
.SH "DUMP FILE FORMAT"
|
||||
.na
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
Each dumped message contains a sequence of text lines,
|
||||
terminated with the newline character. The sequence of
|
||||
information is as follows:
|
||||
.IP \(bu
|
||||
The optional string specified with the \fB-S\fR option.
|
||||
.IP \(bu
|
||||
The \fBsmtp-sink\fR generated headers as documented below.
|
||||
.IP \(bu
|
||||
The message header and body as received from the SMTP client.
|
||||
.IP \(bu
|
||||
An empty line.
|
||||
.PP
|
||||
The format of the \fBsmtp-sink\fR generated headers is as
|
||||
follows:
|
||||
.IP "\fBX-Client-Addr: \fItext\fR"
|
||||
The client IP address without enclosing []. An IPv6 address
|
||||
is prefixed with "ipv6:". This record is always present.
|
||||
.IP "\fBX-Client-Proto: \fItext\fR"
|
||||
The client protocol: SMTP, ESMTP or LMTP. This record is
|
||||
always present.
|
||||
.IP "\fBX-Helo-Args: \fItext\fR"
|
||||
The arguments of the last HELO or EHLO command before this
|
||||
mail delivery transaction. This record is present only if
|
||||
the client sent a recognizable HELO or EHLO command before
|
||||
the DATA command.
|
||||
.IP "\fBX-Mail-Args: \fItext\fR"
|
||||
The arguments, if any, of the MAIL command that started
|
||||
this mail delivery transaction. This record is present only
|
||||
if the client sent a recognizable MAIL command.
|
||||
.IP "\fBX-Rcpt-Args: \fItext\fR"
|
||||
The arguments, if any, of each successive RCPT command
|
||||
within this mail delivery transaction. There may be zero
|
||||
or more of these records. This record is present only if
|
||||
the client sent a recognizable RCPT command.
|
||||
.IP "\fBReceived: \fItext\fR"
|
||||
A message header for compatibility with mail processing
|
||||
software. This three-line header marks the end of the headers
|
||||
provided by \fBsmtp-sink\fR, and is formatted
|
||||
as follows:
|
||||
.RS
|
||||
.IP "\fBfrom \fIhelo\fB ([\fIaddr\fB])\fR"
|
||||
The HELO or EHLO command argument and client IP address.
|
||||
If the client did not send HELO or EHLO, the client IP
|
||||
address is used instead.
|
||||
.IP "\fBby \fIhost\fB (smtp-sink) with \fIproto\fB id \fIrandom\fB;\fR"
|
||||
The hostname specified with the \fB-h\fR option, the client
|
||||
protocol (see \fBX-Client-Proto\fR above), and the pseudo-random
|
||||
portion of the per-message capture file name.
|
||||
.IP \fItime-stamp\fR
|
||||
A time stamp as defined in RFC 2822.
|
||||
.RE
|
||||
.SH "SEE ALSO"
|
||||
.na
|
||||
.nf
|
||||
|
@ -23,6 +23,9 @@ LMTP.
|
||||
Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
|
||||
IPv4 and IPv6 are the default.
|
||||
|
||||
Note: this is an unsupported test program. No attempt is made
|
||||
to maintain compatibility between successive versions.
|
||||
|
||||
Arguments:
|
||||
.IP \fB-4\fR
|
||||
Connect to the server with IPv4. This option has no effect when
|
||||
|
@ -134,7 +134,7 @@ Automatically wake up the named service after the specified
|
||||
number of seconds. The wake up is implemented by connecting
|
||||
to the service and sending a wake up request. A ? at the
|
||||
end of the wake-up time field requests that no wake up
|
||||
events be sent before the service is used.
|
||||
events be sent before the first time a service is used.
|
||||
Specify 0 for no automatic wake up.
|
||||
.sp
|
||||
The \fBpickup\fR(8), \fBqmgr\fR(8) and \fBflush\fR(8)
|
||||
|
@ -3019,6 +3019,10 @@ default is to report only the most serious problems. The paranoid
|
||||
may wish to turn on the policy (UCE and mail relaying) and protocol
|
||||
error (broken mail software) reports.
|
||||
.PP
|
||||
NOTE: postmaster notifications may contain confidential information
|
||||
such as SASL passwords or message content. It is the system
|
||||
administrator's responsibility to treat such information with care.
|
||||
.PP
|
||||
The error classes are:
|
||||
.IP "\fBbounce\fR (also implies \fB2bounce\fR)"
|
||||
Send the postmaster copies of the headers of bounced mail, and
|
||||
@ -7164,7 +7168,8 @@ message contains no To: or Cc: message header.
|
||||
.SH unknown_address_reject_code (default: 450)
|
||||
The numerical Postfix SMTP server response code when a sender or
|
||||
recipient address is rejected by the reject_unknown_sender_domain
|
||||
or reject_unknown_recipient_domain restriction.
|
||||
or reject_unknown_recipient_domain restriction. The response is
|
||||
always 450 in case of a temporary DNS error.
|
||||
.PP
|
||||
Do not change this unless you have a complete understanding of RFC 821.
|
||||
.SH unknown_client_reject_code (default: 450)
|
||||
|
@ -79,10 +79,11 @@ like: </p>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p> After postfix has been built with cdb support, you can use
|
||||
<p> After Postfix has been built with cdb support, you can use
|
||||
"cdb" tables wherever you can use read-only "hash", "btree" or
|
||||
"dbm" tables. However, the "<b>postmap -i</b>" (incremental record
|
||||
insertion) and "<b>postmap -d</b>" (incremental record deletion)
|
||||
command-line options are not available. For the same reason the
|
||||
"cdb" map type cannot be used to store the persistent address
|
||||
verification cache for the verify(8) service. </p>
|
||||
verification cache for the verify(8) service, or to store
|
||||
TLS session information for the tlsmgr(8) service. </p>
|
||||
|
@ -113,9 +113,8 @@ Postfix versions. </p>
|
||||
<h2><a name="build_dovecot">Building Postfix with Dovecot SASL
|
||||
support</a></h2>
|
||||
|
||||
<p> Dovecot SASL support is available in Postfix 2.3 and later. The
|
||||
Dovecot source code is available via http://www.dovecot.org/. At
|
||||
the time
|
||||
<p> Support for the Dovecot version 1 SASL protocol is available
|
||||
in Postfix 2.3 and later. At the time
|
||||
of writing, only server-side SASL support is available, so you can't
|
||||
use it to authenticate to your network provider's server. Dovecot
|
||||
uses its own daemon process for authentication. This keeps the
|
||||
@ -127,7 +126,7 @@ in the Postfix top-level directory: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER_TYPE=\"dovecot\"'
|
||||
% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SERVER_SASL_TYPE=\"dovecot\"'
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@ -138,7 +137,7 @@ INSTALL document. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> The "-DDEF_SASL_SERVER_TYPE" stuff is not necessary; it just
|
||||
<li> <p> The "-DDEF_SERVER_SASL_TYPE" stuff is not necessary; it just
|
||||
makes Postfix configuration a little more convenient because you
|
||||
don't have to specify the SASL plug-in type in the Postfix main.cf
|
||||
file. </p>
|
||||
|
@ -128,7 +128,7 @@
|
||||
# number of seconds. The wake up is implemented by connecting
|
||||
# to the service and sending a wake up request. A ? at the
|
||||
# end of the wake-up time field requests that no wake up
|
||||
# events be sent before the service is used.
|
||||
# events be sent before the first time a service is used.
|
||||
# Specify 0 for no automatic wake up.
|
||||
# .sp
|
||||
# The \fBpickup\fR(8), \fBqmgr\fR(8) and \fBflush\fR(8)
|
||||
|
@ -2801,6 +2801,11 @@ may wish to turn on the policy (UCE and mail relaying) and protocol
|
||||
error (broken mail software) reports.
|
||||
</p>
|
||||
|
||||
<p> NOTE: postmaster notifications may contain confidential information
|
||||
such as SASL passwords or message content. It is the system
|
||||
administrator's responsibility to treat such information with care.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The error classes are:
|
||||
</p>
|
||||
@ -5894,7 +5899,8 @@ The default time unit is s (seconds).
|
||||
<p>
|
||||
The numerical Postfix SMTP server response code when a sender or
|
||||
recipient address is rejected by the reject_unknown_sender_domain
|
||||
or reject_unknown_recipient_domain restriction.
|
||||
or reject_unknown_recipient_domain restriction. The response is
|
||||
always 450 in case of a temporary DNS error.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
@ -213,10 +213,13 @@
|
||||
|
||||
static void cleanup_milter_set_error(CLEANUP_STATE *state, int err)
|
||||
{
|
||||
if (err == EFBIG)
|
||||
if (err == EFBIG) {
|
||||
msg_warn("%s: queue file size limit exceeded", state->queue_id);
|
||||
state->errs |= CLEANUP_STAT_SIZE;
|
||||
else
|
||||
} else {
|
||||
msg_warn("%s: write queue file: %m", state->queue_id);
|
||||
state->errs |= CLEANUP_STAT_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup_milter_error - return dummy error description */
|
||||
|
@ -121,7 +121,7 @@ const char *mail_date(time_t when)
|
||||
* Finally, add the time zone name.
|
||||
*/
|
||||
while (strftime(vstring_end(vp), vstring_avail(vp), " (%Z)", lt) == 0)
|
||||
VSTRING_SPACE(vp, 100);
|
||||
VSTRING_SPACE(vp, vstring_avail(vp) + 100);
|
||||
VSTRING_SKIP(vp);
|
||||
|
||||
return (vstring_str(vp));
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20060806"
|
||||
#define MAIL_RELEASE_DATE "20060823"
|
||||
#define MAIL_VERSION_NUMBER "2.4"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -2250,7 +2250,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
}
|
||||
vstring_strcpy(state->dsn_orcpt_buf, arg + 6);
|
||||
if (dsn_orcpt_addr
|
||||
|| (coded_addr = split_at(STR(state->dsn_orcpt_buf), ';')) == 0
|
||||
|| (coded_addr = split_at(STR(state->dsn_orcpt_buf), ';')) == 0
|
||||
|| xtext_unquote(state->dsn_buf, coded_addr) == 0
|
||||
|| *(dsn_orcpt_type = STR(state->dsn_orcpt_buf)) == 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
@ -2643,9 +2643,11 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||
&& (state->proxy == 0 ? (++start, --len) == 0 : len == 1))
|
||||
break;
|
||||
if (state->err == CLEANUP_STAT_OK) {
|
||||
if (var_message_limit > 0 && var_message_limit - state->act_size < len + 2)
|
||||
if (var_message_limit > 0 && var_message_limit - state->act_size < len + 2) {
|
||||
state->err = CLEANUP_STAT_SIZE;
|
||||
else {
|
||||
msg_warn("%s: queue file size limit exceeded",
|
||||
state->queue_id ? state->queue_id : "NOQUEUE");
|
||||
} else {
|
||||
state->act_size += len + 2;
|
||||
if (out_record(out_stream, curr_rec_type, start, len) < 0)
|
||||
state->err = out_error;
|
||||
|
@ -19,6 +19,11 @@
|
||||
/* UNIX-domain sockets.
|
||||
/* IPv4 and IPv6 are the default.
|
||||
/* This program is the complement of the \fBqmqp-source\fR(1) program.
|
||||
/*
|
||||
/* Note: this is an unsupported test program. No attempt is made
|
||||
/* to maintain compatibility between successive versions.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP \fB-4\fR
|
||||
/* Support IPv4 only. This option has no effect when
|
||||
/* Postfix is built without IPv6 support.
|
||||
|
@ -15,7 +15,10 @@
|
||||
/* Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
|
||||
/* IPv4 and IPv6 are the default.
|
||||
/*
|
||||
/* Options:
|
||||
/* Note: this is an unsupported test program. No attempt is made
|
||||
/* to maintain compatibility between successive versions.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP \fB-4\fR
|
||||
/* Connect to the server with IPv4. This option has no effect when
|
||||
/* Postfix is built without IPv6 support.
|
||||
|
@ -15,11 +15,19 @@
|
||||
/* The purpose is to measure client performance, not protocol
|
||||
/* compliance.
|
||||
/*
|
||||
/* \fBsmtp-sink\fR may also be configured to capture each mail
|
||||
/* delivery transaction to file. Since disk latencies are large
|
||||
/* compared to network delays, this mode of operation can
|
||||
/* reduce the maximal performance by several orders of magnitude.
|
||||
/*
|
||||
/* Connections can be accepted on IPv4 or IPv6 endpoints, or on
|
||||
/* UNIX-domain sockets.
|
||||
/* IPv4 and IPv6 are the default.
|
||||
/* This program is the complement of the \fBsmtp-source\fR(1) program.
|
||||
/*
|
||||
/* Note: this is an unsupported test program. No attempt is made
|
||||
/* to maintain compatibility between successive versions.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP \fB-4\fR
|
||||
/* Support IPv4 only. This option has no effect when
|
||||
@ -37,6 +45,27 @@
|
||||
/* received.
|
||||
/* .IP \fB-C\fR
|
||||
/* Disable XCLIENT support.
|
||||
/* .IP "\fB-d \fIdump-template\fR"
|
||||
/* Dump each mail transaction to a single-message file whose
|
||||
/* name is created by expanding the \fIdump-template\fR via
|
||||
/* strftime(3) and appending a pseudo-random hexadecimal number
|
||||
/* (example: "%Y%m%d%H/%M." expands into "2006081203/05.809a62e3").
|
||||
/* If the template contains "/" characters, missing directories
|
||||
/* are created automatically. The message dump format is
|
||||
/* described below.
|
||||
/* .sp
|
||||
/* Note: this option keeps one capture file open for every
|
||||
/* mail transaction in progress.
|
||||
/* .IP "\fB-D \fIdump-template\fR"
|
||||
/* Append mail transactions to a multi-message dump file whose
|
||||
/* name is created by expanding the \fIdump-template\fR via
|
||||
/* strftime(3).
|
||||
/* If the template contains "/" characters, missing directories
|
||||
/* are created automatically. The message dump format is
|
||||
/* described below.
|
||||
/* .sp
|
||||
/* Note: this option keeps one capture file open for every
|
||||
/* mail transaction in progress.
|
||||
/* .IP \fB-e\fR
|
||||
/* Do not announce ESMTP support.
|
||||
/* .IP \fB-E\fR
|
||||
@ -56,6 +85,11 @@
|
||||
/* and in the EHLO response. The default hostname is "smtp-sink".
|
||||
/* .IP \fB-L\fR
|
||||
/* Enable LMTP instead of SMTP.
|
||||
/* .IP "\fB-m \fIcount\fR (default: 256)"
|
||||
/* An upper bound on the maximal number of simultaneous
|
||||
/* connections that \fBsmtp-sink\fR will handle. This prevents
|
||||
/* the process from running out of file descriptors. Excess
|
||||
/* connections will stay queued in the TCP/IP stack.
|
||||
/* .IP "\fB-n \fIcount\fR"
|
||||
/* Terminate after \fIcount\fR sessions. This is for testing purposes.
|
||||
/* .IP \fB-p\fR
|
||||
@ -86,6 +120,14 @@
|
||||
/* DATA, ., RSET, NOOP, and QUIT. Separate command names by
|
||||
/* white space or commas, and use quotes to protect white space
|
||||
/* from the shell. Command names are case-insensitive.
|
||||
/* .IP "\fB-S start-string\fR"
|
||||
/* An optional string that is prepended to each message that is
|
||||
/* written to a dump file (see the dump file format description
|
||||
/* below). The following C escape sequences are supported: \ea
|
||||
/* (bell), \eb (backslace), \ef (formfeed), \en (newline), \er
|
||||
/* (carriage return), \et (horizontal tab), \ev (vertical tab),
|
||||
/* \e\fIddd\fR (up to three octal digits) and \e\e (the backslash
|
||||
/* character).
|
||||
/* .IP "\fB-t \fItimeout\fR (default: 100)"
|
||||
/* Limit the time for receiving a command or sending a response.
|
||||
/* The time limit is specified in seconds.
|
||||
@ -102,6 +144,60 @@
|
||||
/* .IP \fIbacklog\fR
|
||||
/* The maximum length the queue of pending connections,
|
||||
/* as defined by the \fBlisten\fR(2) system call.
|
||||
/* DUMP FILE FORMAT
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* Each dumped message contains a sequence of text lines,
|
||||
/* terminated with the newline character. The sequence of
|
||||
/* information is as follows:
|
||||
/* .IP \(bu
|
||||
/* The optional string specified with the \fB-S\fR option.
|
||||
/* .IP \(bu
|
||||
/* The \fBsmtp-sink\fR generated headers as documented below.
|
||||
/* .IP \(bu
|
||||
/* The message header and body as received from the SMTP client.
|
||||
/* .IP \(bu
|
||||
/* An empty line.
|
||||
/* .PP
|
||||
/* The format of the \fBsmtp-sink\fR generated headers is as
|
||||
/* follows:
|
||||
/* .IP "\fBX-Client-Addr: \fItext\fR"
|
||||
/* The client IP address without enclosing []. An IPv6 address
|
||||
/* is prefixed with "ipv6:". This record is always present.
|
||||
/* .IP "\fBX-Client-Proto: \fItext\fR"
|
||||
/* The client protocol: SMTP, ESMTP or LMTP. This record is
|
||||
/* always present.
|
||||
/* .IP "\fBX-Helo-Args: \fItext\fR"
|
||||
/* The arguments of the last HELO or EHLO command before this
|
||||
/* mail delivery transaction. This record is present only if
|
||||
/* the client sent a recognizable HELO or EHLO command before
|
||||
/* the DATA command.
|
||||
/* .IP "\fBX-Mail-Args: \fItext\fR"
|
||||
/* The arguments, if any, of the MAIL command that started
|
||||
/* this mail delivery transaction. This record is present only
|
||||
/* if the client sent a recognizable MAIL command.
|
||||
/* .IP "\fBX-Rcpt-Args: \fItext\fR"
|
||||
/* The arguments, if any, of each successive RCPT command
|
||||
/* within this mail delivery transaction. There may be zero
|
||||
/* or more of these records. This record is present only if
|
||||
/* the client sent a recognizable RCPT command.
|
||||
/* .IP "\fBReceived: \fItext\fR"
|
||||
/* A message header for compatibility with mail processing
|
||||
/* software. This three-line header marks the end of the headers
|
||||
/* provided by \fBsmtp-sink\fR, and is formatted
|
||||
/* as follows:
|
||||
/* .RS
|
||||
/* .IP "\fBfrom \fIhelo\fB ([\fIaddr\fB])\fR"
|
||||
/* The HELO or EHLO command argument and client IP address.
|
||||
/* If the client did not send HELO or EHLO, the client IP
|
||||
/* address is used instead.
|
||||
/* .IP "\fBby \fIhost\fB (smtp-sink) with \fIproto\fB id \fIrandom\fB;\fR"
|
||||
/* The hostname specified with the \fB-h\fR option, the client
|
||||
/* protocol (see \fBX-Client-Proto\fR above), and the pseudo-random
|
||||
/* portion of the per-message capture file name.
|
||||
/* .IP \fItime-stamp\fR
|
||||
/* A time stamp as defined in RFC 2822.
|
||||
/* .RE
|
||||
/* SEE ALSO
|
||||
/* smtp-source(1), SMTP/LMTP message generator
|
||||
/* LICENSE
|
||||
@ -120,12 +216,15 @@
|
||||
#include <sys_defs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef STRCASECMP_IN_STRINGS_H
|
||||
#include <strings.h>
|
||||
@ -146,10 +245,14 @@
|
||||
#include <stringops.h>
|
||||
#include <sane_accept.h>
|
||||
#include <inet_proto.h>
|
||||
#include <myaddrinfo.h>
|
||||
#include <make_dirs.h>
|
||||
#include <myrand.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <smtp_stream.h>
|
||||
#include <mail_date.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -158,8 +261,17 @@ typedef struct SINK_STATE {
|
||||
VSTRING *buffer;
|
||||
int data_state;
|
||||
int (*read_fn) (struct SINK_STATE *);
|
||||
int in_mail;
|
||||
int rcpts;
|
||||
char *push_back_ptr;
|
||||
/* Capture file information for fake Received: header */
|
||||
MAI_HOSTADDR_STR client_addr; /* IP address */
|
||||
char *addr_prefix; /* ipv6: or empty */
|
||||
char *helo_args; /* text after HELO or EHLO */
|
||||
const char *client_proto; /* SMTP, ESMTP, LMTP */
|
||||
time_t start_time; /* MAIL command time */
|
||||
int id; /* pseudo-random */
|
||||
VSTREAM *dump_file; /* dump file or null */
|
||||
} SINK_STATE;
|
||||
|
||||
#define ST_ANY 0
|
||||
@ -173,6 +285,10 @@ typedef struct SINK_STATE {
|
||||
#define PUSH_BACK_GET(state) (*(state)->push_back_ptr++)
|
||||
#define PUSH_BACK_SET(state, text) ((state)->push_back_ptr = (text))
|
||||
|
||||
#ifndef DEF_MAX_CLIENT_COUNT
|
||||
#define DEF_MAX_CLIENT_COUNT 256
|
||||
#endif
|
||||
|
||||
static int var_tmout = 100;
|
||||
static int var_max_line_length = 2048;
|
||||
static char *var_myhostname;
|
||||
@ -194,10 +310,19 @@ static int disable_saslauth;
|
||||
static int disable_xclient;
|
||||
static int disable_xforward;
|
||||
static int disable_enh_status;
|
||||
static int max_client_count = DEF_MAX_CLIENT_COUNT;
|
||||
static int client_count;
|
||||
static int sock;
|
||||
|
||||
static char *single_template; /* individual template */
|
||||
static char *shared_template; /* shared template */
|
||||
static VSTRING *start_string; /* dump content prefix */
|
||||
|
||||
#define SOFT_ERROR_RESP "450 4.3.0 Error: command failed"
|
||||
#define HARD_ERROR_RESP "500 5.3.0 Error: command failed"
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/* do_stats - show counters */
|
||||
|
||||
static void do_stats(void)
|
||||
@ -223,10 +348,211 @@ static void soft_err_resp(SINK_STATE *state)
|
||||
smtp_flush(state->stream);
|
||||
}
|
||||
|
||||
/* exp_path_template - expand template pathname, static result */
|
||||
|
||||
static VSTRING *exp_path_template(const char *template, time_t start_time)
|
||||
{
|
||||
static VSTRING *path_buf = 0;
|
||||
struct tm *lt;
|
||||
|
||||
if (path_buf == 0)
|
||||
path_buf = vstring_alloc(100);
|
||||
else
|
||||
VSTRING_RESET(path_buf);
|
||||
lt = localtime(&start_time);
|
||||
while (strftime(STR(path_buf), vstring_avail(path_buf), template, lt) == 0)
|
||||
VSTRING_SPACE(path_buf, vstring_avail(path_buf) + 100);
|
||||
VSTRING_SKIP(path_buf);
|
||||
return (path_buf);
|
||||
}
|
||||
|
||||
/* make_parent_dir - create parent directory or bust */
|
||||
|
||||
static void make_parent_dir(const char *path, mode_t mode)
|
||||
{
|
||||
const char *parent;
|
||||
|
||||
parent = sane_dirname((VSTRING *) 0, path);
|
||||
if (make_dirs(parent, mode) < 0)
|
||||
msg_fatal("mkdir %s: %m", parent);
|
||||
}
|
||||
|
||||
/* mail_file_open - open mail capture file */
|
||||
|
||||
static void mail_file_open(SINK_STATE *state)
|
||||
{
|
||||
const char *myname = "mail_file_open";
|
||||
VSTRING *path_buf;
|
||||
ssize_t len;
|
||||
int tries = 0;
|
||||
|
||||
/*
|
||||
* Save the start time for later.
|
||||
*/
|
||||
time(&(state->start_time));
|
||||
|
||||
/*
|
||||
* Expand the per-message dumpfile pathname template.
|
||||
*/
|
||||
path_buf = exp_path_template(single_template, state->start_time);
|
||||
|
||||
/*
|
||||
* Append a random hexadecimal string to the pathname and create a new
|
||||
* file. Retry with a different path if the file already exists. Create
|
||||
* intermediate directories on the fly when the template specifies
|
||||
* multiple pathname segments.
|
||||
*/
|
||||
#define ID_FORMAT "%08x"
|
||||
|
||||
for (len = VSTRING_LEN(path_buf); /* void */ ; vstring_truncate(path_buf, len)) {
|
||||
if (++tries > 100)
|
||||
msg_fatal("%s: something is looping", myname);
|
||||
state->id = myrand();
|
||||
vstring_sprintf_append(path_buf, ID_FORMAT, state->id);
|
||||
if ((state->dump_file = vstream_fopen(STR(path_buf),
|
||||
O_RDWR | O_CREAT | O_EXCL,
|
||||
0644)) != 0) {
|
||||
break;
|
||||
} else if (errno == EEXIST) {
|
||||
continue;
|
||||
} else if (errno == ENOENT) {
|
||||
make_parent_dir(STR(path_buf), 0755);
|
||||
continue;
|
||||
} else {
|
||||
msg_fatal("open %s: %m", STR(path_buf));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't leave temporary files behind.
|
||||
*/
|
||||
if (shared_template != 0 && unlink(STR(path_buf)) < 0)
|
||||
msg_fatal("unlink %s: %m", STR(path_buf));
|
||||
|
||||
/*
|
||||
* Do initial header records.
|
||||
*/
|
||||
if (start_string)
|
||||
vstream_fprintf(state->dump_file, "%s", STR(start_string));
|
||||
vstream_fprintf(state->dump_file, "X-Client-Addr: %s%s\n",
|
||||
state->addr_prefix, state->client_addr.buf);
|
||||
vstream_fprintf(state->dump_file, "X-Client-Proto: %s\n", state->client_proto);
|
||||
if (state->helo_args)
|
||||
vstream_fprintf(state->dump_file, "X-Helo-Args: %s\n", state->helo_args);
|
||||
/* Note: there may be more than one recipient. */
|
||||
}
|
||||
|
||||
/* mail_file_finish_header - do final smtp-sink generated header records */
|
||||
|
||||
static void mail_file_finish_header(SINK_STATE *state)
|
||||
{
|
||||
if (state->helo_args)
|
||||
vstream_fprintf(state->dump_file, "Received: from %s ([%s%s])\n",
|
||||
state->helo_args, state->addr_prefix,
|
||||
state->client_addr.buf);
|
||||
else
|
||||
vstream_fprintf(state->dump_file, "Received: from [%s%s] ([%s%s])\n",
|
||||
state->addr_prefix, state->client_addr.buf,
|
||||
state->addr_prefix, state->client_addr.buf);
|
||||
vstream_fprintf(state->dump_file, "\tby %s (smtp-sink)"
|
||||
" with %s id " ID_FORMAT ";\n",
|
||||
var_myhostname, state->client_proto, state->id);
|
||||
vstream_fprintf(state->dump_file, "\t%s\n", mail_date(state->start_time));
|
||||
}
|
||||
|
||||
/* mail_file_cleanup - common cleanup for capture file */
|
||||
|
||||
static void mail_file_cleanup(SINK_STATE *state)
|
||||
{
|
||||
(void) vstream_fclose(state->dump_file);
|
||||
state->dump_file = 0;
|
||||
}
|
||||
|
||||
/* mail_file_finish - handle message completion for capture file */
|
||||
|
||||
static void mail_file_finish(SINK_STATE *state)
|
||||
{
|
||||
|
||||
/*
|
||||
* Optionally append the captured message to a shared dumpfile.
|
||||
*/
|
||||
if (shared_template) {
|
||||
const char *out_path;
|
||||
VSTREAM *out_fp;
|
||||
ssize_t count;
|
||||
|
||||
/*
|
||||
* Expand the shared dumpfile pathname template.
|
||||
*/
|
||||
out_path = STR(exp_path_template(shared_template, state->start_time));
|
||||
|
||||
/*
|
||||
* Open the shared dump file.
|
||||
*/
|
||||
#define OUT_OPEN_FLAGS (O_WRONLY | O_CREAT | O_APPEND)
|
||||
#define OUT_OPEN_MODE 0644
|
||||
|
||||
if ((out_fp = vstream_fopen(out_path, OUT_OPEN_FLAGS, OUT_OPEN_MODE))
|
||||
== 0 && errno == ENOENT) {
|
||||
make_parent_dir(out_path, 0755);
|
||||
out_fp = vstream_fopen(out_path, OUT_OPEN_FLAGS, OUT_OPEN_MODE);
|
||||
}
|
||||
if (out_fp == 0)
|
||||
msg_fatal("open %s: %m", out_path);
|
||||
|
||||
/*
|
||||
* Append message content from single-message dump file.
|
||||
*/
|
||||
if (vstream_fseek(state->dump_file, 0L, SEEK_SET) < 0)
|
||||
msg_fatal("seek file %s: %m", VSTREAM_PATH(state->dump_file));
|
||||
VSTRING_RESET(state->buffer);
|
||||
for (;;) {
|
||||
count = vstream_fread(state->dump_file, STR(state->buffer),
|
||||
vstring_avail(state->buffer));
|
||||
if (count <= 0)
|
||||
break;
|
||||
if (vstream_fwrite(out_fp, STR(state->buffer), count) != count)
|
||||
msg_fatal("append file %s: %m", out_path);
|
||||
}
|
||||
if (vstream_ferror(state->dump_file))
|
||||
msg_fatal("read file %s: %m", VSTREAM_PATH(state->dump_file));
|
||||
if (vstream_fclose(out_fp))
|
||||
msg_fatal("append file %s: %m", out_path);
|
||||
}
|
||||
mail_file_cleanup(state);
|
||||
}
|
||||
|
||||
/* mail_file_reset - abort mail to capture file */
|
||||
|
||||
static void mail_file_reset(SINK_STATE *state)
|
||||
{
|
||||
if (shared_template == 0
|
||||
&& unlink(VSTREAM_PATH(state->dump_file)) < 0
|
||||
&& errno != ENOENT)
|
||||
msg_fatal("unlink %s: %m", VSTREAM_PATH(state->dump_file));
|
||||
mail_file_cleanup(state);
|
||||
}
|
||||
|
||||
/* mail_cmd_reset - reset mail transaction information */
|
||||
|
||||
static void mail_cmd_reset(SINK_STATE *state)
|
||||
{
|
||||
state->in_mail = 0;
|
||||
/* Not: state->rcpts = 0. This breaks the DOT reply with LMTP. */
|
||||
if (state->dump_file)
|
||||
mail_file_reset(state);
|
||||
}
|
||||
|
||||
/* ehlo_response - respond to EHLO command */
|
||||
|
||||
static void ehlo_response(SINK_STATE *state)
|
||||
static void ehlo_response(SINK_STATE *state, const char *args)
|
||||
{
|
||||
#define SKIP(cp, cond) for (/* void */; *cp && (cond); cp++)
|
||||
|
||||
/* EHLO aborts a mail transaction in progress. */
|
||||
mail_cmd_reset(state);
|
||||
if (enable_lmtp == 0)
|
||||
state->client_proto = "ESMTP";
|
||||
smtp_printf(state->stream, "250-%s", var_myhostname);
|
||||
if (!disable_pipelining)
|
||||
smtp_printf(state->stream, "250-PIPELINING");
|
||||
@ -242,50 +568,107 @@ static void ehlo_response(SINK_STATE *state)
|
||||
smtp_printf(state->stream, "250-ENHANCEDSTATUSCODES");
|
||||
smtp_printf(state->stream, "250 ");
|
||||
smtp_flush(state->stream);
|
||||
if (single_template) {
|
||||
if (state->helo_args)
|
||||
myfree(state->helo_args);
|
||||
SKIP(args, ISSPACE(*args));
|
||||
state->helo_args = mystrdup(args);
|
||||
}
|
||||
}
|
||||
|
||||
/* helo_response - respond to HELO command */
|
||||
|
||||
static void helo_response(SINK_STATE *state)
|
||||
static void helo_response(SINK_STATE *state, const char *args)
|
||||
{
|
||||
/* HELO aborts a mail transaction in progress. */
|
||||
mail_cmd_reset(state);
|
||||
state->client_proto = "SMTP";
|
||||
smtp_printf(state->stream, "250 %s", var_myhostname);
|
||||
smtp_flush(state->stream);
|
||||
if (single_template) {
|
||||
if (state->helo_args)
|
||||
myfree(state->helo_args);
|
||||
SKIP(args, ISSPACE(*args));
|
||||
state->helo_args = mystrdup(args);
|
||||
}
|
||||
}
|
||||
|
||||
/* ok_response - send 250 OK */
|
||||
|
||||
static void ok_response(SINK_STATE *state)
|
||||
static void ok_response(SINK_STATE *state, const char *unused_args)
|
||||
{
|
||||
smtp_printf(state->stream, "250 2.0.0 Ok");
|
||||
smtp_flush(state->stream);
|
||||
}
|
||||
|
||||
/* mail_response - reset recipient count, send 250 OK */
|
||||
/* rset_response - reset, send 250 OK */
|
||||
|
||||
static void mail_response(SINK_STATE *state)
|
||||
static void rset_response(SINK_STATE *state, const char *unused_args)
|
||||
{
|
||||
state->rcpts = 0;
|
||||
mail_cmd_reset(state);
|
||||
smtp_printf(state->stream, "250 2.1.0 Ok");
|
||||
smtp_flush(state->stream);
|
||||
}
|
||||
|
||||
/* mail_response - reset recipient count, send 250 OK */
|
||||
|
||||
static void mail_response(SINK_STATE *state, const char *args)
|
||||
{
|
||||
if (state->in_mail) {
|
||||
smtp_printf(state->stream, "503 5.5.1 Error: nested MAIL command");
|
||||
smtp_flush(state->stream);
|
||||
return;
|
||||
}
|
||||
state->in_mail++;
|
||||
state->rcpts = 0;
|
||||
smtp_printf(state->stream, "250 2.1.0 Ok");
|
||||
smtp_flush(state->stream);
|
||||
if (single_template) {
|
||||
mail_file_open(state);
|
||||
SKIP(args, *args != ':');
|
||||
SKIP(args, *args == ':');
|
||||
SKIP(args, ISSPACE(*args));
|
||||
vstream_fprintf(state->dump_file, "X-Mail-Args: %s\n", args);
|
||||
}
|
||||
}
|
||||
|
||||
/* rcpt_response - bump recipient count, send 250 OK */
|
||||
|
||||
static void rcpt_response(SINK_STATE *state)
|
||||
static void rcpt_response(SINK_STATE *state, const char *args)
|
||||
{
|
||||
if (state->in_mail == 0) {
|
||||
smtp_printf(state->stream, "503 5.5.1 Error: need MAIL command");
|
||||
smtp_flush(state->stream);
|
||||
return;
|
||||
}
|
||||
state->rcpts++;
|
||||
smtp_printf(state->stream, "250 2.1.5 Ok");
|
||||
smtp_flush(state->stream);
|
||||
/* Note: there may be more than one recipient per mail transaction. */
|
||||
if (state->dump_file) {
|
||||
SKIP(args, *args != ':');
|
||||
SKIP(args, *args == ':');
|
||||
SKIP(args, ISSPACE(*args));
|
||||
vstream_fprintf(state->dump_file, "X-Rcpt-Args: %s\n", args);
|
||||
}
|
||||
}
|
||||
|
||||
/* data_response - respond to DATA command */
|
||||
|
||||
static void data_response(SINK_STATE *state)
|
||||
static void data_response(SINK_STATE *state, const char *unused_args)
|
||||
{
|
||||
if (state->in_mail == 0 || state->rcpts == 0) {
|
||||
smtp_printf(state->stream, "503 5.5.1 Error: need RCPT command");
|
||||
smtp_flush(state->stream);
|
||||
return;
|
||||
}
|
||||
/* Not: ST_ANY. */
|
||||
state->data_state = ST_CR_LF;
|
||||
smtp_printf(state->stream, "354 End data with <CR><LF>.<CR><LF>");
|
||||
smtp_flush(state->stream);
|
||||
state->read_fn = data_read;
|
||||
if (state->dump_file)
|
||||
mail_file_finish_header(state);
|
||||
}
|
||||
|
||||
/* data_event - delayed response to DATA command */
|
||||
@ -294,7 +677,7 @@ static void data_event(int unused_event, char *context)
|
||||
{
|
||||
SINK_STATE *state = (SINK_STATE *) context;
|
||||
|
||||
data_response(state);
|
||||
data_response(state, "");
|
||||
}
|
||||
|
||||
/* dot_resp_hard - hard error response to . command */
|
||||
@ -325,7 +708,7 @@ static void dot_resp_soft(SINK_STATE *state)
|
||||
|
||||
/* dot_response - response to . command */
|
||||
|
||||
static void dot_response(SINK_STATE *state)
|
||||
static void dot_response(SINK_STATE *state, const char *unused_args)
|
||||
{
|
||||
if (enable_lmtp) {
|
||||
while (state->rcpts-- > 0) /* XXX this could block */
|
||||
@ -338,7 +721,7 @@ static void dot_response(SINK_STATE *state)
|
||||
|
||||
/* quit_response - respond to QUIT command */
|
||||
|
||||
static void quit_response(SINK_STATE *state)
|
||||
static void quit_response(SINK_STATE *state, const char *unused_args)
|
||||
{
|
||||
smtp_printf(state->stream, "221 Bye");
|
||||
smtp_flush(state->stream);
|
||||
@ -348,7 +731,7 @@ static void quit_response(SINK_STATE *state)
|
||||
|
||||
/* conn_response - respond to connect command */
|
||||
|
||||
static void conn_response(SINK_STATE *state)
|
||||
static void conn_response(SINK_STATE *state, const char *unused_args)
|
||||
{
|
||||
if (pretend_pix)
|
||||
smtp_printf(state->stream, "220 ********");
|
||||
@ -400,10 +783,19 @@ static int data_read(SINK_STATE *state)
|
||||
state->data_state = data_trans[0].next_state;
|
||||
else
|
||||
state->data_state = ST_ANY;
|
||||
if (state->dump_file) {
|
||||
if (ch != '\r' && state->data_state != ST_CR_LF_DOT)
|
||||
VSTREAM_PUTC(ch, state->dump_file);
|
||||
if (vstream_ferror(state->dump_file))
|
||||
msg_fatal("append file %s: %m", VSTREAM_PATH(state->dump_file));
|
||||
}
|
||||
if (state->data_state == ST_CR_LF_DOT_CR_LF) {
|
||||
PUSH_BACK_SET(state, ".\r\n");
|
||||
state->read_fn = command_read;
|
||||
state->data_state = ST_ANY;
|
||||
if (state->dump_file)
|
||||
mail_file_finish(state);
|
||||
mail_cmd_reset(state);
|
||||
if (count) {
|
||||
mesg_count++;
|
||||
do_stats();
|
||||
@ -427,7 +819,7 @@ static int data_read(SINK_STATE *state)
|
||||
*/
|
||||
typedef struct SINK_COMMAND {
|
||||
const char *name;
|
||||
void (*response) (SINK_STATE *);
|
||||
void (*response) (SINK_STATE *, const char *);
|
||||
void (*hard_response) (SINK_STATE *);
|
||||
void (*soft_response) (SINK_STATE *);
|
||||
int flags;
|
||||
@ -451,7 +843,7 @@ static SINK_COMMAND command_table[] = {
|
||||
"rcpt", rcpt_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
"data", data_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
".", dot_response, dot_resp_hard, dot_resp_soft, FLAG_ENABLE,
|
||||
"rset", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
"rset", rset_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
"noop", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
"vrfy", ok_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
"quit", quit_response, hard_err_resp, soft_err_resp, FLAG_ENABLE,
|
||||
@ -502,11 +894,12 @@ static void set_cmds_flags(const char *cmds, int flags)
|
||||
|
||||
/* command_resp - respond to command */
|
||||
|
||||
static int command_resp(SINK_STATE *state, SINK_COMMAND *cmdp, const char *command, char *args)
|
||||
static int command_resp(SINK_STATE *state, SINK_COMMAND *cmdp,
|
||||
const char *command, const char *args)
|
||||
{
|
||||
/* We use raw syslog. Sanitize data content and length. */
|
||||
if (cmdp->flags & FLAG_SYSLOG)
|
||||
syslog(LOG_INFO, "%s %.100s", command, printable(args, '?'));
|
||||
syslog(LOG_INFO, "%s %.100s", command, args);
|
||||
if (cmdp->flags & FLAG_DISCONNECT)
|
||||
return (-1);
|
||||
if (cmdp->flags & FLAG_HARD_ERR) {
|
||||
@ -520,7 +913,7 @@ static int command_resp(SINK_STATE *state, SINK_COMMAND *cmdp, const char *comma
|
||||
if (cmdp->response == data_response && fixed_delay > 0) {
|
||||
event_request_timer(data_event, (char *) state, fixed_delay);
|
||||
} else {
|
||||
cmdp->response(state);
|
||||
cmdp->response(state, args);
|
||||
if (cmdp->response == quit_response)
|
||||
return (-1);
|
||||
}
|
||||
@ -604,7 +997,7 @@ static int command_read(SINK_STATE *state)
|
||||
*/
|
||||
vstring_truncate(state->buffer, VSTRING_LEN(state->buffer) - 2);
|
||||
VSTRING_TERMINATE(state->buffer);
|
||||
state->data_state = ST_ANY;
|
||||
state->data_state = ST_CR_LF;
|
||||
VSTRING_RESET(state->buffer);
|
||||
|
||||
/*
|
||||
@ -626,7 +1019,7 @@ static int command_read(SINK_STATE *state)
|
||||
smtp_flush(state->stream);
|
||||
return (0);
|
||||
}
|
||||
return (command_resp(state, cmdp, command, ptr));
|
||||
return (command_resp(state, cmdp, command, printable(ptr, '?')));
|
||||
}
|
||||
|
||||
/* read_timeout - handle timer event */
|
||||
@ -698,6 +1091,8 @@ static void read_event(int unused_event, char *context)
|
||||
|
||||
static void disconnect(SINK_STATE *state)
|
||||
{
|
||||
static void connect_event(int, char *);
|
||||
|
||||
event_disable_readwrite(vstream_fileno(state->stream));
|
||||
event_cancel_timer(read_timeout, (char *) state);
|
||||
if (count) {
|
||||
@ -706,24 +1101,36 @@ static void disconnect(SINK_STATE *state)
|
||||
}
|
||||
vstream_fclose(state->stream);
|
||||
vstring_free(state->buffer);
|
||||
/* Clean up file capture attributes. */
|
||||
if (state->helo_args)
|
||||
myfree(state->helo_args);
|
||||
/* Delete incomplete mail transaction. */
|
||||
mail_cmd_reset(state);
|
||||
myfree((char *) state);
|
||||
if (max_quit_count > 0 && quit_count >= max_quit_count)
|
||||
exit(0);
|
||||
if (client_count-- == max_client_count)
|
||||
event_enable_read(sock, connect_event, (char *) 0);
|
||||
}
|
||||
|
||||
/* connect_event - handle connection events */
|
||||
|
||||
static void connect_event(int unused_event, char *context)
|
||||
static void connect_event(int unused_event, char *unused_context)
|
||||
{
|
||||
int sock = CAST_CHAR_PTR_TO_INT(context);
|
||||
struct sockaddr sa;
|
||||
SOCKADDR_SIZE len = sizeof(sa);
|
||||
SINK_STATE *state;
|
||||
int fd;
|
||||
|
||||
if ((fd = sane_accept(sock, &sa, &len)) >= 0) {
|
||||
/* Safety: limit the number of open sockets and capture files. */
|
||||
if (++client_count == max_client_count)
|
||||
event_disable_readwrite(sock);
|
||||
state = (SINK_STATE *) mymalloc(sizeof(*state));
|
||||
SOCKADDR_TO_HOSTADDR(&sa, len, &state->client_addr,
|
||||
(MAI_SERVPORT_STR *) 0, sa.sa_family);
|
||||
if (msg_verbose)
|
||||
msg_info("connect (%s)",
|
||||
msg_info("connect (%s %s)",
|
||||
#ifdef AF_LOCAL
|
||||
sa.sa_family == AF_LOCAL ? "AF_LOCAL" :
|
||||
#else
|
||||
@ -733,15 +1140,24 @@ static void connect_event(int unused_event, char *context)
|
||||
#ifdef AF_INET6
|
||||
sa.sa_family == AF_INET6 ? "AF_INET6" :
|
||||
#endif
|
||||
"unknown protocol family");
|
||||
"unknown protocol family",
|
||||
state->client_addr.buf);
|
||||
non_blocking(fd, NON_BLOCKING);
|
||||
state = (SINK_STATE *) mymalloc(sizeof(*state));
|
||||
state->stream = vstream_fdopen(fd, O_RDWR);
|
||||
state->buffer = vstring_alloc(1024);
|
||||
state->read_fn = command_read;
|
||||
state->data_state = ST_ANY;
|
||||
PUSH_BACK_SET(state, "");
|
||||
smtp_timeout_setup(state->stream, var_tmout);
|
||||
state->in_mail = 0;
|
||||
state->rcpts = 0;
|
||||
/* Initialize file capture attributes. */
|
||||
state->addr_prefix = (sa.sa_family == AF_INET6 ? "ipv6:" : "");
|
||||
state->helo_args = 0;
|
||||
state->client_proto = enable_lmtp ? "LMTP" : "SMTP";
|
||||
state->start_time = 0;
|
||||
state->id = 0;
|
||||
state->dump_file = 0;
|
||||
|
||||
/*
|
||||
* We use the smtp_stream module to produce output. That module
|
||||
@ -780,12 +1196,11 @@ static void connect_event(int unused_event, char *context)
|
||||
|
||||
static void usage(char *myname)
|
||||
{
|
||||
msg_fatal("usage: %s [-468acCeEFLpPv] [-f commands] [-h hostname] [-n count] [-q commands] [-r commands] [-s commands] [-w delay] [host]:port backlog", myname);
|
||||
msg_fatal("usage: %s [-468acCeEFLpPv] [-f commands] [-h hostname] [-m max_concurrency] [-n quit_count] [-q commands] [-r commands] [-s commands] [-w delay] [-d dump-template] [-D dump-template] [-S start-string] [host]:port backlog", myname);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sock;
|
||||
int backlog;
|
||||
int ch;
|
||||
const char *protocols = INET_PROTO_NAME_ALL;
|
||||
@ -804,7 +1219,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Parse JCL.
|
||||
*/
|
||||
while ((ch = GETOPT(argc, argv, "468acCeEf:Fh:Ln:pPq:r:s:t:vw:")) > 0) {
|
||||
while ((ch = GETOPT(argc, argv, "468acCeEf:Fh:Ln:m:pPq:r:s:S:t:vw:d:D:")) > 0) {
|
||||
switch (ch) {
|
||||
case '4':
|
||||
protocols = INET_PROTO_NAME_IPV4;
|
||||
@ -825,6 +1240,12 @@ int main(int argc, char **argv)
|
||||
disable_xclient = 1;
|
||||
reset_cmd_flags("xclient", FLAG_ENABLE);
|
||||
break;
|
||||
case 'd':
|
||||
single_template = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
shared_template = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
disable_esmtp = 1;
|
||||
break;
|
||||
@ -845,9 +1266,13 @@ int main(int argc, char **argv)
|
||||
case 'L':
|
||||
enable_lmtp = 1;
|
||||
break;
|
||||
case 'm':
|
||||
if ((max_client_count = atoi(optarg)) <= 0)
|
||||
msg_fatal("bad concurrency limit: %s", optarg);
|
||||
break;
|
||||
case 'n':
|
||||
if ((max_quit_count = atoi(optarg)) <= 0)
|
||||
msg_fatal("bad count: %s", optarg);
|
||||
msg_fatal("bad quit count: %s", optarg);
|
||||
break;
|
||||
case 'p':
|
||||
disable_pipelining = 1;
|
||||
@ -867,6 +1292,10 @@ int main(int argc, char **argv)
|
||||
openlog(basename(argv[0]), LOG_PID, LOG_MAIL);
|
||||
set_cmds_flags(optarg, FLAG_SYSLOG);
|
||||
break;
|
||||
case 'S':
|
||||
start_string = vstring_alloc(10);
|
||||
unescape(start_string, optarg);
|
||||
break;
|
||||
case 't':
|
||||
if ((var_tmout = atoi(optarg)) <= 0)
|
||||
msg_fatal("bad timeout: %s", optarg);
|
||||
@ -886,6 +1315,8 @@ int main(int argc, char **argv)
|
||||
usage(argv[0]);
|
||||
if ((backlog = atoi(argv[optind + 1])) <= 0)
|
||||
usage(argv[0]);
|
||||
if (single_template && shared_template)
|
||||
msg_fatal("use only one of -d or -D, but not both");
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
@ -904,10 +1335,15 @@ int main(int argc, char **argv)
|
||||
sock = inet_listen(argv[optind], backlog, BLOCKING);
|
||||
}
|
||||
|
||||
if (single_template)
|
||||
mysrand((int) time((time_t *) 0));
|
||||
else if (shared_template)
|
||||
single_template = shared_template;
|
||||
|
||||
/*
|
||||
* Start the event handler.
|
||||
*/
|
||||
event_enable_read(sock, connect_event, CAST_INT_TO_CHAR_PTR(sock));
|
||||
event_enable_read(sock, connect_event, (char *) 0);
|
||||
for (;;)
|
||||
event_loop(-1);
|
||||
}
|
||||
|
@ -17,6 +17,9 @@
|
||||
/* Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
|
||||
/* IPv4 and IPv6 are the default.
|
||||
/*
|
||||
/* Note: this is an unsupported test program. No attempt is made
|
||||
/* to maintain compatibility between successive versions.
|
||||
/*
|
||||
/* Arguments:
|
||||
/* .IP \fB-4\fR
|
||||
/* Connect to the server with IPv4. This option has no effect when
|
||||
@ -510,7 +513,7 @@ static void send_helo(SESSION *session)
|
||||
* Send the standard greeting with our hostname
|
||||
*/
|
||||
if ((except = vstream_setjmp(session->stream)) != 0)
|
||||
msg_fatal("%s while sending HELO", exception_text(except));
|
||||
msg_fatal("%s while sending %s", exception_text(except), protocol);
|
||||
|
||||
command(session->stream, "%s %s", protocol, var_myhostname);
|
||||
|
||||
@ -528,15 +531,16 @@ static void helo_done(int unused_event, char *context)
|
||||
SESSION *session = (SESSION *) context;
|
||||
RESPONSE *resp;
|
||||
int except;
|
||||
const char *protocol = (talk_lmtp ? "LHLO" : "HELO");
|
||||
|
||||
/*
|
||||
* Get response to HELO command.
|
||||
*/
|
||||
if ((except = vstream_setjmp(session->stream)) != 0)
|
||||
msg_fatal("%s while sending HELO", exception_text(except));
|
||||
msg_fatal("%s while sending %s", exception_text(except), protocol);
|
||||
|
||||
if ((resp = response(session->stream, buffer))->code / 100 != 2)
|
||||
msg_fatal("HELO rejected: %d %s", resp->code, resp->str);
|
||||
msg_fatal("%s rejected: %d %s", protocol, resp->code, resp->str);
|
||||
|
||||
send_mail(session);
|
||||
}
|
||||
|
@ -15,6 +15,10 @@
|
||||
/* DIAGNOSTICS
|
||||
/* peekfd() returns -1 in case of trouble. The global \fIerrno\fR
|
||||
/* variable reflects the nature of the problem.
|
||||
/* BUGS
|
||||
/* On some systems, non-blocking read() may fail even after a
|
||||
/* positive return from peekfd(). The smtp-sink program works
|
||||
/* around this by using the readable() function instead.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -1049,8 +1049,9 @@ int vstream_fclose(VSTREAM *stream)
|
||||
*/
|
||||
if (stream->pid != 0)
|
||||
msg_panic("vstream_fclose: stream has process");
|
||||
if ((stream->buf.flags & VSTREAM_FLAG_WRITE_DOUBLE) != 0)
|
||||
if ((stream->buf.flags & VSTREAM_FLAG_WRITE_DOUBLE) != 0 && stream->fd >= 0)
|
||||
vstream_fflush(stream);
|
||||
/* Do not remove: vstream_fdclose() depends on this error test. */
|
||||
err = vstream_ferror(stream);
|
||||
if (stream->buf.flags & VSTREAM_FLAG_DOUBLE) {
|
||||
if (stream->read_fd >= 0)
|
||||
@ -1079,8 +1080,22 @@ int vstream_fclose(VSTREAM *stream)
|
||||
|
||||
int vstream_fdclose(VSTREAM *stream)
|
||||
{
|
||||
|
||||
/*
|
||||
* Flush unwritten output, just like vstream_fclose(). Errors are
|
||||
* reported by vstream_fclose().
|
||||
*/
|
||||
if ((stream->buf.flags & VSTREAM_FLAG_WRITE_DOUBLE) != 0)
|
||||
(void) vstream_fflush(stream);
|
||||
|
||||
/*
|
||||
* NOTE: Negative file descriptors are not part of the external
|
||||
* interface. They are for internal use only, in order to support
|
||||
* vstream_fdclose() without a lot of code duplication. Applications that
|
||||
* rely on negative VSTREAM file descriptors will break without warning.
|
||||
*/
|
||||
if (stream->buf.flags & VSTREAM_FLAG_DOUBLE) {
|
||||
stream->read_fd = stream->write_fd = -1;
|
||||
stream->fd = stream->read_fd = stream->write_fd = -1;
|
||||
} else {
|
||||
stream->fd = -1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user