Compatibility: replace %% in milter replies by %, and strip
single (i.e. invalid) % characters. File: milter/milter8.c.
+ Compatibility: $_ macro support for Milter applications.
+ Files: smtpd/smtpd.c, smtpd/smtpd_milter.c,
+ cleanup/cleanup_state.c, cleanup/cleanup_milter.c.
+
+20060721
+
+ Safety: disable Milter processing after "postsuper -r". If
+ the mail has been filtered there is no need to do it again.
+ Moreover, when mail has passed through an external content
+ filter, we don't have sufficient information to reproduce
+ the exact same SMTP events and Sendmail macros that Milters
+ received when the mail originally arrived in Postfix. File:
+ pickup/pickup.c.
+
+ Bugfix: Milters received a truncated ORCPT=xxx parameter
+ due to destructive parsing of something that didn't have
+ to be preserved before Milter support was added to Postfix.
+ File: smtpd/smtpd.c.
+
Wish list:
Add M flag (enable multi-recipient delivery) to pipe daemon.
tidy: clean
rm -f Makefile */Makefile src/*/Makefile
cp Makefile.init Makefile
+ rm -f README_FILES/RELEASE_NOTES
+ ln -s ../RELEASE_NOTES README_FILES
rm -f bin/[!CRS]* lib/[!CRS]* include/[!CRS]* libexec/[!CRS]* \
junk */junk */*/junk \
*core */*core */*/*core \
Sendmail source code instead:
$ g\bgz\bzc\bca\bat\bt s\bse\ben\bnd\bdm\bma\bai\bil\bl-\b-x\bx.\b.y\by.\b.z\bz.\b.t\bta\bar\br.\b.g\bgz\bz |\b| t\bta\bar\br x\bxf\bf -\b-
- $ c\bcd\bd s\bse\ben\bnd\bdm\bma\bai\bil\bl-\b-x\bx.\b.y\by.\b.z\bz
+ $ c\bcd\bd s\bse\ben\bnd\bdm\bma\bai\bil\bl-\b-x\bx.\b.y\by.\b.z\bz/\b/l\bli\bib\bbm\bmi\bil\blt\bte\ber\br
$ m\bma\bak\bke\be
[...lots of output omitted...]
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|j |Always |value of myhostname |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+ |_ |Always |The validated client name |
+ | | |and address |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|{auth_authen} |MAIL, DATA, EOM |SASL login name |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|{auth_author} |MAIL, DATA, EOM |SASL sender |
+++ /dev/null
-The stable Postfix release is called postfix-2.2.x where 2=major
-release number, 2=minor release number, x=patchlevel. The stable
-release never changes except for patches that address bugs or
-emergencies. Patches change the patchlevel and the release date.
-
-New features are developed in snapshot releases. These are called
-postfix-2.3-yyyymmdd where yyyymmdd is the release date (yyyy=year,
-mm=month, dd=day). Patches are never issued for snapshot releases;
-instead, a new snapshot is released.
-
-The mail_release_date configuration parameter (format: yyyymmdd)
-specifies the release date of a stable release or snapshot release.
-
-Incompatibility with Postfix 2.1 and earlier
-============================================
-
-If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
-before proceeding.
-
-Major changes with snapshot 20050510
-====================================
-
-This release improves usability of DSN (enhanced status codes) in
-Postfix access tables, RBL reply templates and in transport maps
-that use the error(8) delivery agent.
-
-- When the SMTP server rejects a sender address, it transforms a
- recipient DSN status (e.g., 4.1.1-4.1.6) into the corresponding
- sender DSN status, and vice versa.
-
-- When the SMTP server rejects non-address information (such as the
- HELO command parameter or the client hostname/address), it
- transforms a sender or recipient DSN status into a generic
- non-address DSN status (e.g., 4.0.0).
-
-These transformations are needed when the same access table or RBL
-reply template are used for client, helo, sender, or recipient
-restrictions; or when the same error(8) mailer information is used
-for both senders and recipients.
-
-Incompatibility with snapshot 20050503
-======================================
-
-The format of some "warning:" messages in the maillog has changed
-so that they are easier to sort:
-
-- The logging now talks about "access table", instead of using three
-different expressions "access table", "access map" and "SMTPD access
-map" for the same thing.
-
-- "non-SMTP command" is now logged BEFORE the client name/address
-and the offending client input, instead of at the end.
-
-Major change with snapshot 20050427+DSN
-=======================================
-
-This is experimental DSN support added to snapshot 20050427. The
-code is not for production purposes; it is not fully tested, some
-names and interfaces are still rough around the edges, and it does
-not update the oqmgr so you have to use qmgr instead. Some
-implementation notes and open issues are described in the
-DSN_SUPPORT_README file (top-level directory).
-
-Incompatibility with snapshot 20050329
-======================================
-
-If you use TLS, you need to execute "postfix reload" because the
-TLS manager protocol has changed.
-
-Incompatibility with snapshot 20050328
-======================================
-
-The logging format has changed. Postfix delivery agents now log the
-RFC 3463 enhanced status code as "dsn=x.y.z" where y and z can be
-up to three digits each. See the file pfloggsum-dsn-patch for an
-update to the pfloggsum script.
-
-After you upgrade from Postfix 2.2 or 2.3 you need to execute
-"postfix reload", otherwise you will keep running the old Postfix
-queue manager, which gives no special treatment to the enhanced
-status codes that it receives from Postfix delivery agents.
-
-Major changes with snapshot 20050328
-====================================
-
-This release introduces support for RFC 3463 enhanced status codes.
-For example, status code 5.1.1 means "recipient unknown". Postfix
-recognizes enhanced status codes in remote server replies, generates
-enhanced status codes while handling email, and reports enhanced
-status codes in non-delivery notifications. This improves the user
-interaction with mail clients that hide the text of error messages
-from users.
-
-You can, but don't have to, specify RFC 3463 enhanced status codes
-in the output from commands that receive mail from a pipe. If a
-command terminates with non-zero exit status, and an enhanced status
-code is present at the beginning of the command output, then that
-status code takes precedence over the non-zero exit status.
-
-You can, but don't have to, specify RFC 3463 enhanced status codes
-in Postfix access maps, header/body_checks REJECT actions, or in
-RBL replies. For example:
-
- REJECT 5.7.1 You can't go here from there
-
-The status 5.7.1 means "no authorization, message refused", and is
-the default for access maps, header/body_checks REJECT actions, and
-for RBL replies.
-
-If you specify your own enhanced status code, the Postfix SMTP
-server will automatically change a leading '5' digit (hard error)
-into '4' where appropriate. This is needed, for example, with
-soft_bounce=yes.
--- /dev/null
+../RELEASE_NOTES
\ No newline at end of file
<blockquote>
<pre>
$ <b>gzcat sendmail-<i>x.y.z</i>.tar.gz | tar xf -</b>
-$ <b>cd sendmail-<i>x.y.z</i></b>
+$ <b>cd sendmail-<i>x.y.z</i>/libmilter</b>
$ <b>make</b>
[...<i>lots of output omitted</i>...]
</pre>
<tr> <td> j </td> <td> Always </td> <td> value of <a href="postconf.5.html#myhostname">myhostname</a> </td>
</tr>
+<tr> <td> _ </td> <td> Always </td> <td> The validated client name
+and address </td> </tr>
+
<tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOM </td> <td> SASL
login name </td> </tr>
--- /dev/null
+Distribution of Milter responsibility
+=====================================
+
+Milters look at the SMTP commands as well as the message content.
+In Postfix these are handled by different processes:
+
+- smtpd(8) (the SMTP server) focuses on the SMTP commands, strips
+ the SMTP encapsulation, and passes envelope information and message
+ content to the cleanup server.
+
+- the cleanup(8) server parses the message content (it understands
+ headers, body, and MIME structure), and creates a queue file with
+ envelope and content information. The cleanup server adds additional
+ envelope records, such as when to send a "delayed mail" notice.
+
+If we want to support message modifications (add/delete recipient,
+add/delete/replace header, replace body) then it pretty much has
+to be implemented in the cleanup server, if we want to avoid extra
+temporary files.
+
+Network versus local submission
+===============================
+
+As of Sendmail 8.12, all mail is received via SMTP, so all mail is
+subject to Miltering (local submissions are queued in a submission
+queue and then delivered via SMTP to the main MTA). In Postfix,
+local submissions are received by the pickup server, which feeds
+the mail into the cleanup server after doing some sanity checks.
+
+How do we set up the Milters with SMTP mail versus local submissions?
+
+- SMTP mail: smtpd creates Milter contexts, and sends them, including
+ their sockets, to the cleanup server. The smtpd is responsible
+ for sending the Milter abort and close messages. Both smtpd and
+ cleanup are responsible for closing their Milter socket. Since
+ smtpd and cleanup inspect mail at different times, there is no
+ conflict with access to the Milter socket.
+
+- Local submission: the cleanup server creates Milter contexts.
+ The cleanup server provides dummy connect and helo information,
+ or perhaps none at all, and provides sender and recipient events.
+ The cleanup server is responsible for sending the Milter abort
+ and close messages, and for closing the Milter socket.
+
+A special case of local submission is "sendmail -t". This creates
+a record stream in which recipients appear after content. However,
+Milters expect to receive envelope information before content, not
+after. This is not a problem: just like a queue manager, the
+cleanup-side Milter client can jump around through the queue file
+and send the information to the Milter in the expected order.
+
+Interaction with XCLIENT, "postsuper -r", and external content filters
+======================================================================
+
+Milter applications expect that the MTA supplies context information
+in the form of Sendmail-like macros (j=hostname, {client_name}=the
+SMTP client hostname, etc.). Not all these macros have a Postfix
+equivalent. Postfix 2.3 makes a subset available.
+
+If Postfix does not implement a specific macro, people can usually
+work around it. But we should avoid inconsistency. If Postfix can
+make macro X available at Milter protocol stage Y, then it must
+also be able to make that macro available at all later Milter
+protocol stages, even those that are handled by a different Postfix
+process.
+
+Thus, when adding Milter support for a specific Sendmail-like macro
+to the SMTP server:
+
+- We may have to update the XCLIENT protocol, so that Milter
+ applications can be tested with XCLIENT. If not, then we must
+ prominently document everywhere that XCLIENT does not provide
+ 100% accurate simulation for Milters. An additional complication
+ is that the SMTP command length is limited, and that each XCLIENT
+ command resets the SMTP server to the 220 stage and generates
+ "connect" events for anvil(8) and for Milters.
+
+- The SMTP server has to send the corresponding attribute to the
+ cleanup server. The cleanup server then stores the attribute in
+ the queue file, so that Milters produce consistent results when
+ mail is re-queued with "postsuper -r".
+
+But wait, there is more. If mail is filtered by an external content
+filter, then it needs to preserve all the Milter attributes so that
+after "postsuper -r", Milters produce the exact same result as when
+mail was received originally by Postfix. Specifically, after
+"postsuper -r" a signing Milter must not sign mail that it did not
+sign on the first pass through Postfix, and it must not reject mail
+that it accepted on the first pass through Postfix.
+
+Instead of trying to re-create the Milter execution environment
+after "postsuper -r" we simply disable Milter processing. The
+rationale for this is: if mail was Miltered before it was written
+to queue file, then there is no need to Milter it again.
+
+We might want to take a similar approach with external (signing or
+blocking) content filters: don't filter mail that has already been
+filtered. Unfortunately, this is complicated by the fact that mail
+can make multiple iterations through Postfix (for example, when
+multiple external content filters are configured). Mail that was
+caught by "postsuper -r" somewhere in the middle if this trip should
+not be allowed to slip past any filters. To achieve this, we would
+have to preserve its current "content_filter" record that specifies
+what needs to be done next. This is the opposite of normal "postsuper
+-r" usage, which is most often intended to remove unwanted
+"content_filter" records. We could add a postsuper command-line
+option to re-queue and preserve "content_filter" records, but is
+is unlikely that humans will ever be able to use this correctly.
+
+Message envelope or content modifications
+=========================================
+
+Milters can send modification requests after receiving the end of
+the message body. If we can implement all the header/body-related
+Milter operations in the cleanup server, then we can try to edit
+the queue file in place, without ever having to make a temporary
+copy. Once a Milter is done editing, the queue file can be used as
+input for the next Milter, and so on. Finally, the cleanup server
+calls fsync() and waits for successful return.
+
+To implement in-place queue file edits, we need to introduce
+surprisingly little change to the existing Postfix queue file
+structure. All we need is a way to specify a jump from one place
+in the file to another.
+
+Postfix does not store queue files as plain text files. Instead all
+information is stored in records with an explicit type and length
+for sender, recipient, arrival time, and so on. Even the content
+that makes up the message header and body is stored as records with
+an explicit type and length. This organization makes it very easy
+to introduce pointer records, which is what we will use to jump
+from one place in a queue file to another place.
+
+- Deleting a recipient or header record is easy - just mark the
+ record as killed. When deleting a recipient, we must kill all
+ recipient records that result from virtual alias expansion of the
+ original recipient address. When deleting a very long header or
+ body line, multiple queue file records may need to be killed. We
+ won't try to reuse the deleted space for other purposes.
+
+- Replacing header or body records involves pointer records.
+ Basically, a record is replaced by overwriting it with a forward
+ pointer to space after the end of the queue file, putting the new
+ record there, followed by a reverse pointer to the record that
+ follows the replaced information. If the replaced record is shorter
+ than a pointer record, we relocate the records that follow it to
+ the new area, until we have enough space for the forward pointer
+ record. See below for a discussion on what it takes to make this
+ safe.
+
+ Postfix queue files are segmented. The first segment is for
+ envelope records, the second for message header and body content,
+ and the third segment is for information that was extracted or
+ generated from the message header and body content. Each segment
+ is terminated by a marker record. For now we don't want to change
+ their location. In particular, we want to avoid moving the start
+ of a segment.
+
+ To ensure that we can always replace a header or body record by
+ a pointer record, without having to relocate a marker record, the
+ cleanup server always places a dummy pointer record at the end
+ of the headers and at the end of the body.
+
+ When a Milter wants to replace an entire body, we have the option
+ to overwrite existing body records until we run out of space, and
+ then writing a pointer to space at the end of the queue file,
+ followed by the remainder of the body, and a pointer to the marker
+ that ends the message content segment.
+
+- Appending a recipient or header record involves pointer records
+ as well. This requires that the queue file already contains a
+ dummy pointer record at the place where we want to append recipient
+ or header content (Milters currently do not replace individual
+ body records, but we could add this if need be). To append,
+ change the dummy pointer into a forward pointer to space after
+ the end of a message, put the new record there, followed by a
+ reverse pointer to the record that follows the forward pointer.
+
+ To append another record, replace the reverse pointer by a forward
+ pointer to space after the end of a message, put the new record
+ there, followed by the value of the reverse pointer that we
+ replace. Thus, there is no one-to-one correspondence between
+ forward and backward pointers! In fact, there can be multiple
+ forward pointers for one reverse pointer.
+
+When relocating a record we must not relocate the target of a jump
+==================================================================
+
+As discussed above, when replacing an existing record, we overwrite
+it with a forward pointer to the new information. If the old record
+is too small we relocate one or more records that follow the record
+that's being replaced, until we have enough space for the forward
+pointer record.
+
+Now we have to become really careful. Could we end up relocating a
+record that is the target of a forward or reverse pointer, and thus
+corrupt the queue file? The answer is NO.
+
+- We never relocate end-of-segment marker records. Instead, the
+ cleanup server writes dummy pointer records to guarantee that
+ there is always space for a pointer.
+
+- When a record is the target of a forward pointer, it is "edited"
+ information that is preceded either by the end-of-queue-file
+ marker record, or it is preceded by the reverse pointer at the
+ end of earlier written "edited" information. Thus, the target of
+ a forward pointer will not be relocated to make space for a pointer
+ record.
+
+- When a record is the target of a reverse pointer, it is always
+ preceded by a forward pointer record (or by a forward pointer
+ record followed by some unused space). Thus, the target of a
+ reverse pointer will not be relocated to make space for a pointer
+ record.
+
+Could we end up relocating a pointer record? Yes, but that is OK,
+as long as pointers contain absolute offsets.
+
+Pointer records introduce the possibility of loops
+==================================================
+
+When a queue file is damaged, a bogus pointer value may send Postfix
+into a loop. This must not happen.
+
+Detecting loops is not trivial:
+
+- A sequence of multiple forward pointers may be followed by one
+ legitimate reverse pointer to the location after the first forward
+ pointer. See above for a discussion of how to append a record to
+ an appended record.
+
+- We do know, however, that there will not be more reverse pointers
+ than forward pointers. But this does not help much.
+
+Perhaps we can include a record count at the start of the queue
+file, so that the record walking code knows that it's looking at
+some records more than once, and return an error indication.
+
+How many bytes do we need for a pointer record?
+===============================================
+
+A pointer record would look like this:
+
+ type (1 byte)
+ offset (see below)
+
+Postfix uses long for queue file size/offset information, and stores
+them as %15ld in the SIZE record at the start of the queue file.
+This is somewhat less than a 64-bit long, but it is enough for a
+some time to come, and it is easily changed without breaking forward
+or backward compatibility.
+
+It does mean, however, that a pointer record can easily exceed the
+length of a header record. This is why we go through the trouble
+of record relocation and dummy records.
<blockquote>
<pre>
$ <b>gzcat sendmail-<i>x.y.z</i>.tar.gz | tar xf -</b>
-$ <b>cd sendmail-<i>x.y.z</i></b>
+$ <b>cd sendmail-<i>x.y.z</i>/libmilter</b>
$ <b>make</b>
[...<i>lots of output omitted</i>...]
</pre>
<tr> <td> j </td> <td> Always </td> <td> value of myhostname </td>
</tr>
+<tr> <td> _ </td> <td> Always </td> <td> The validated client name
+and address </td> </tr>
+
<tr> <td> {auth_authen} </td> <td> MAIL, DATA, EOM </td> <td> SASL
login name </td> </tr>
#endif
MILTERS *milters; /* mail filters */
const char *client_name; /* real or ersatz client */
+ const char *reverse_name; /* real or ersatz client */
const char *client_addr; /* real or ersatz client */
int client_af; /* real or ersatz client */
const char *client_port; /* real or ersatz client */
/*
* Connect macros.
*/
+ if (strcmp(name, S8_MAC__) == 0) {
+ vstring_sprintf(state->temp1, "%s [%s]",
+ state->reverse_name, state->client_addr);
+ if (strcasecmp(state->client_name, state->reverse_name) != 0)
+ vstring_strcat(state->temp1, " (may be forged)");
+ return (STR(state->temp1));
+ }
if (strcmp(name, S8_MAC_J) == 0)
return (var_myhostname);
if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
- return (nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR));
+ return (state->client_addr);
if (strcmp(name, S8_MAC_CLIENT_NAME) == 0)
- return (nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_NAME));
+ return (state->client_name);
+ if (strcmp(name, S8_MAC_CLIENT_PTR) == 0)
+ return (state->reverse_name);
/*
* MAIL FROM macros.
#define NO_CLIENT_PORT "0"
state->client_name = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_NAME);
+ state->reverse_name =
+ nvtable_find(state->attr, MAIL_ATTR_ACT_REVERSE_CLIENT_NAME);
state->client_addr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR);
state->client_port = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_PORT);
proto_attr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_AF);
state->client_af = AF_INET;
} else
state->client_af = atoi(proto_attr);
+ if (state->reverse_name == 0)
+ state->reverse_name = state->client_name;
if (state->client_port == 0)
state->client_port = NO_CLIENT_PORT;
}
state->verp_delims = 0;
state->milters = 0;
state->client_name = 0;
+ state->reverse_name = 0;
state->client_addr = 0;
state->client_af = 0;
state->client_port = 0;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20060720"
+#define MAIL_RELEASE_DATE "20060721"
#define MAIL_VERSION_NUMBER "2.4"
#ifdef SNAPSHOT
* bounces its copy of the message. because the original input file is
* not readable by the bounce service.
*
+ * If mail is re-injected with "postsuper -r", disable Milter applications.
+ * If they were run before the mail was queued then there is no need to
+ * run them again. Moreover, the queue file does not contain enough
+ * information to reproduce the exact same SMTP events and Sendmail
+ * macros that Milters received when the mail originally arrived in
+ * Postfix.
+ *
* The actual message copying code is in a separate routine, so that it is
* easier to implement the many possible error exits without forgetting
* to close files, or to release memory.
cleanup_flags =
input_transp_cleanup(CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL,
pickup_input_transp_mask);
+ if (info->st.st_uid == var_owner_uid && (info->st.st_mode & S_IROTH) == 0)
+ cleanup_flags &= ~CLEANUP_FLAG_MILTER;
cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
*/
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ACT_CLIENT_NAME, state->name);
+ rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
+ MAIL_ATTR_ACT_REVERSE_CLIENT_NAME, state->reverse_name);
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ACT_CLIENT_ADDR, state->addr);
if (state->helo_name)
smtpd_chat_reply(state, "501 5.7.1 DSN support is disabled");
return (-1);
}
+ vstring_strcpy(state->dsn_orcpt_buf, arg + 6);
if (dsn_orcpt_addr
- || (coded_addr = split_at(arg + 6, ';')) == 0
+ || (coded_addr = split_at(STR(state->dsn_orcpt_buf), ';')) == 0
|| xtext_unquote(state->dsn_buf, coded_addr) == 0
- || *(dsn_orcpt_type = arg + 6) == 0) {
+ || *(dsn_orcpt_type = STR(state->dsn_orcpt_buf)) == 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state,
"501 5.5.4 Error: Bad ORCPT parameter syntax");
char *dsn_envid; /* temporary MAIL FROM state */
int dsn_ret; /* temporary MAIL FROM state */
VSTRING *dsn_buf; /* scratch space for xtext expansion */
+ VSTRING *dsn_orcpt_buf; /* scratch space for ORCPT parsing */
/*
* Pass-through proxy client.
/*
* Connect macros.
*/
+ if (strcmp(name, S8_MAC__) == 0) {
+ if (state->expand_buf == 0)
+ state->expand_buf = vstring_alloc(10);
+ vstring_sprintf(state->expand_buf, "%s [%s]",
+ state->reverse_name, state->addr);
+ if (strcasecmp(state->name, state->reverse_name) != 0)
+ vstring_strcat(state->expand_buf, " (may be forged)");
+ return (STR(state->expand_buf));
+ }
if (strcmp(name, S8_MAC_J) == 0)
return (var_myhostname);
if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
#endif
state->dsn_envid = 0;
state->dsn_buf = vstring_alloc(100);
+ state->dsn_orcpt_buf = vstring_alloc(100);
#ifdef USE_TLS
state->tls_use_tls = 0;
state->tls_enforce_tls = 0;