# HG changeset patch # User markus schnalke # Date 1291669621 10800 # Node ID 72e377210d5ee7ddb86edd524c960d87094da6db # Parent 1aa107c6b1e527d9183bc8423b67ea1963dd6335 heavy refactoring of deliver.c I need to have closer looks in there; seems as if there are possibilies to clean up diff -r 1aa107c6b1e5 -r 72e377210d5e src/deliver.c --- a/src/deliver.c Mon Dec 06 17:46:24 2010 -0300 +++ b/src/deliver.c Mon Dec 06 18:07:01 2010 -0300 @@ -42,17 +42,19 @@ if (addr_is_defered(rcpt)) { if ((now - msg->received_time) >= conf.max_defer_time) { addr_mark_failed(rcpt); - } else + } else { defered_list = g_list_prepend(defered_list, rcpt); + } } - if (addr_is_failed(rcpt)) + if (addr_is_failed(rcpt)) { failed_list = g_list_prepend(failed_list, rcpt); + } } - if (failed_list != NULL) { + if (failed_list) { ok_fail = fail_msg(msg, conf.errmsg_file, failed_list, err_fmt, args); g_list_free(failed_list); } - if (defered_list != NULL) { + if (defered_list) { ok_warn = warn_msg(msg, conf.warnmsg_file, defered_list, err_fmt, args); g_list_free(defered_list); } @@ -67,25 +69,103 @@ } gboolean +deliver_local_mbox(message* msg, GList* hdr_list, address* rcpt, address* env_addr) +{ + DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); + if (append_file(msg, hdr_list, rcpt->local_part)) { + if (env_addr != rcpt) { + logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n", msg->uid, rcpt->local_part, rcpt->domain, env_addr->local_part, env_addr->domain); + } else { + logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", msg->uid, rcpt->local_part, rcpt->domain); + } + addr_mark_delivered(rcpt); + return TRUE; + } + + /* prevents 'Resource temporarily unavailable (11)' */ + if (errno != EAGAIN) { + addr_mark_failed(rcpt); + } else { + addr_mark_defered(rcpt); + } + return FALSE; +} + +gboolean +deliver_local_pipe(message* msg, GList* hdr_list, address* rcpt, address* env_addr) +{ + guint flags; + + DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); + + flags = (conf.pipe_fromline) ? MSGSTR_FROMLINE : 0; + flags |= (conf.pipe_fromhack) ? MSGSTR_FROMHACK : 0; + if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), flags)) { + logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", + msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); + addr_mark_delivered(rcpt); + return TRUE; + } + + if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { + addr_mark_failed(rcpt); + } else { + addr_mark_defered(rcpt); + /* has no effect yet, except that mail remains in spool */ + } + return FALSE; +} + +gboolean +deliver_local_mda(message* msg, GList* hdr_list, address* rcpt, address* env_addr) +{ + gboolean ok = FALSE; + gchar *cmd = g_malloc(256); + GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); + guint flags; + + DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); + + if (!expand(var_table, conf.mda, cmd, 256)) { + logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda); + destroy_table(var_table); + return FALSE; + } + + flags = (conf.mda_fromline) ? MSGSTR_FROMLINE : 0; + flags |= (conf.mda_fromhack) ? MSGSTR_FROMHACK : 0; + if (pipe_out(msg, hdr_list, rcpt, cmd, flags)) { + logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", + msg->uid, rcpt->local_part, rcpt->domain, cmd); + addr_mark_delivered(rcpt); + ok = TRUE; + } else if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { + addr_mark_failed(rcpt); + } else { + addr_mark_defered(rcpt); + /* has no effect yet, except that mail remains in spool */ + } + + destroy_table(var_table); + return ok; +} + +gboolean deliver_local(msg_out * msgout) { message *msg = msgout->msg; GList *rcpt_list = msgout->rcpt_list; GList *rcpt_node; - gboolean ok = TRUE, flag = FALSE, ok_fail = FALSE; + gboolean ok = FALSE, flag = FALSE, ok_fail = FALSE; DEBUG(5) debugf("deliver_local entered\n"); flag = (msg->data_list == NULL); - if (flag) { - if (!(ok = spool_read_data(msg))) { - logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); - } + if (flag && !spool_read_data(msg)) { + logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); + return FALSE; } - if (!ok) - return FALSE; - ok = FALSE; for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { GList *hdr_list; address *rcpt = (address *) (rcpt_node->data); @@ -93,8 +173,9 @@ address *ret_path = msg->return_path; header *retpath_hdr, *envto_hdr; - /* we need a private copy of the hdr list because we add headers here that belong to the rcpt only. - g_list_copy copies only the nodes, so it is safe to g_list_free it */ + /* we need a private copy of the hdr list because we add headers + here that belong to the rcpt only. g_list_copy copies only + the nodes, so it is safe to g_list_free it */ hdr_list = g_list_copy(msg->hdr_list); retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr)); envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path)); @@ -103,82 +184,38 @@ hdr_list = g_list_prepend(hdr_list, retpath_hdr); if (rcpt->local_part[0] == '|') { - DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); - if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), - (conf.pipe_fromline ? MSGSTR_FROMLINE : 0) - | (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))) { - logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", - msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); - addr_mark_delivered(rcpt); + /* probably for expanded aliases, but why not done + like with the mda? //meillo 2010-12-06 */ + if (deliver_local_pipe(msg, hdr_list, rcpt, env_addr)) { ok = TRUE; - } else { - if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { - addr_mark_failed(rcpt); - } else { - addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */ - } } } else { /* figure out which mailbox type should be used for this user */ gchar *user = rcpt->local_part; gchar *mbox_type = conf.mbox_default; - if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp) != NULL) + if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp)) { mbox_type = "mbox"; - else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp) != NULL) + } else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp)) { mbox_type = "mda"; + } if (strcmp(mbox_type, "mbox") == 0) { - DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); - if (append_file(msg, hdr_list, rcpt->local_part)) { - if (env_addr != rcpt) { - logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n", - msg->uid, rcpt->local_part, rcpt->domain, - env_addr->local_part, env_addr->domain); - } else { - logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", - msg->uid, rcpt->local_part, rcpt->domain); + if (deliver_local_mbox(msg, hdr_list, rcpt, env_addr)) { + ok = TRUE; + } + } else if (strcmp(mbox_type, "mda") == 0) { + if (conf.mda) { + if (deliver_local_mda(msg, hdr_list, rcpt, env_addr)) { + ok = TRUE; } - addr_mark_delivered(rcpt); - ok = TRUE; } else { - if (errno != EAGAIN) { /* prevents 'Resource temporarily unavailable (11)' */ - addr_mark_failed(rcpt); - } else { - addr_mark_defered(rcpt); - } + logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n"); } - } else if (strcmp(mbox_type, "mda") == 0) { - if (conf.mda) { - gchar *cmd = g_malloc(256); - GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); - - DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); - - if (expand(var_table, conf.mda, cmd, 256)) { - - if (pipe_out(msg, hdr_list, rcpt, cmd, (conf.mda_fromline ? MSGSTR_FROMLINE : 0) - | (conf.mda_fromhack ? MSGSTR_FROMHACK : 0))) { - logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", - msg->uid, rcpt->local_part, rcpt->domain, cmd); - addr_mark_delivered(rcpt); - ok = TRUE; - } else { - if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { - addr_mark_failed(rcpt); - } else { - addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */ - } - } - } else - logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda); - - destroy_table(var_table); - } else - logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n"); - } else + } else { logwrite(LOG_ALERT, "unknown mbox type '%s'\n", mbox_type); + } } destroy_header(retpath_hdr); @@ -188,10 +225,12 @@ } ok_fail = delivery_failures(msg, rcpt_list, "%s (%d)", ext_strerror(errno), errno); - if (flag) + if (flag) { msg_free_data(msg); - if (ok || ok_fail) + } + if (ok || ok_fail) { deliver_finish(msgout); + } return ok; } @@ -236,20 +275,17 @@ foreach(msgout_list, msgout_node) { msg_out *msgout = (msg_out *) (msgout_node->data); - gboolean flag, ok_msg = TRUE, ok_fail = FALSE; + gboolean flag, ok_fail = FALSE; message *msg = msgout->msg; GList *rcpt_node, *rcpt_list = msgout->rcpt_list; DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); flag = (msg->data_list == NULL); - if (flag) { - if (!(ok_msg = spool_read_data(msg))) { - logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); - } + if (flag && !spool_read_data(msg)) { + logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); + continue; } - if (!ok_msg) - continue; ok = FALSE; foreach(rcpt_list, rcpt_node) { @@ -259,7 +295,9 @@ DEBUG(1) debugf("attempting to deliver %s to %s@%s with pipe\n", msg->uid, rcpt->local_part, rcpt->domain); - if (expand(var_table, route->pipe, cmd, 256)) { + if (!expand(var_table, route->pipe, cmd, 256)) { + logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); + } else { if (pipe_out(msg, msg->hdr_list, rcpt, cmd, (route->pipe_fromline ? MSGSTR_FROMLINE : 0) | (route->pipe_fromhack ? MSGSTR_FROMHACK : 0))) { @@ -276,24 +314,25 @@ addr_mark_defered(rcpt); } } - } else - logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); + } destroy_table(var_table); } ok_fail = delivery_failures(msg, rcpt_list, "%s", strerror(errno)); - if (flag) + if (flag) { msg_free_data(msg); - - if (ok || ok_fail) + } + if (ok || ok_fail) { deliver_finish(msgout); + } } return ok; } -/* deliver list of messages to one host and finishes them if the message was delivered to at least one rcpt. +/* deliver list of messages to one host and finishes them if the message was + delivered to at least one rcpt. Returns TRUE if at least one msg was delivered to at least one rcpt. */ gboolean @@ -305,102 +344,34 @@ gint port = 25; /* paranoid check: */ - if (msgout_list == NULL) { + if (!msgout_list) { logwrite(LOG_ALERT, "Ooops: empty list of messages in deliver_msglist_host()\n"); return FALSE; } - if (host == NULL) { + if (!host) { /* XXX: what if mail_host isn't set? Is this possible? */ host = route->mail_host->address; port = route->mail_host->port; } - if ((psb = (route->wrapper ? smtp_out_open_child(route->wrapper) : smtp_out_open(host, port, res_list)))) { + if (route->wrapper) { + psb = smtp_out_open_child(route->wrapper); + } else { + psb = smtp_out_open(host, port, res_list); + } - if (route->wrapper) { - /* it seems as if the remote_host is only set for logging - /* XXX: this could probably be moved into smtp_out_open_child() */ - psb->remote_host = host; - } - - set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo); - -#ifdef ENABLE_AUTH - if ((route->auth_name) && (route->auth_login) && (route->auth_secret)) - set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); -#endif - if (smtp_out_init(psb, route->instant_helo)) { - - if (!route->do_pipelining) - psb->use_pipelining = FALSE; - - foreach(msgout_list, msgout_node) { - msg_out *msgout = (msg_out *) (msgout_node->data); - gboolean flag, ok_msg = FALSE, ok_fail = FALSE; - message *msg = msgout->msg; - - /* we may have to read the data at this point and remember if we did */ - flag = (msg->data_list == NULL); - if (flag) { - if (!spool_read_data(msg)) { - logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); - break; - } - } - - smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); - - ok_fail = delivery_failures(msg, msgout->rcpt_list, - "while connected with %s, the server replied\n\t%s", host, psb->buffer); - - if ((psb->error == smtp_eof) - || (psb->error == smtp_timeout)) { - /* connection lost */ - break; - } else if (psb->error != smtp_ok) { - if (g_list_next(msgout_node) != NULL) - if (!smtp_out_rset(psb)) - break; - } - ok_msg = (psb->error == smtp_ok); - - if (flag) - msg_free_data(msg); - if (ok_msg) - ok = TRUE; - if (ok_msg || ok_fail) { - deliver_finish(msgout); - } - } - if (psb->error == smtp_ok || (psb->error == smtp_fail) - || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { - smtp_out_quit(psb); - } - } else { - /* smtp_out_init() failed */ - if ((psb->error == smtp_fail) || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { - smtp_out_quit(psb); - - foreach(msgout_list, msgout_node) { - msg_out *msgout = (msg_out *) (msgout_node->data); - smtp_out_mark_rcpts(psb, msgout->rcpt_list); - - if (delivery_failures(msgout->msg, msgout->rcpt_list, - "while connected with %s, the server replied\n\t%s", host, psb->buffer)) - deliver_finish(msgout); - } - } - } - destroy_smtpbase(psb); - } else { + if (!psb) { /* smtp_out_open() failed */ foreach(msgout_list, msgout_node) { msg_out *msgout = (msg_out *) (msgout_node->data); GList *rcpt_node; - for (rcpt_node = g_list_first(msgout->rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { + for (rcpt_node = g_list_first(msgout->rcpt_list); + rcpt_node; + rcpt_node = g_list_next(rcpt_node)) { address *rcpt = (address *) (rcpt_node->data); + gboolean ret = FALSE; addr_unmark_delivered(rcpt); if (route->connect_error_fail) { @@ -408,15 +379,96 @@ } else { addr_mark_defered(rcpt); } - if (route->wrapper - ? delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", - strerror(errno)) - : delivery_failures(msgout->msg, msgout->rcpt_list, "could not open connection to %s:%d :\n\t%s", - host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno))) + if (route->wrapper) { + ret = delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", strerror(errno)); + } else { + ret = delivery_failures(msgout->msg, msgout->rcpt_list, "could not open connection to %s:%d :\n\t%s", host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno)); + } + if (ret) { deliver_finish(msgout); + } } } + return ok; } + + + if (route->wrapper) { + /* it seems as if the remote_host is only set for logging + /* XXX: this could probably be moved into smtp_out_open_child() */ + psb->remote_host = host; + } + + set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo); + +#ifdef ENABLE_AUTH + if ((route->auth_name) && (route->auth_login) && (route->auth_secret)) { + set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); + } +#endif + if (!smtp_out_init(psb, route->instant_helo)) { + /* smtp_out_init() failed */ + if ((psb->error==smtp_fail) || (psb->error==smtp_trylater) || (psb->error==smtp_syntax)) { + smtp_out_quit(psb); + + foreach(msgout_list, msgout_node) { + msg_out *msgout = (msg_out *) (msgout_node->data); + smtp_out_mark_rcpts(psb, msgout->rcpt_list); + + if (delivery_failures(msgout->msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer)) { + deliver_finish(msgout); + } + } + } + destroy_smtpbase(psb); + return ok; + } + + if (!route->do_pipelining) { + psb->use_pipelining = FALSE; + } + + foreach(msgout_list, msgout_node) { + msg_out *msgout = (msg_out *) (msgout_node->data); + gboolean flag, ok_msg = FALSE, ok_fail = FALSE; + message *msg = msgout->msg; + + /* we may have to read the data at this point and remember if we did */ + flag = (msg->data_list == NULL); + if (flag && !spool_read_data(msg)) { + logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); + break; + } + + smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); + + ok_fail = delivery_failures(msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer); + + if ((psb->error == smtp_eof) || (psb->error == smtp_timeout)) { + /* connection lost */ + break; + } else if (psb->error != smtp_ok) { + if (g_list_next(msgout_node) && !smtp_out_rset(psb)) { + break; + } + } + ok_msg = (psb->error == smtp_ok); + + if (flag) { + msg_free_data(msg); + } + if (ok_msg) { + ok = TRUE; + } + if (ok_msg || ok_fail) { + deliver_finish(msgout); + } + } + if (psb->error == smtp_ok || (psb->error == smtp_fail) + || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { + smtp_out_quit(psb); + } + destroy_smtpbase(psb); return ok; } @@ -439,37 +491,37 @@ deliver_route_msgout_list(connect_route * route, GList * msgout_list) { gboolean ok = FALSE; + GList *mo_ph_list; + GList *mo_ph_node; DEBUG(5) debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name); if (route->mail_host) { /* this is easy... deliver everything to a smart host for relay */ - if (deliver_msglist_host(route, msgout_list, NULL, route->resolve_list)) + return deliver_msglist_host(route, msgout_list, NULL, route->resolve_list); + } + + /* this is not easy... */ + + mo_ph_list = route_msgout_list(route, msgout_list); + /* okay, now we have ordered our messages by the hosts. */ + if (!mo_ph_list) { + return FALSE; + } + + /* TODO: It would be nice to be able to fork for each host. + We cannot do that yet because of complications with finishing the + messages. Threads could be a solution because they use the same + memory. But we are not thread safe yet... + */ + foreach(mo_ph_list, mo_ph_node) { + msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data); + if (deliver_msglist_host(route, mo_ph->msgout_list, mo_ph->host, route->resolve_list)) { ok = TRUE; - - } else { - /* this is not easy... */ - GList *mo_ph_list; - - mo_ph_list = route_msgout_list(route, msgout_list); - /* okay, now we have ordered our messages by the hosts. */ - if (mo_ph_list != NULL) { - GList *mo_ph_node; - /* TODO: It would be nice to be able to fork for each host. - We cannot do that yet because of complications with finishing the - messages. Threads could be a solution because they use the same - memory. But we are not thread safe yet... - */ - foreach(mo_ph_list, mo_ph_node) { - msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data); - if (deliver_msglist_host (route, mo_ph->msgout_list, mo_ph->host, route->resolve_list)) - ok = TRUE; - - destroy_msgout_perhost(mo_ph); - } - g_list_free(mo_ph_list); } + destroy_msgout_perhost(mo_ph); } + g_list_free(mo_ph_list); return ok; } @@ -492,50 +544,59 @@ GList *rcpt_list_non_delivered = NULL; GList *rcpt_node; - /* we have to delete already delivered rcpt's because a previous route may have delivered to it */ + /* we have to delete already delivered rcpt's because a + previous route may have delivered to it */ foreach(msgout_cloned->rcpt_list, rcpt_node) { address *rcpt = (address *) (rcpt_node->data); - /* failed addresses already have been bounced - there should be a better way to handle those. */ + /* failed addresses already have been bounced; + there should be a better way to handle those. */ if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) - && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) + && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) { rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); + } } g_list_free(msgout_cloned->rcpt_list); msgout_cloned->rcpt_list = rcpt_list_non_delivered; - if (msgout_cloned->rcpt_list) { - if (route_is_allowed_mail_local(route, msgout->msg->return_path) - && route_is_allowed_return_path(route, msgout->msg-> return_path)) { - GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; - msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); + if (!msgout_cloned->rcpt_list) { + destroy_msg_out(msgout_cloned); + continue; + } - if (rcpt_list_allowed != NULL) { - logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); + if (!route_is_allowed_mail_local(route, msgout->msg->return_path) + || !route_is_allowed_return_path(route, msgout->msg-> return_path)) { + destroy_msg_out(msgout_cloned); + continue; + } - g_list_free(msgout_cloned->rcpt_list); - msgout_cloned->rcpt_list = rcpt_list_allowed; + GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; + msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); - if (route->last_route) { - GList *rcpt_node; - foreach(msgout_cloned->rcpt_list, rcpt_node) { - address *rcpt = (address *) (rcpt_node->data); - rcpt->flags |= ADDR_FLAG_LAST_ROUTE; - } - } + if (!rcpt_list_allowed) { + destroy_msg_out(msgout_cloned); + continue; + } + logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); - route_prepare_msgout(route, msgout_cloned); - msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); - } else - destroy_msg_out(msgout_cloned); - } else - destroy_msg_out(msgout_cloned); - } else - destroy_msg_out(msgout_cloned); + g_list_free(msgout_cloned->rcpt_list); + msgout_cloned->rcpt_list = rcpt_list_allowed; + + if (route->last_route) { + GList *rcpt_node; + foreach(msgout_cloned->rcpt_list, rcpt_node) { + address *rcpt = (address *) (rcpt_node->data); + rcpt->flags |= ADDR_FLAG_LAST_ROUTE; + } + } + + route_prepare_msgout(route, msgout_cloned); + msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); } - if (msgout_list_deliver != NULL) { - if (deliver_route_msgout_list(route, msgout_list_deliver)) + if (msgout_list_deliver) { + if (deliver_route_msgout_list(route, msgout_list_deliver)) { ok = TRUE; + } destroy_msg_out_list(msgout_list_deliver); } return ok; @@ -552,15 +613,16 @@ foreach(msgout->rcpt_list, rcpt_node) { address *rcpt = (address *) (rcpt_node->data); - if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) + if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) { msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); + } } } -/* after delivery attempts, we check if there are any rcpt addresses left in the message. - If all addresses have been completed, the spool files will be deleted, - otherwise the header spool will be written back. - We never changed the data spool, so there is no need to write that back. +/* after delivery attempts, we check if there are any rcpt addresses left in + the message. If all addresses have been completed, the spool files will be + deleted, otherwise the header spool will be written back. We never changed + the data spool, so there is no need to write that back. returns TRUE if all went well. */ @@ -568,7 +630,6 @@ deliver_finish(msg_out * msgout) { GList *rcpt_node; - gboolean ok = FALSE; message *msg = msgout->msg; gboolean finished = TRUE; @@ -578,11 +639,13 @@ were always set on the original address structs */ foreach(msg->rcpt_list, rcpt_node) { address *rcpt = (address *) (rcpt_node->data); - if (!addr_is_finished_children(rcpt)) + if (!addr_is_finished_children(rcpt)) { finished = FALSE; - else { - /* if ALL children have been delivered, mark parent as delivered. - if there is one or more not delivered, it must have failed, we mark the parent as failed as well. + } else { + /* if ALL children have been delivered, mark parent as + delivered. if there is one or more not delivered, + it must have failed, we mark the parent as failed + as well. */ if (addr_is_delivered_children(rcpt)) { addr_mark_delivered(rcpt); @@ -592,19 +655,22 @@ } } - if (!finished) { - /* one not delivered address was found */ - if (spool_write(msg, FALSE)) { - ok = TRUE; - DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); - } else - logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid); - } else { - ok = spool_delete_all(msg); - if (ok) + if (finished) { + if (spool_delete_all(msg)) { logwrite(LOG_NOTICE, "%s completed.\n", msg->uid); + return TRUE; + } + return FALSE; } - return ok; + + /* one not delivered address was found */ + if (!spool_write(msg, FALSE)) { + logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid); + return FALSE; + } + + DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); + return TRUE; } gboolean @@ -614,8 +680,9 @@ GList *msgout_node; foreach(msgout_list, msgout_node) { msg_out *msgout = (msg_out *) (msgout_node->data); - if (!deliver_finish(msgout)) + if (!deliver_finish(msgout)) { ok = FALSE; + } } return ok; } @@ -624,28 +691,36 @@ deliver_msgout_list_online(GList * msgout_list) { GList *rf_list = NULL; - gchar *connect_name = detect_online(); + gchar *connect_name = NULL; gboolean ok = FALSE; - if (connect_name != NULL) { - logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); - /* we are online! */ - rf_list = (GList *) table_find(conf.connect_routes, connect_name); - if (rf_list != NULL) { - GList *route_list = read_route_list(rf_list, FALSE); - if (route_list) { - GList *route_node; - foreach(route_list, route_node) { - connect_route *route = (connect_route *) (route_node->data); - ok = deliver_route_msg_list(route, msgout_list); - } - destroy_route_list(route_list); - } else - logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name); - } else { - logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); - } + connect_name = detect_online(); + if (!connect_name) { + return FALSE; } + + /* we are online! */ + logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); + + rf_list = (GList *) table_find(conf.connect_routes, connect_name); + if (!rf_list) { + logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); + return FALSE; + } + + GList *route_list = read_route_list(rf_list, FALSE); + if (!route_list) { + logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name); + return FALSE; + } + + GList *route_node; + foreach(route_list, route_node) { + connect_route *route = (connect_route *) (route_node->data); + /* TODO: ok gets overwritten */ + ok = deliver_route_msg_list(route, msgout_list); + } + destroy_route_list(route_list); return ok; } @@ -653,7 +728,9 @@ deliver_msg_list(GList * msg_list, guint flags) { GList *msgout_list = create_msg_out_list(msg_list); - GList *local_msgout_list = NULL, *localnet_msgout_list = NULL, *other_msgout_list = NULL; + GList *local_msgout_list = NULL; + GList *localnet_msgout_list = NULL; + GList *other_msgout_list = NULL; GList *msgout_node; GList *alias_table = NULL; gboolean ok = TRUE; @@ -679,8 +756,11 @@ rcpt_list = g_list_copy(msgout->msg->rcpt_list); if (conf.log_user) { address *addr = create_address_qualified(conf.log_user, TRUE, conf.host_name); - if (addr) + if (addr) { rcpt_list = g_list_prepend(rcpt_list, addr); + } else { + logwrite(LOG_ALERT, "invalid log_user address `%s', ignoring\n", conf.log_user); + } } if (alias_table) { GList *aliased_rcpt_list; @@ -714,8 +794,9 @@ } } - if (alias_table) + if (alias_table) { destroy_table(alias_table); + } /* actual delivery */ @@ -723,8 +804,9 @@ DEBUG(5) debugf("local_msgout_list\n"); foreach(local_msgout_list, msgout_node) { msg_out *msgout = (msg_out *) (msgout_node->data); - if (!deliver_local(msgout)) + if (!deliver_local(msgout)) { ok = FALSE; + } } destroy_msg_out_list(local_msgout_list); } @@ -734,15 +816,17 @@ GList *route_node; DEBUG(5) debugf("localnet_msgout_list\n"); - if (conf.local_net_routes) + if (conf.local_net_routes) { route_list = read_route_list(conf.local_net_routes, TRUE); - else + } else { route_list = g_list_append(NULL, create_local_route()); + } foreach(route_list, route_node) { connect_route *route = (connect_route *) (route_node->data); - if (!deliver_route_msg_list(route, localnet_msgout_list)) + if (!deliver_route_msg_list(route, localnet_msgout_list)) { ok = FALSE; + } } destroy_msg_out_list(localnet_msgout_list); destroy_route_list(route_list); @@ -750,8 +834,9 @@ if (other_msgout_list) { DEBUG(5) debugf("other_msgout_list\n"); - if (!deliver_msgout_list_online(other_msgout_list)) + if (!deliver_msgout_list_online(other_msgout_list)) { ok = FALSE; + } destroy_msg_out_list(other_msgout_list); }