From 1c5595bf81d8bb5ab9d79e85a10e82b9e54ec6a1 Mon Sep 17 00:00:00 2001 From: InterLinked1 <24227567+InterLinked1@users.noreply.github.com> Date: Sun, 12 Jan 2025 13:48:31 -0500 Subject: [PATCH] net_smtp: Update message processor interface. A common thing for each message processor to do is check the direction, scope, and filter iteration of a processor pass (among other things) to determine if it wants to handle it. Since these are common checks, pull these out from individual modules into net_smtp, and have the processor callback define when it should run using bitmasks for each of these properties. This is similar to the filter interface, which already allows bitmasks to be passed along. Also fix a recent bug where delivery callbacks in mod_smtp_mailing_lists were always being run, even if the recipient wasn't a mailing list. Additionally, a lot of noisy debug output has been disabled by default. --- include/net_smtp.h | 35 +++++++--- modules/mod_mailscript.c | 31 +++++---- modules/mod_sieve.c | 19 +++--- modules/mod_smtp_greylisting.c | 25 +++---- modules/mod_smtp_mailing_lists.c | 18 +++--- modules/mod_smtp_recipient_monitor.c | 20 +++--- nets/net_smtp.c | 97 ++++++++++++++++++---------- 7 files changed, 149 insertions(+), 96 deletions(-) diff --git a/include/net_smtp.h b/include/net_smtp.h index db3fa84..2d6e85f 100644 --- a/include/net_smtp.h +++ b/include/net_smtp.h @@ -74,8 +74,8 @@ enum smtp_filter_type { }; enum smtp_filter_scope { - SMTP_SCOPE_INDIVIDUAL = 0, /* Run individually for each recipient of a message */ - SMTP_SCOPE_COMBINED, /* Run once for all recipients of a message */ + SMTP_SCOPE_INDIVIDUAL = (1 << 0), /* Run individually for each recipient of a message */ + SMTP_SCOPE_COMBINED = (1 << 1), /* Run once for all recipients of a message */ }; enum smtp_direction { @@ -84,6 +84,8 @@ enum smtp_direction { SMTP_DIRECTION_OUT = (1 << 2), /*!< Outgoing mail to another MTA */ }; +#define SMTP_DIRECTION_ALL (SMTP_DIRECTION_SUBMIT | SMTP_DIRECTION_IN | SMTP_DIRECTION_OUT) + /*! * \note There are two different "filtering" APIs available, * based on the smtp_filter_data (filters) and smtp_msg_process (message processors) structures. @@ -251,11 +253,13 @@ int smtp_message_quarantinable(struct smtp_session *smtp); #define SMTP_MSG_DIRECTION_OUT 1 enum msg_process_iteration { - FILTER_BEFORE_MAILBOX = 0, /*!< Execute before the mailbox filters */ - FILTER_MAILBOX, /*!< Mailbox filter execution */ - FILTER_AFTER_MAILBOX, /*!< Execute after the mailbox filters */ + FILTER_BEFORE_MAILBOX = (1 << 0), /*!< Execute before the mailbox filters */ + FILTER_MAILBOX = (1 << 1), /*!< Mailbox filter execution */ + FILTER_AFTER_MAILBOX = (1 << 2), /*!< Execute after the mailbox filters */ }; +#define FILTER_ALL_PASSES (FILTER_BEFORE_MAILBOX | FILTER_MAILBOX | FILTER_AFTER_MAILBOX) + struct smtp_msg_process { /* Inputs */ struct smtp_session *smtp; /*!< SMTP session. Not originally included, so try to avoid using this! */ @@ -284,6 +288,13 @@ struct smtp_msg_process { char *relayroute; /*!< Relay route */ }; +struct smtp_message_processor { + int (*callback)(struct smtp_msg_process *mproc); /*!< Callback function to execute to process the message */ + enum smtp_direction dir; /*!< Direction(s) for which to execute callback */ + enum smtp_filter_scope scope; /*!< Scope(s) for which to execute callback */ + enum msg_process_iteration iteration; /*!< Pass(es) for which to execute callback (3 passes are done for each processor) */ +}; + /*! \brief Initialize an smtp_msg_process structure for use */ void smtp_mproc_init(struct smtp_session *smtp, struct smtp_msg_process *mproc); @@ -293,17 +304,19 @@ void smtp_mproc_init(struct smtp_session *smtp, struct smtp_msg_process *mproc); */ #define smtp_register_processor(cb) __smtp_register_processor(cb, BBS_MODULE_SELF) -int __smtp_register_processor(int (*cb)(struct smtp_msg_process *mproc), void *mod); +int __smtp_register_processor(struct smtp_message_processor *proc, void *mod); /*! \brief Unregister an SMTP processor previously registered with smtp_register_processor */ -int smtp_unregister_processor(int (*cb)(struct smtp_msg_process *mproc)); +int smtp_unregister_processor(struct smtp_message_processor *proc); /*! * \brief Run SMTP callbacks for a message (only called by net_smtp) * \param mproc * \retval 0 to continue (some or all callbacks were executed and none returned -1), -1 to abort transaction immediately (because a callback returned -1) */ -int smtp_run_callbacks(struct smtp_msg_process *mproc, enum smtp_filter_scope scope); +#define smtp_run_callbacks(mproc, scope) __smtp_run_callbacks(mproc, scope, __FILE__, __LINE__, __func__) + +int __smtp_run_callbacks(struct smtp_msg_process *mproc, enum smtp_filter_scope scope, const char *file, int line, const char *func); struct smtp_response { /* Response */ @@ -325,8 +338,10 @@ struct smtp_response { * \param freedata * \retval 0 to continue, -1 if message should be aborted and a failure response generated, 1 if message is being silently dropped */ -int smtp_run_delivery_callbacks(struct smtp_session *smtp, struct smtp_msg_process *mproc, struct mailbox *mbox, struct smtp_response **restrict resp, - enum smtp_direction dir, enum smtp_filter_scope scope, const char *recipient, size_t datalen, void **freedata); +#define smtp_run_delivery_callbacks(smtp, mproc, mbox, resp, dir, scope, recipient, datalen, freedata) __smtp_run_delivery_callbacks(smtp, mproc, mbox, resp, dir, scope, recipient, datalen, freedata, __FILE__, __LINE__, __func__) + +int __smtp_run_delivery_callbacks(struct smtp_session *smtp, struct smtp_msg_process *mproc, struct mailbox *mbox, struct smtp_response **restrict resp, + enum smtp_direction dir, enum smtp_filter_scope scope, const char *recipient, size_t datalen, void **freedata, const char *file, int line, const char *func); #define smtp_abort(r, c, sub, msg) \ r->code = c; \ diff --git a/modules/mod_mailscript.c b/modules/mod_mailscript.c index af609c5..a03a339 100644 --- a/modules/mod_mailscript.c +++ b/modules/mod_mailscript.c @@ -240,7 +240,10 @@ static int test_condition(struct smtp_msg_process *mproc, int lineno, int lastre REQUIRE_ARG(s);/* Empty match implicitly matches anything anyways */ +#ifdef EXTRA_DEBUG bbs_debug(7, "Evaluating condition: %s\n", s); +#endif + next = strsep(&s, " "); REQUIRE_ARG(s); if (!strcasecmp(next, "NOT")) { @@ -636,9 +639,12 @@ static int run_rules(struct smtp_msg_process *mproc, const char *rulesfile, cons } else { bbs_warning("Invalid command: %s\n", s); } + if (!was_skip && skip_rule) { /* Rule statement just evaluated as false */ +#ifdef EXTRA_DEBUG /* We butchered the rule statement with strsep so can't print it out again */ bbs_debug(5, "Skipping rule, condition false\n"); +#endif } } @@ -654,15 +660,6 @@ static int mailscript(struct smtp_msg_process *mproc) char filepath[256]; const char *mboxmaildir; - if (mproc->scope != SMTP_SCOPE_INDIVIDUAL) { - /* Filters are only run for individual delivery. - * Even global rules should use SMTP_SCOPE_INDIVIDUAL, - * since they could manipulate the mailbox in some way, - * and we don't have a single mailbox if processing - * a message that will get delivered to multiple recipients. */ - return 0; - } - /* Calculate maildir path, if we have a mailbox */ if (mproc->userid) { snprintf(filepath, sizeof(filepath), "%s/%d", mailbox_maildir(NULL), mproc->userid); @@ -701,16 +698,28 @@ static int mailscript(struct smtp_msg_process *mproc) } } +struct smtp_message_processor proc = { + .callback = mailscript, + .dir = SMTP_DIRECTION_ALL, + /* Filters are only run for individual delivery. + * Even global rules should use SMTP_SCOPE_INDIVIDUAL, + * since they could manipulate the mailbox in some way, + * and we don't have a single mailbox if processing + * a message that will get delivered to multiple recipients. */ + .scope = SMTP_SCOPE_INDIVIDUAL, + .iteration = FILTER_ALL_PASSES, /* We handle all passes, with more granular logic in the callback */ +}; + static int load_module(void) { snprintf(before_rules, sizeof(before_rules), "%s/before.rules", mailbox_maildir(NULL)); snprintf(after_rules, sizeof(after_rules), "%s/after.rules", mailbox_maildir(NULL)); - return smtp_register_processor(mailscript); + return smtp_register_processor(&proc); } static int unload_module(void) { - return smtp_unregister_processor(mailscript); + return smtp_unregister_processor(&proc); } BBS_MODULE_INFO_DEPENDENT("SMTP MailScript Engine", "net_smtp.so"); diff --git a/modules/mod_sieve.c b/modules/mod_sieve.c index df4a943..08564ec 100644 --- a/modules/mod_sieve.c +++ b/modules/mod_sieve.c @@ -581,14 +581,6 @@ static int sieve(struct smtp_msg_process *mproc) char filepath[256]; const char *mboxmaildir; - if (mproc->scope != SMTP_SCOPE_INDIVIDUAL) { - return 0; /* Filters are only run for individual delivery */ - } - - if (mproc->direction != SMTP_MSG_DIRECTION_IN) { - return 0; /* Currently, Sieve can only be used for filtering inbound mail. If support for Sieve extension for outbound mail is added, this could change. */ - } - /* Calculate maildir path, if we have a mailbox */ if (mproc->userid) { snprintf(filepath, sizeof(filepath), "%s/%d", mailbox_maildir(NULL), mproc->userid); @@ -707,6 +699,13 @@ static int script_validate(const char *filename, struct mailbox *mbox, char **er } #pragma GCC diagnostic pop /* -Wdiscarded-qualifiers */ +struct smtp_message_processor proc = { + .callback = sieve, + .dir = SMTP_DIRECTION_IN, /* Currently, Sieve can only be used for filtering inbound mail. If support for Sieve extension for outbound mail is added, this could change. */ + .scope = SMTP_SCOPE_INDIVIDUAL, /* Filters are only run for individual delivery */ + .iteration = FILTER_ALL_PASSES, /* We handle all passes, with more granular logic in the callback */ +}; + static int load_module(void) { if (SIEVE2_VALUE_LAST != 27) { @@ -718,13 +717,13 @@ static int load_module(void) if (sieve_register_provider(script_validate, get_capabilities())) { return -1; } - return smtp_register_processor(sieve); + return smtp_register_processor(&proc); } static int unload_module(void) { sieve_unregister_provider(script_validate); - return smtp_unregister_processor(sieve); + return smtp_unregister_processor(&proc); } BBS_MODULE_INFO_DEPENDENT("RFC5228 Sieve Filtering", "net_smtp.so"); diff --git a/modules/mod_smtp_greylisting.c b/modules/mod_smtp_greylisting.c index e5ebf26..70f3c4a 100755 --- a/modules/mod_smtp_greylisting.c +++ b/modules/mod_smtp_greylisting.c @@ -314,22 +314,13 @@ static int processor(struct smtp_msg_process *mproc) time_t now; int spamscore; - if (mproc->scope != SMTP_SCOPE_COMBINED) { - return 0; - } else if (mproc->dir != SMTP_DIRECTION_IN) { - return 0; /* Only applies to incoming mail */ - } else if (smtp_is_exempt_relay(mproc->smtp)) { + if (smtp_is_exempt_relay(mproc->smtp)) { /* We don't greylist outbound mail, only inbound mail from the Internet. * Technically, this check is a subset of bbs_ip_is_private_ipv4 below, * which ignores all private IPs. However, this is a flag check, * as opposed to parsing the IP address, so in a potentially common case, * this is much quicker to check now. */ return 0; - } else if (mproc->iteration != FILTER_BEFORE_MAILBOX) { - /* We want to do this on the first pass, before a user's mailbox rules even run. - * Greylist typically takes precedence over most other handling. - * This is still after DATA and after SpamAssassin has run, so we're good. */ - return 0; } else if (!mproc->smtp || !smtp_node(mproc->smtp)) { bbs_warning("Not an interactive session?\n"); return 0; @@ -473,12 +464,22 @@ static int load_config(void) return 0; } +struct smtp_message_processor proc = { + .callback = processor, + .dir = SMTP_DIRECTION_IN, /* Only applies to incoming mail */ + .scope = SMTP_SCOPE_COMBINED, /* This is for the message as a whole, not instances of its delivery */ + /* We want to do this on the first pass, before a user's mailbox rules even run. + * Greylist typically takes precedence over most other handling. + * This is still after DATA and after SpamAssassin has run, so we're good. */ + .iteration = FILTER_BEFORE_MAILBOX, +}; + static int load_module(void) { if (load_config()) { return -1; } - if (smtp_register_processor(processor)) { + if (smtp_register_processor(&proc)) { return -1; } bbs_cli_register_multiple(cli_commands_greylisting); @@ -489,7 +490,7 @@ static int unload_module(void) { int res; bbs_cli_unregister_multiple(cli_commands_greylisting); - res = smtp_unregister_processor(processor); + res = smtp_unregister_processor(&proc); RWLIST_WRLOCK_REMOVE_ALL(&greylisted_messages, entry, free); RWLIST_WRLOCK_REMOVE_ALL(&safe_senders, entry, free); return res; diff --git a/modules/mod_smtp_mailing_lists.c b/modules/mod_smtp_mailing_lists.c index 4d9253c..cc87931 100644 --- a/modules/mod_smtp_mailing_lists.c +++ b/modules/mod_smtp_mailing_lists.c @@ -539,6 +539,15 @@ static int blast_exploder(struct smtp_session *smtp, struct smtp_response *resp, return 0; } + safe_strncpy(name, user, sizeof(name)); + subaddr = name; + addr = strsep(&subaddr, "+"); + + l = find_list(addr, domain); + if (!l) { + return 0; + } + /* Even though it's not really an "outgoing" message, * it makes more sense to run callbacks as such here. * There is no mailbox corresponding to this filter execution, @@ -556,15 +565,6 @@ static int blast_exploder(struct smtp_session *smtp, struct smtp_response *resp, resp = &tmpresp; } - safe_strncpy(name, user, sizeof(name)); - subaddr = name; - addr = strsep(&subaddr, "+"); - - l = find_list(addr, domain); - if (!l) { - return 0; - } - /* First, validate what permissions the sending user has for this list */ if (!sender_authorized(l, smtp, from)) { bbs_auth("Unauthorized attempt to post to list %s by %s (%s) (fromlocal: %d)\n", diff --git a/modules/mod_smtp_recipient_monitor.c b/modules/mod_smtp_recipient_monitor.c index 88b4c92..7fd807f 100755 --- a/modules/mod_smtp_recipient_monitor.c +++ b/modules/mod_smtp_recipient_monitor.c @@ -77,18 +77,9 @@ static int processor(struct smtp_msg_process *mproc) struct deferred_attempt *attempt; const char *fromheader; - if (mproc->dir != SMTP_DIRECTION_SUBMIT) { - return 0; /* Only applies to user submissions */ - } - if (mproc->scope != SMTP_SCOPE_COMBINED) { - return 0; /* We don't need to do this per-recipient, once for all is good, hence combined */ - } if (!mproc->userid) { return 0; /* Only for user-level filters, not global */ } - if (mproc->iteration != FILTER_BEFORE_MAILBOX) { - return 0; /* Do on pre-mailbox pass, to nip it in the bud as early as possible. */ - } if (!mproc->recipients) { bbs_warning("Recipient list not available?\n"); return 0; @@ -248,14 +239,21 @@ static int processor(struct smtp_msg_process *mproc) return -1; } +struct smtp_message_processor proc = { + .callback = processor, + .dir = SMTP_DIRECTION_SUBMIT, /* Only applies to user submissions */ + .scope = SMTP_SCOPE_COMBINED, /* This is for the message as a whole, not instances of its delivery */ + .iteration = FILTER_BEFORE_MAILBOX, /* Do on pre-mailbox pass, to nip it in the bud as early as possible. */ +}; + static int load_module(void) { - return smtp_register_processor(processor); + return smtp_register_processor(&proc); } static int unload_module(void) { - int res = smtp_unregister_processor(processor); + int res = smtp_unregister_processor(&proc); RWLIST_WRLOCK_REMOVE_ALL(&deferred_attempts, entry, free); return res; } diff --git a/nets/net_smtp.c b/nets/net_smtp.c index 65870da..d973aa8 100644 --- a/nets/net_smtp.c +++ b/nets/net_smtp.c @@ -1515,7 +1515,9 @@ void smtp_run_filters(struct smtp_filter_data *fdata, enum smtp_direction dir) int res = 0; total++; if (!(f->direction & fdata->dir)) { +#ifdef DEBUG_FILTERS bbs_debug(5, "Ignoring %s SMTP filter %s %p (wrong direction)...\n", smtp_filter_direction_name(f->direction), smtp_filter_type_name(f->type), f); +#endif continue; } @@ -1528,12 +1530,16 @@ void smtp_run_filters(struct smtp_filter_data *fdata, enum smtp_direction dir) /* Filter applicable to this direction */ if (f->scope == SMTP_SCOPE_INDIVIDUAL) { if (!fdata->recipient) { +#ifdef DEBUG_FILTERS bbs_debug(5, "Ignoring %s SMTP filter %s %p (wrong scope)...\n", smtp_filter_direction_name(f->direction), smtp_filter_type_name(f->type), f); +#endif continue; } } else { if (fdata->recipient) { +#ifdef DEBUG_FILTERS bbs_debug(5, "Ignoring %s SMTP filter %s %p (wrong scope)...\n", smtp_filter_direction_name(f->direction), smtp_filter_type_name(f->type), f); +#endif continue; } } @@ -1542,7 +1548,9 @@ void smtp_run_filters(struct smtp_filter_data *fdata, enum smtp_direction dir) * Unless, it's simply adding the Received header, in which case, still do it, * for things like mailing lists which involve using smtp_inject. */ if (f->priority != 0) { +#ifdef DEBUG_FILTERS bbs_debug(5, "Ignoring %s SMTP filter %s %p (no node)...\n", smtp_filter_direction_name(f->direction), smtp_filter_type_name(f->type), f); +#endif continue; } } @@ -1619,14 +1627,14 @@ void smtp_mproc_init(struct smtp_session *smtp, struct smtp_msg_process *mproc) } struct smtp_processor { - int (*cb)(struct smtp_msg_process *proc); + const struct smtp_message_processor *processor; void *mod; RWLIST_ENTRY(smtp_processor) entry; }; static RWLIST_HEAD_STATIC(processors, smtp_processor); -int __smtp_register_processor(int (*cb)(struct smtp_msg_process *mproc), void *mod) +int __smtp_register_processor(struct smtp_message_processor *processor, void *mod) { struct smtp_processor *proc; @@ -1635,7 +1643,7 @@ int __smtp_register_processor(int (*cb)(struct smtp_msg_process *mproc), void *m return -1; } - proc->cb = cb; + proc->processor = processor; proc->mod = mod; RWLIST_WRLOCK(&processors); @@ -1644,53 +1652,74 @@ int __smtp_register_processor(int (*cb)(struct smtp_msg_process *mproc), void *m return 0; } -int smtp_unregister_processor(int (*cb)(struct smtp_msg_process *mproc)) +int smtp_unregister_processor(struct smtp_message_processor *processor) { struct smtp_processor *proc; - proc = RWLIST_WRLOCK_REMOVE_BY_FIELD(&processors, cb, cb, entry); + proc = RWLIST_WRLOCK_REMOVE_BY_FIELD(&processors, processor, processor, entry); if (!proc) { - bbs_error("Couldn't remove processor %p\n", cb); + bbs_error("Couldn't remove processor %p\n", processor); return -1; } free(proc); return 0; } -int smtp_run_callbacks(struct smtp_msg_process *mproc, enum smtp_filter_scope scope) +/*! \brief Single pass of callbacks */ +static inline int __run_callbacks(struct smtp_msg_process *mproc, enum msg_process_iteration iteration, const char *file, int line, const char *func) { - int res = 0; + int res; struct smtp_processor *proc; - mproc->scope = scope; /* This could be set earlier, but is made an argument to this function to ensure callers explicitly set it */ + mproc->iteration = iteration; -#define EXECUTE_FILTERS(iter)\ - mproc->iteration = iter; \ - bbs_debug(3, "Running SMTP callbacks for %s scope, %s direction, %s pass\n", \ - mproc->scope == SMTP_SCOPE_INDIVIDUAL ? "INDIVIDUAL" : "COMBINED", \ - mproc->dir == SMTP_DIRECTION_IN ? "IN" : mproc->dir == SMTP_DIRECTION_SUBMIT ? "SUBMIT" : "OUT", \ - mproc->iteration == FILTER_BEFORE_MAILBOX ? "pre-mailbox" : mproc->iteration == FILTER_AFTER_MAILBOX ? "post-mailbox" : "mailbox"); \ - RWLIST_TRAVERSE(&processors, proc, entry) { \ - bbs_module_ref(proc->mod, 3); \ - res |= proc->cb(mproc); \ - bbs_module_unref(proc->mod, 3); \ - if (res) { \ - bbs_debug(4, "Message processor returned %d\n", res); \ - goto done; /* Stop processing immediately if a processor returns nonzero */ \ - } \ - } \ + __bbs_log(LOG_DEBUG, 3, file, line, func, "Running SMTP callbacks for %s scope, %s direction, %s pass\n", + mproc->scope == SMTP_SCOPE_INDIVIDUAL ? "INDIVIDUAL" : "COMBINED", + mproc->dir == SMTP_DIRECTION_IN ? "IN" : mproc->dir == SMTP_DIRECTION_SUBMIT ? "SUBMIT" : "OUT", + mproc->iteration == FILTER_BEFORE_MAILBOX ? "pre-mailbox" : mproc->iteration == FILTER_AFTER_MAILBOX ? "post-mailbox" : "mailbox"); + + RWLIST_TRAVERSE(&processors, proc, entry) { + const struct smtp_message_processor *processor = proc->processor; + /* If it doesn't match what the processor wants, skip it */ + if (!(processor->dir & mproc->dir)) { + continue; + } else if (!(processor->scope & mproc->scope)) { + continue; + } else if (!(processor->iteration & mproc->iteration)) { + continue; + } + /* No need to ref the module unless we are actually going to execute. + * The module can't unregister the processor without WRLOCK'ing the list, + * and we have it locked for this traversal. */ + bbs_module_ref(proc->mod, 3); + res = processor->callback(mproc); + bbs_module_unref(proc->mod, 3); + if (res) { + __bbs_log(LOG_DEBUG, 4, file, line, func, "Message processor returned %d\n", res); + return res; /* Stop processing immediately if a processor returns nonzero */ + } + } + return 0; +} + +int __smtp_run_callbacks(struct smtp_msg_process *mproc, enum smtp_filter_scope scope, const char *file, int line, const char *func) +{ + int res = 0; + + mproc->scope = scope; /* This could be set earlier, but is made an argument to this function to ensure callers explicitly set it */ /* We make 3 passes, so that the postmaster can enforce a hierarchy of filters, * with some always executing before or after a mailbox's rules. */ RWLIST_RDLOCK(&processors); - EXECUTE_FILTERS(FILTER_BEFORE_MAILBOX); - if (scope == SMTP_SCOPE_INDIVIDUAL) { - EXECUTE_FILTERS(FILTER_MAILBOX); + res |= __run_callbacks(mproc, FILTER_BEFORE_MAILBOX, file, line, func); + if (!res && scope == SMTP_SCOPE_INDIVIDUAL) { + res |= __run_callbacks(mproc, FILTER_MAILBOX, file, line, func); + } + if (!res) { + res |= __run_callbacks(mproc, FILTER_AFTER_MAILBOX, file, line, func); } - EXECUTE_FILTERS(FILTER_AFTER_MAILBOX); -#undef EXECUTE_FILTERS -done: RWLIST_UNLOCK(&processors); + if (mproc->fp) { /* Although in most cases, we do the COMBINED pass and then the INDIVIDUAL pass, * in some cases we might just do the COMBINED pass and then abort, @@ -1698,12 +1727,14 @@ int smtp_run_callbacks(struct smtp_msg_process *mproc, enum smtp_filter_scope sc fclose(mproc->fp); mproc->fp = NULL; } + return res == -1 ? -1 : 0; /* If we aborted callbacks, 1 was returned, but we should return 0 since most callers just check for nonzero return */ } /* Note: In the case of SMTP_SCOPE_COMBINED, this is kind of a misnomer, since it's not being called from a delivery handler, but the wrapper is still useful */ -int smtp_run_delivery_callbacks(struct smtp_session *smtp, struct smtp_msg_process *mproc, struct mailbox *mbox, struct smtp_response **restrict resp_ptr, - enum smtp_direction dir, enum smtp_filter_scope scope, const char *recipient, size_t datalen, void **freedata) +int __smtp_run_delivery_callbacks(struct smtp_session *smtp, struct smtp_msg_process *mproc, struct mailbox *mbox, struct smtp_response **restrict resp_ptr, + enum smtp_direction dir, enum smtp_filter_scope scope, const char *recipient, size_t datalen, void **freedata, + const char *file, int line, const char *func) { unsigned int mailboxid; char recip_buf[256]; @@ -1763,7 +1794,7 @@ int smtp_run_delivery_callbacks(struct smtp_session *smtp, struct smtp_msg_proce mproc->newdir = strdup("Junk"); } - if (smtp_run_callbacks(mproc, scope)) { + if (__smtp_run_callbacks(mproc, scope, file, line, func)) { return -1; /* If returned nonzero, it's assumed it responded with an SMTP error code as appropriate. */ }