*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
with "*" are not settable by the user but are used by the option-reading
software for alternative value types. Some options are publicly visible and so
are stored in the driver instance block. These are flagged with opt_public. */
+#define LOFF(field) OPT_OFF(autoreply_transport_options_block, field)
optionlist autoreply_transport_options[] = {
- { "bcc", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, bcc) },
- { "cc", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, cc) },
- { "file", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, file) },
- { "file_expand", opt_bool,
- (void *)offsetof(autoreply_transport_options_block, file_expand) },
- { "file_optional", opt_bool,
- (void *)offsetof(autoreply_transport_options_block, file_optional) },
- { "from", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, from) },
- { "headers", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, headers) },
- { "log", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, logfile) },
- { "mode", opt_octint,
- (void *)offsetof(autoreply_transport_options_block, mode) },
- { "never_mail", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, never_mail) },
- { "once", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, oncelog) },
- { "once_file_size", opt_int,
- (void *)offsetof(autoreply_transport_options_block, once_file_size) },
- { "once_repeat", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, once_repeat) },
- { "reply_to", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, reply_to) },
- { "return_message", opt_bool,
- (void *)offsetof(autoreply_transport_options_block, return_message) },
- { "subject", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, subject) },
- { "text", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, text) },
- { "to", opt_stringptr,
- (void *)offsetof(autoreply_transport_options_block, to) },
+ { "bcc", opt_stringptr, LOFF(bcc) },
+ { "cc", opt_stringptr, LOFF(cc) },
+ { "file", opt_stringptr, LOFF(file) },
+ { "file_expand", opt_bool, LOFF(file_expand) },
+ { "file_optional", opt_bool, LOFF(file_optional) },
+ { "from", opt_stringptr, LOFF(from) },
+ { "headers", opt_stringptr, LOFF(headers) },
+ { "log", opt_stringptr, LOFF(logfile) },
+ { "mode", opt_octint, LOFF(mode) },
+ { "never_mail", opt_stringptr, LOFF(never_mail) },
+ { "once", opt_stringptr, LOFF(oncelog) },
+ { "once_file_size", opt_int, LOFF(once_file_size) },
+ { "once_repeat", opt_stringptr, LOFF(once_repeat) },
+ { "reply_to", opt_stringptr, LOFF(reply_to) },
+ { "return_message", opt_bool, LOFF(return_message) },
+ { "subject", opt_stringptr, LOFF(subject) },
+ { "text", opt_stringptr, LOFF(text) },
+ { "to", opt_stringptr, LOFF(to) },
};
/* Size of the options list. An extern variable has to be used so that its
#else /*!MACRO_PREDEF*/
-/* Default private options block for the autoreply transport. */
+/* Default private options block for the autoreply transport.
+All non-mentioned lements zero/null/false. */
autoreply_transport_options_block autoreply_transport_option_defaults = {
- NULL, /* from */
- NULL, /* reply_to */
- NULL, /* to */
- NULL, /* cc */
- NULL, /* bcc */
- NULL, /* subject */
- NULL, /* headers */
- NULL, /* text */
- NULL, /* file */
- NULL, /* logfile */
- NULL, /* oncelog */
- NULL, /* once_repeat */
- NULL, /* never_mail */
- 0600, /* mode */
- 0, /* once_file_size */
- FALSE, /* file_expand */
- FALSE, /* file_optional */
- FALSE /* return message */
+ .mode = 0600,
};
list. Any that are found are removed.
Arguments:
- listptr points to the list of addresses
+ list list of addresses to be checked
never_mail an address list, already expanded
-Returns: nothing
+Returns: edited replacement address list, or NULL, or original
*/
-static void
-check_never_mail(uschar **listptr, const uschar *never_mail)
+static uschar *
+check_never_mail(uschar * list, const uschar * never_mail)
{
-uschar *s = *listptr;
+rmark reset_point = store_mark();
+uschar * newlist = string_copy(list);
+uschar * s = newlist;
+BOOL hit = FALSE;
-while (*s != 0)
+while (*s)
{
uschar *error, *next;
uschar *e = parse_find_address_end(s, FALSE);
/* If there is some kind of syntax error, just give up on this header
line. */
- if (next == NULL) break;
+ if (!next) break;
/* See if the address is on the never_mail list */
{
DEBUG(D_transport)
debug_printf("discarding recipient %s (matched never_mail)\n", next);
+ hit = TRUE;
if (terminator == ',') e++;
memmove(s, e, Ustrlen(e) + 1);
}
}
}
+/* If no addresses were removed, retrieve the memory used and return
+the original. */
+
+if (!hit)
+ {
+ store_reset(reset_point);
+ return list;
+ }
+
/* Check to see if we removed the last address, leaving a terminating comma
that needs to be removed */
-s = *listptr + Ustrlen(*listptr);
-while (s > *listptr && (isspace(s[-1]) || s[-1] == ',')) s--;
+s = newlist + Ustrlen(newlist);
+while (s > newlist && (isspace(s[-1]) || s[-1] == ',')) s--;
*s = 0;
-/* Check to see if there any addresses left; if not, set NULL */
+/* Check to see if there any addresses left; if not, return NULL */
+
+s = newlist;
+while (s && isspace(*s)) s++;
+if (*s)
+ return newlist;
-s = *listptr;
-while (s != 0 && isspace(*s)) s++;
-if (*s == 0) *listptr = NULL;
+store_reset(reset_point);
+return NULL;
}
return FALSE;
if (oncerepeat)
- {
- once_repeat_sec = readconf_readtime(oncerepeat, 0, FALSE);
- if (once_repeat_sec < 0)
+ if ((once_repeat_sec = readconf_readtime(oncerepeat, 0, FALSE)) < 0)
{
addr->transport_return = FAIL;
addr->message = string_sprintf("Invalid time value \"%s\" for "
"\"once_repeat\" in %s transport", oncerepeat, tblock->name);
return FALSE;
}
- }
}
/* If the never_mail option is set, we have to scan all the recipients and
return FALSE;
}
- if (to) check_never_mail(&to, never_mail);
- if (cc) check_never_mail(&cc, never_mail);
- if (bcc) check_never_mail(&bcc, never_mail);
+ if (to) to = check_never_mail(to, never_mail);
+ if (cc) cc = check_never_mail(cc, never_mail);
+ if (bcc) bcc = check_never_mail(bcc, never_mail);
if (!to && !cc && !bcc)
{
else
{
EXIM_DATUM key_datum, result_datum;
- uschar * dirname = string_copy(oncelog);
- uschar * s;
+ uschar * dirname, * s;
- if ((s = Ustrrchr(dirname, '/'))) *s = '\0';
+ dirname = (s = Ustrrchr(oncelog, '/'))
+ ? string_copyn(oncelog, s - oncelog) : NULL;
EXIM_DBOPEN(oncelog, dirname, O_RDWR|O_CREAT, ob->mode, &dbm_file);
if (!dbm_file)
{
/* Make a subprocess to send the message */
-pid = child_open_exim(&fd);
-
-/* Creation of child failed; defer this delivery. */
-
-if (pid < 0)
+if ((pid = child_open_exim(&fd, US"autoreply")) < 0)
{
+ /* Creation of child failed; defer this delivery. */
+
addr->transport_return = DEFER;
addr->basic_errno = errno;
addr->message = string_sprintf("Failed to create child process to send "
if (ff)
{
+debug_printf("%s %d: ff\n", __FUNCTION__, __LINE__);
while (Ufgets(big_buffer, big_buffer_size, ff) != NULL)
{
if (file_expand)
if (return_message)
{
- uschar *rubric = (tblock->headers_only)?
- US"------ This is a copy of the message's header lines.\n"
- : (tblock->body_only)?
- US"------ This is a copy of the body of the message, without the headers.\n"
- :
- US"------ This is a copy of the message, including all the headers.\n";
+debug_printf("%s %d: ret msg\n", __FUNCTION__, __LINE__);
+ uschar *rubric = tblock->headers_only
+ ? US"------ This is a copy of the message's header lines.\n"
+ : tblock->body_only
+ ? US"------ This is a copy of the body of the message, without the headers.\n"
+ : US"------ This is a copy of the message, including all the headers.\n";
transport_ctx tctx = {
.u = {.fd = fileno(fp)},
.tblock = tblock,