static int bounce_one_proto(char *service_name, VSTREAM *client) { const char *myname = "bounce_one_proto"; int flags; int dsn_ret; /* * Read and validate the client request. */ if (mail_command_server(client, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_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, rcpb_scan, (void *) rcpt_buf, ATTR_TYPE_FUNC, dsb_scan, (void *) dsn_buf, ATTR_TYPE_END) != 9) { msg_warn("malformed request"); return (-1); } /* * Sanitize input. */ if (strcmp(service_name, MAIL_SERVICE_BOUNCE) != 0) { msg_warn("wrong service name \"%s\" for one-recipient bouncing", service_name); return (-1); } if (mail_queue_name_ok(STR(queue_name)) == 0) { msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); return (-1); } if (mail_queue_id_ok(STR(queue_id)) == 0) { msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } printable(STR(dsn_envid), '?'); VS_NEUTER(rcpt_buf->address); VS_NEUTER(rcpt_buf->orig_addr); VS_NEUTER(rcpt_buf->dsn_orcpt); VS_NEUTER(dsn_buf->status); VS_NEUTER(dsn_buf->action); VS_NEUTER(dsn_buf->reason); VS_NEUTER(dsn_buf->dtype); VS_NEUTER(dsn_buf->dtext); VS_NEUTER(dsn_buf->mtype); VS_NEUTER(dsn_buf->mname); (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf); (void) DSN_FROM_DSN_BUF(dsn_buf); /* * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and * RECIPIENT_FROM_RCPT_BUF(). */ if (msg_verbose) msg_info("%s: flags=0x%x queue=%s id=%s encoding=%s sender=%s envid=%s dsn_ret=0x%x orig_to=%s to=%s off=%ld dsn_orig=%s notif=0x%x stat=%s act=%s why=%s", myname, flags, STR(queue_name), STR(queue_id), STR(encoding), STR(sender), STR(dsn_envid), dsn_ret, STR(rcpt_buf->orig_addr), STR(rcpt_buf->address), rcpt_buf->offset, STR(rcpt_buf->dsn_orcpt), rcpt_buf->dsn_notify, STR(dsn_buf->status), STR(dsn_buf->action), STR(dsn_buf->reason)); /* * Execute the request. */ return (bounce_one_service(flags, STR(queue_name), STR(queue_id), STR(encoding), STR(sender), STR(dsn_envid), dsn_ret, rcpt_buf, dsn_buf, bounce_templates)); }
static int bounce_verp_proto(char *service_name, VSTREAM *client) { const char *myname = "bounce_verp_proto"; int flags; int smtputf8; int dsn_ret; /* * Read and validate the client request. */ if (mail_command_server(client, RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), RECV_ATTR_STR(MAIL_ATTR_ENCODING, encoding), RECV_ATTR_INT(MAIL_ATTR_SMTPUTF8, &smtputf8), RECV_ATTR_STR(MAIL_ATTR_SENDER, sender), RECV_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), RECV_ATTR_INT(MAIL_ATTR_DSN_RET, &dsn_ret), RECV_ATTR_STR(MAIL_ATTR_VERPDL, verp_delims), ATTR_TYPE_END) != 9) { msg_warn("malformed request"); return (-1); } /* * Sanitize input. */ if (mail_queue_name_ok(STR(queue_name)) == 0) { msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); return (-1); } if (mail_queue_id_ok(STR(queue_id)) == 0) { msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } VS_NEUTER(encoding); VS_NEUTER(sender); VS_NEUTER(dsn_envid); VS_NEUTER(verp_delims); if (strlen(STR(verp_delims)) != 2) { msg_warn("malformed verp delimiter string: %s", STR(verp_delims)); return (-1); } if (msg_verbose) msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x delim=%s", myname, flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, STR(verp_delims)); /* * On request by the client, set up a trap to delete the log file in case * of errors. */ if (flags & BOUNCE_FLAG_CLEAN) bounce_cleanup_register(service_name, STR(queue_id)); /* * Execute the request. Fall back to traditional notification if a bounce * was returned as undeliverable, because we don't want to VERPify those. */ if (!*STR(sender) || !strcasecmp_utf8(STR(sender), mail_addr_double_bounce())) { msg_warn("request to send VERP-style notification of bounced mail"); return (bounce_notify_service(flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, bounce_templates)); } else return (bounce_notify_verp(flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, STR(verp_delims), bounce_templates)); }
static int bounce_append_proto(char *service_name, VSTREAM *client) { const char *myname = "bounce_append_proto"; int flags; /* * Read and validate the client request. */ if (mail_command_server(client, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf, ATTR_TYPE_FUNC, dsb_scan, (void *) dsn_buf, ATTR_TYPE_END) != 4) { msg_warn("malformed request"); return (-1); } /* * Sanitize input. */ if (mail_queue_id_ok(STR(queue_id)) == 0) { msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } VS_NEUTER(rcpt_buf->address); VS_NEUTER(rcpt_buf->orig_addr); VS_NEUTER(rcpt_buf->dsn_orcpt); VS_NEUTER(dsn_buf->status); VS_NEUTER(dsn_buf->action); VS_NEUTER(dsn_buf->reason); VS_NEUTER(dsn_buf->dtype); VS_NEUTER(dsn_buf->dtext); VS_NEUTER(dsn_buf->mtype); VS_NEUTER(dsn_buf->mname); (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf); (void) DSN_FROM_DSN_BUF(dsn_buf); /* * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and * RECIPIENT_FROM_RCPT_BUF(). */ if (msg_verbose) msg_info("%s: flags=0x%x service=%s id=%s org_to=%s to=%s off=%ld dsn_org=%s, notif=0x%x stat=%s act=%s why=%s", myname, flags, service_name, STR(queue_id), STR(rcpt_buf->orig_addr), STR(rcpt_buf->address), rcpt_buf->offset, STR(rcpt_buf->dsn_orcpt), rcpt_buf->dsn_notify, STR(dsn_buf->status), STR(dsn_buf->action), STR(dsn_buf->reason)); /* * On request by the client, set up a trap to delete the log file in case * of errors. */ if (flags & BOUNCE_FLAG_CLEAN) bounce_cleanup_register(service_name, STR(queue_id)); /* * Execute the request. */ return (bounce_append_service(flags, service_name, STR(queue_id), &rcpt_buf->rcpt, &dsn_buf->dsn)); }
static int bounce_notify_proto(char *service_name, VSTREAM *client, int (*service) (int, char *, char *, char *, char *, int, char *, char *, int, BOUNCE_TEMPLATES *)) { const char *myname = "bounce_notify_proto"; int flags; int smtputf8; int dsn_ret; /* * Read and validate the client request. */ if (mail_command_server(client, RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name), RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), RECV_ATTR_STR(MAIL_ATTR_ENCODING, encoding), RECV_ATTR_INT(MAIL_ATTR_SMTPUTF8, &smtputf8), RECV_ATTR_STR(MAIL_ATTR_SENDER, sender), RECV_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), RECV_ATTR_INT(MAIL_ATTR_DSN_RET, &dsn_ret), ATTR_TYPE_END) != 8) { msg_warn("malformed request"); return (-1); } /* * Sanitize input. */ if (mail_queue_name_ok(STR(queue_name)) == 0) { msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); return (-1); } if (mail_queue_id_ok(STR(queue_id)) == 0) { msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); return (-1); } VS_NEUTER(encoding); VS_NEUTER(sender); VS_NEUTER(dsn_envid); if (msg_verbose) msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x", myname, flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret); /* * On request by the client, set up a trap to delete the log file in case * of errors. */ if (flags & BOUNCE_FLAG_CLEAN) bounce_cleanup_register(service_name, STR(queue_id)); /* * Execute the request. */ return (service(flags, service_name, STR(queue_name), STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, bounce_templates)); }