int flush_add(const char *site, const char *queue_id) { const char *myname = "flush_add"; int status; if (msg_verbose) msg_info("%s: site %s id %s", myname, site, queue_id); /* * Don't bother the server if the service is turned off, or if the site * is not eligible. */ if (flush_domains == 0) msg_panic("missing flush client initialization"); if (domain_list_match(flush_domains, site) != 0) status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_ADD, ATTR_TYPE_STR, MAIL_ATTR_SITE, site, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_END); else if (flush_domains->error == 0) status = FLUSH_STAT_DENY; else status = FLUSH_STAT_FAIL; if (msg_verbose) msg_info("%s: site %s id %s status %d", myname, site, queue_id, status); return (status); }
int bounce_flush_verp(int flags, const char *queue, const char *id, const char *encoding, const char *sender, const char *dsn_envid, int dsn_ret, const char *verp_delims) { /* * When we're pretending that we can't bounce, don't send a bounce * message. */ if (var_soft_bounce) return (-1); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_VERP, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, ATTR_TYPE_END) == 0) { return (0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { msg_info("%s: status=deferred (bounce failed)", id); return (-1); } else { return (-1); } }
int trace_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { VSTRING *why = vstring_alloc(100); DSN my_dsn = *dsn; int req_stat; /* * User-requested address verification, verbose delivery, or DSN SUCCESS * notification. */ if (strcmp(relay, NO_RELAY_AGENT) != 0) vstring_sprintf(why, "delivery via %s: ", relay); vstring_strcat(why, my_dsn.reason); my_dsn.reason = vstring_str(why); if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, ATTR_TYPE_END) != 0) { msg_warn("%s: %s service failure", id, var_trace_service); req_stat = -1; } else { if (flags & DEL_REQ_FLAG_USR_VRFY) log_adhoc(id, stats, rcpt, relay, dsn, my_dsn.action); req_stat = 0; } vstring_free(why); return (req_stat); }
int defer_warn(int flags, const char *queue, const char *id, const char *sender, const char *envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0) { return (0); } else { return (-1); } }
int trace_flush(int flags, const char *queue, const char *id, const char *encoding, const char *sender, const char *dsn_envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0) { return (0); } else { return (-1); } }
int flush_send_file(const char *queue_id) { const char *myname = "flush_send_file"; int status; if (msg_verbose) msg_info("%s: queue_id %s", myname, queue_id); /* * Require that the service is turned on. */ status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_END); if (msg_verbose) msg_info("%s: queue_id %s status %d", myname, queue_id, status); return (status); }
int flush_refresh(void) { const char *myname = "flush_refresh"; int status; if (msg_verbose) msg_info("%s", myname); /* * Don't bother the server if the service is turned off. */ if (*var_fflush_domains == 0) status = FLUSH_STAT_DENY; else status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service, ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_REFRESH, ATTR_TYPE_END); if (msg_verbose) msg_info("%s: status %d", myname, status); return (status); }
int defer_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { const char *rcpt_domain; DSN my_dsn = *dsn; int status; /* * Sanity check. */ if (my_dsn.status[0] != '4' || !dsn_valid(my_dsn.status)) { msg_warn("defer_append: ignoring dsn code \"%s\"", my_dsn.status); my_dsn.status = "4.0.0"; } /* * MTA-requested address verification information is stored in the verify * service database. */ if (flags & DEL_REQ_FLAG_MTA_VRFY) { my_dsn.action = "undeliverable"; status = verify_append(id, stats, rcpt, relay, &my_dsn, DEL_RCPT_STAT_DEFER); return (status); } /* * User-requested address verification information is logged and mailed * to the requesting user. */ if (flags & DEL_REQ_FLAG_USR_VRFY) { my_dsn.action = "undeliverable"; status = trace_append(flags, id, stats, rcpt, relay, &my_dsn); return (status); } /* * Normal mail delivery. May also send a delivery record to the user. * * XXX DSN We write all deferred recipients to the defer logfile regardless * of DSN NOTIFY options, because those options don't apply to mailq(1) * reports or to postmaster notifications. */ else { /* * Supply default action. */ my_dsn.action = "delayed"; if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, ATTR_TYPE_END) != 0) msg_warn("%s: %s service failure", id, var_defer_service); log_adhoc(id, stats, rcpt, relay, &my_dsn, "deferred"); /* * Traced delivery. */ if (flags & DEL_REQ_FLAG_RECORD) if (trace_append(flags, id, stats, rcpt, relay, &my_dsn) != 0) msg_warn("%s: %s service failure", id, var_trace_service); /* * Notify the fast flush service. XXX Should not this belong in the * bounce/defer daemon? Well, doing it here is more robust. */ if ((rcpt_domain = strrchr(rcpt->address, '@')) != 0 && *++rcpt_domain != 0) switch (flush_add(rcpt_domain, id)) { case FLUSH_STAT_OK: case FLUSH_STAT_DENY: break; default: msg_warn("%s: %s service failure", id, var_flush_service); break; } return (-1); } }
int bounce_one_intern(int flags, const char *queue, const char *id, const char *encoding, const char *sender, const char *dsn_envid, int dsn_ret, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { DSN my_dsn = *dsn; int status; /* * MTA-requested address verification information is stored in the verify * service database. */ if (flags & DEL_REQ_FLAG_MTA_VRFY) { my_dsn.action = "undeliverable"; status = verify_append(id, stats, rcpt, relay, &my_dsn, DEL_RCPT_STAT_BOUNCE); return (status); } /* * User-requested address verification information is logged and mailed * to the requesting user. */ if (flags & DEL_REQ_FLAG_USR_VRFY) { my_dsn.action = "undeliverable"; status = trace_append(flags, id, stats, rcpt, relay, &my_dsn); return (status); } /* * When we're not bouncing, then use the standard multi-recipient logfile * based procedure. */ else if (var_soft_bounce) { return (bounce_append_intern(flags, id, stats, rcpt, relay, &my_dsn)); } /* * Normal mail delivery. May also send a delivery record to the user. * * XXX DSN We send all recipients regardless of DSN NOTIFY options, because * those options don't apply to postmaster notifications. */ else { /* * Supply default action. */ my_dsn.action = "failed"; if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_ONE, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, ATTR_TYPE_END) == 0 && ((flags & DEL_REQ_FLAG_RECORD) == 0 || trace_append(flags, id, stats, rcpt, relay, &my_dsn) == 0)) { log_adhoc(id, stats, rcpt, relay, &my_dsn, "bounced"); status = 0; } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { VSTRING *junk = vstring_alloc(100); my_dsn.status = "4.3.0"; vstring_sprintf(junk, "%s or %s service failure", var_bounce_service, var_trace_service); my_dsn.reason = vstring_str(junk); status = defer_append_intern(flags, id, stats, rcpt, relay, &my_dsn); vstring_free(junk); } else { status = -1; } return (status); } }
int bounce_append_intern(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { DSN my_dsn = *dsn; int status; /* * MTA-requested address verification information is stored in the verify * service database. */ if (flags & DEL_REQ_FLAG_MTA_VRFY) { my_dsn.action = "undeliverable"; status = verify_append(id, stats, rcpt, relay, &my_dsn, DEL_RCPT_STAT_BOUNCE); return (status); } /* * User-requested address verification information is logged and mailed * to the requesting user. */ if (flags & DEL_REQ_FLAG_USR_VRFY) { my_dsn.action = "undeliverable"; status = trace_append(flags, id, stats, rcpt, relay, &my_dsn); return (status); } /* * Normal (well almost) delivery. When we're pretending that we can't * bounce, don't create a defer log file when we wouldn't keep the bounce * log file. That's a lot of negatives in one sentence. */ else if (var_soft_bounce && (flags & BOUNCE_FLAG_CLEAN)) { return (-1); } /* * Normal mail delivery. May also send a delivery record to the user. * * XXX DSN We write all recipients to the bounce logfile regardless of DSN * NOTIFY options, because those options don't apply to postmaster * notifications. */ else { char *my_status = mystrdup(my_dsn.status); const char *log_status = var_soft_bounce ? "SOFTBOUNCE" : "bounced"; /* * Supply default action. */ my_dsn.status = my_status; if (var_soft_bounce) { my_status[0] = '4'; my_dsn.action = "delayed"; } else { my_dsn.action = "failed"; } if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ? var_defer_service : var_bounce_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt, ATTR_TYPE_FUNC, dsn_print, (void *) &my_dsn, ATTR_TYPE_END) == 0 && ((flags & DEL_REQ_FLAG_RECORD) == 0 || trace_append(flags, id, stats, rcpt, relay, &my_dsn) == 0)) { log_adhoc(id, stats, rcpt, relay, &my_dsn, log_status); status = (var_soft_bounce ? -1 : 0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { VSTRING *junk = vstring_alloc(100); my_dsn.status = "4.3.0"; vstring_sprintf(junk, "%s or %s service failure", var_bounce_service, var_trace_service); my_dsn.reason = vstring_str(junk); status = defer_append_intern(flags, id, stats, rcpt, relay, &my_dsn); vstring_free(junk); } else { status = -1; } myfree(my_status); return (status); } }