masqmail
changeset 280:72e377210d5e
heavy refactoring of deliver.c
I need to have closer looks in there; seems as if there are possibilies
to clean up
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Mon, 06 Dec 2010 18:07:01 -0300 |
parents | 1aa107c6b1e5 |
children | ea5f86e0a81c |
files | src/deliver.c |
diffstat | 1 files changed, 361 insertions(+), 276 deletions(-) [+] |
line diff
1.1 --- a/src/deliver.c Mon Dec 06 17:46:24 2010 -0300 1.2 +++ b/src/deliver.c Mon Dec 06 18:07:01 2010 -0300 1.3 @@ -42,17 +42,19 @@ 1.4 if (addr_is_defered(rcpt)) { 1.5 if ((now - msg->received_time) >= conf.max_defer_time) { 1.6 addr_mark_failed(rcpt); 1.7 - } else 1.8 + } else { 1.9 defered_list = g_list_prepend(defered_list, rcpt); 1.10 + } 1.11 } 1.12 - if (addr_is_failed(rcpt)) 1.13 + if (addr_is_failed(rcpt)) { 1.14 failed_list = g_list_prepend(failed_list, rcpt); 1.15 + } 1.16 } 1.17 - if (failed_list != NULL) { 1.18 + if (failed_list) { 1.19 ok_fail = fail_msg(msg, conf.errmsg_file, failed_list, err_fmt, args); 1.20 g_list_free(failed_list); 1.21 } 1.22 - if (defered_list != NULL) { 1.23 + if (defered_list) { 1.24 ok_warn = warn_msg(msg, conf.warnmsg_file, defered_list, err_fmt, args); 1.25 g_list_free(defered_list); 1.26 } 1.27 @@ -67,25 +69,103 @@ 1.28 } 1.29 1.30 gboolean 1.31 +deliver_local_mbox(message* msg, GList* hdr_list, address* rcpt, address* env_addr) 1.32 +{ 1.33 + DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); 1.34 + if (append_file(msg, hdr_list, rcpt->local_part)) { 1.35 + if (env_addr != rcpt) { 1.36 + 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); 1.37 + } else { 1.38 + logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", msg->uid, rcpt->local_part, rcpt->domain); 1.39 + } 1.40 + addr_mark_delivered(rcpt); 1.41 + return TRUE; 1.42 + } 1.43 + 1.44 + /* prevents 'Resource temporarily unavailable (11)' */ 1.45 + if (errno != EAGAIN) { 1.46 + addr_mark_failed(rcpt); 1.47 + } else { 1.48 + addr_mark_defered(rcpt); 1.49 + } 1.50 + return FALSE; 1.51 +} 1.52 + 1.53 +gboolean 1.54 +deliver_local_pipe(message* msg, GList* hdr_list, address* rcpt, address* env_addr) 1.55 +{ 1.56 + guint flags; 1.57 + 1.58 + DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); 1.59 + 1.60 + flags = (conf.pipe_fromline) ? MSGSTR_FROMLINE : 0; 1.61 + flags |= (conf.pipe_fromhack) ? MSGSTR_FROMHACK : 0; 1.62 + if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), flags)) { 1.63 + logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", 1.64 + msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); 1.65 + addr_mark_delivered(rcpt); 1.66 + return TRUE; 1.67 + } 1.68 + 1.69 + if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { 1.70 + addr_mark_failed(rcpt); 1.71 + } else { 1.72 + addr_mark_defered(rcpt); 1.73 + /* has no effect yet, except that mail remains in spool */ 1.74 + } 1.75 + return FALSE; 1.76 +} 1.77 + 1.78 +gboolean 1.79 +deliver_local_mda(message* msg, GList* hdr_list, address* rcpt, address* env_addr) 1.80 +{ 1.81 + gboolean ok = FALSE; 1.82 + gchar *cmd = g_malloc(256); 1.83 + GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); 1.84 + guint flags; 1.85 + 1.86 + DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); 1.87 + 1.88 + if (!expand(var_table, conf.mda, cmd, 256)) { 1.89 + logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda); 1.90 + destroy_table(var_table); 1.91 + return FALSE; 1.92 + } 1.93 + 1.94 + flags = (conf.mda_fromline) ? MSGSTR_FROMLINE : 0; 1.95 + flags |= (conf.mda_fromhack) ? MSGSTR_FROMHACK : 0; 1.96 + if (pipe_out(msg, hdr_list, rcpt, cmd, flags)) { 1.97 + logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", 1.98 + msg->uid, rcpt->local_part, rcpt->domain, cmd); 1.99 + addr_mark_delivered(rcpt); 1.100 + ok = TRUE; 1.101 + } else if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { 1.102 + addr_mark_failed(rcpt); 1.103 + } else { 1.104 + addr_mark_defered(rcpt); 1.105 + /* has no effect yet, except that mail remains in spool */ 1.106 + } 1.107 + 1.108 + destroy_table(var_table); 1.109 + return ok; 1.110 +} 1.111 + 1.112 +gboolean 1.113 deliver_local(msg_out * msgout) 1.114 { 1.115 message *msg = msgout->msg; 1.116 GList *rcpt_list = msgout->rcpt_list; 1.117 GList *rcpt_node; 1.118 - gboolean ok = TRUE, flag = FALSE, ok_fail = FALSE; 1.119 + gboolean ok = FALSE, flag = FALSE, ok_fail = FALSE; 1.120 1.121 DEBUG(5) debugf("deliver_local entered\n"); 1.122 1.123 flag = (msg->data_list == NULL); 1.124 - if (flag) { 1.125 - if (!(ok = spool_read_data(msg))) { 1.126 - logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); 1.127 - } 1.128 + if (flag && !spool_read_data(msg)) { 1.129 + logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); 1.130 + return FALSE; 1.131 } 1.132 - if (!ok) 1.133 - return FALSE; 1.134 1.135 - ok = FALSE; 1.136 for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { 1.137 GList *hdr_list; 1.138 address *rcpt = (address *) (rcpt_node->data); 1.139 @@ -93,8 +173,9 @@ 1.140 address *ret_path = msg->return_path; 1.141 header *retpath_hdr, *envto_hdr; 1.142 1.143 - /* we need a private copy of the hdr list because we add headers here that belong to the rcpt only. 1.144 - g_list_copy copies only the nodes, so it is safe to g_list_free it */ 1.145 + /* we need a private copy of the hdr list because we add headers 1.146 + here that belong to the rcpt only. g_list_copy copies only 1.147 + the nodes, so it is safe to g_list_free it */ 1.148 hdr_list = g_list_copy(msg->hdr_list); 1.149 retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr)); 1.150 envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path)); 1.151 @@ -103,82 +184,38 @@ 1.152 hdr_list = g_list_prepend(hdr_list, retpath_hdr); 1.153 1.154 if (rcpt->local_part[0] == '|') { 1.155 - DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); 1.156 - if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), 1.157 - (conf.pipe_fromline ? MSGSTR_FROMLINE : 0) 1.158 - | (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))) { 1.159 - logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", 1.160 - msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); 1.161 - addr_mark_delivered(rcpt); 1.162 + /* probably for expanded aliases, but why not done 1.163 + like with the mda? //meillo 2010-12-06 */ 1.164 + if (deliver_local_pipe(msg, hdr_list, rcpt, env_addr)) { 1.165 ok = TRUE; 1.166 - } else { 1.167 - if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { 1.168 - addr_mark_failed(rcpt); 1.169 - } else { 1.170 - addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */ 1.171 - } 1.172 } 1.173 } else { 1.174 /* figure out which mailbox type should be used for this user */ 1.175 gchar *user = rcpt->local_part; 1.176 gchar *mbox_type = conf.mbox_default; 1.177 1.178 - if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp) != NULL) 1.179 + if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp)) { 1.180 mbox_type = "mbox"; 1.181 - else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp) != NULL) 1.182 + } else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp)) { 1.183 mbox_type = "mda"; 1.184 + } 1.185 1.186 if (strcmp(mbox_type, "mbox") == 0) { 1.187 - DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); 1.188 - if (append_file(msg, hdr_list, rcpt->local_part)) { 1.189 - if (env_addr != rcpt) { 1.190 - logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n", 1.191 - msg->uid, rcpt->local_part, rcpt->domain, 1.192 - env_addr->local_part, env_addr->domain); 1.193 - } else { 1.194 - logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", 1.195 - msg->uid, rcpt->local_part, rcpt->domain); 1.196 + if (deliver_local_mbox(msg, hdr_list, rcpt, env_addr)) { 1.197 + ok = TRUE; 1.198 + } 1.199 + } else if (strcmp(mbox_type, "mda") == 0) { 1.200 + if (conf.mda) { 1.201 + if (deliver_local_mda(msg, hdr_list, rcpt, env_addr)) { 1.202 + ok = TRUE; 1.203 } 1.204 - addr_mark_delivered(rcpt); 1.205 - ok = TRUE; 1.206 } else { 1.207 - if (errno != EAGAIN) { /* prevents 'Resource temporarily unavailable (11)' */ 1.208 - addr_mark_failed(rcpt); 1.209 - } else { 1.210 - addr_mark_defered(rcpt); 1.211 - } 1.212 + logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n"); 1.213 } 1.214 1.215 - } else if (strcmp(mbox_type, "mda") == 0) { 1.216 - if (conf.mda) { 1.217 - gchar *cmd = g_malloc(256); 1.218 - GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); 1.219 - 1.220 - DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); 1.221 - 1.222 - if (expand(var_table, conf.mda, cmd, 256)) { 1.223 - 1.224 - if (pipe_out(msg, hdr_list, rcpt, cmd, (conf.mda_fromline ? MSGSTR_FROMLINE : 0) 1.225 - | (conf.mda_fromhack ? MSGSTR_FROMHACK : 0))) { 1.226 - logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", 1.227 - msg->uid, rcpt->local_part, rcpt->domain, cmd); 1.228 - addr_mark_delivered(rcpt); 1.229 - ok = TRUE; 1.230 - } else { 1.231 - if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { 1.232 - addr_mark_failed(rcpt); 1.233 - } else { 1.234 - addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */ 1.235 - } 1.236 - } 1.237 - } else 1.238 - logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda); 1.239 - 1.240 - destroy_table(var_table); 1.241 - } else 1.242 - logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n"); 1.243 - } else 1.244 + } else { 1.245 logwrite(LOG_ALERT, "unknown mbox type '%s'\n", mbox_type); 1.246 + } 1.247 } 1.248 1.249 destroy_header(retpath_hdr); 1.250 @@ -188,10 +225,12 @@ 1.251 } 1.252 ok_fail = delivery_failures(msg, rcpt_list, "%s (%d)", ext_strerror(errno), errno); 1.253 1.254 - if (flag) 1.255 + if (flag) { 1.256 msg_free_data(msg); 1.257 - if (ok || ok_fail) 1.258 + } 1.259 + if (ok || ok_fail) { 1.260 deliver_finish(msgout); 1.261 + } 1.262 1.263 return ok; 1.264 } 1.265 @@ -236,20 +275,17 @@ 1.266 1.267 foreach(msgout_list, msgout_node) { 1.268 msg_out *msgout = (msg_out *) (msgout_node->data); 1.269 - gboolean flag, ok_msg = TRUE, ok_fail = FALSE; 1.270 + gboolean flag, ok_fail = FALSE; 1.271 message *msg = msgout->msg; 1.272 GList *rcpt_node, *rcpt_list = msgout->rcpt_list; 1.273 1.274 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); 1.275 1.276 flag = (msg->data_list == NULL); 1.277 - if (flag) { 1.278 - if (!(ok_msg = spool_read_data(msg))) { 1.279 - logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); 1.280 - } 1.281 + if (flag && !spool_read_data(msg)) { 1.282 + logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid); 1.283 + continue; 1.284 } 1.285 - if (!ok_msg) 1.286 - continue; 1.287 1.288 ok = FALSE; 1.289 foreach(rcpt_list, rcpt_node) { 1.290 @@ -259,7 +295,9 @@ 1.291 1.292 DEBUG(1) debugf("attempting to deliver %s to %s@%s with pipe\n", msg->uid, rcpt->local_part, rcpt->domain); 1.293 1.294 - if (expand(var_table, route->pipe, cmd, 256)) { 1.295 + if (!expand(var_table, route->pipe, cmd, 256)) { 1.296 + logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); 1.297 + } else { 1.298 1.299 if (pipe_out(msg, msg->hdr_list, rcpt, cmd, (route->pipe_fromline ? MSGSTR_FROMLINE : 0) 1.300 | (route->pipe_fromhack ? MSGSTR_FROMHACK : 0))) { 1.301 @@ -276,24 +314,25 @@ 1.302 addr_mark_defered(rcpt); 1.303 } 1.304 } 1.305 - } else 1.306 - logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); 1.307 + } 1.308 1.309 destroy_table(var_table); 1.310 } 1.311 ok_fail = delivery_failures(msg, rcpt_list, "%s", strerror(errno)); 1.312 1.313 - if (flag) 1.314 + if (flag) { 1.315 msg_free_data(msg); 1.316 - 1.317 - if (ok || ok_fail) 1.318 + } 1.319 + if (ok || ok_fail) { 1.320 deliver_finish(msgout); 1.321 + } 1.322 } 1.323 1.324 return ok; 1.325 } 1.326 1.327 -/* deliver list of messages to one host and finishes them if the message was delivered to at least one rcpt. 1.328 +/* deliver list of messages to one host and finishes them if the message was 1.329 + delivered to at least one rcpt. 1.330 Returns TRUE if at least one msg was delivered to at least one rcpt. 1.331 */ 1.332 gboolean 1.333 @@ -305,102 +344,34 @@ 1.334 gint port = 25; 1.335 1.336 /* paranoid check: */ 1.337 - if (msgout_list == NULL) { 1.338 + if (!msgout_list) { 1.339 logwrite(LOG_ALERT, "Ooops: empty list of messages in deliver_msglist_host()\n"); 1.340 return FALSE; 1.341 } 1.342 1.343 - if (host == NULL) { 1.344 + if (!host) { 1.345 /* XXX: what if mail_host isn't set? Is this possible? */ 1.346 host = route->mail_host->address; 1.347 port = route->mail_host->port; 1.348 } 1.349 1.350 - if ((psb = (route->wrapper ? smtp_out_open_child(route->wrapper) : smtp_out_open(host, port, res_list)))) { 1.351 + if (route->wrapper) { 1.352 + psb = smtp_out_open_child(route->wrapper); 1.353 + } else { 1.354 + psb = smtp_out_open(host, port, res_list); 1.355 + } 1.356 1.357 - if (route->wrapper) { 1.358 - /* it seems as if the remote_host is only set for logging 1.359 - /* XXX: this could probably be moved into smtp_out_open_child() */ 1.360 - psb->remote_host = host; 1.361 - } 1.362 - 1.363 - set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo); 1.364 - 1.365 -#ifdef ENABLE_AUTH 1.366 - if ((route->auth_name) && (route->auth_login) && (route->auth_secret)) 1.367 - set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); 1.368 -#endif 1.369 - if (smtp_out_init(psb, route->instant_helo)) { 1.370 - 1.371 - if (!route->do_pipelining) 1.372 - psb->use_pipelining = FALSE; 1.373 - 1.374 - foreach(msgout_list, msgout_node) { 1.375 - msg_out *msgout = (msg_out *) (msgout_node->data); 1.376 - gboolean flag, ok_msg = FALSE, ok_fail = FALSE; 1.377 - message *msg = msgout->msg; 1.378 - 1.379 - /* we may have to read the data at this point and remember if we did */ 1.380 - flag = (msg->data_list == NULL); 1.381 - if (flag) { 1.382 - if (!spool_read_data(msg)) { 1.383 - logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); 1.384 - break; 1.385 - } 1.386 - } 1.387 - 1.388 - smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); 1.389 - 1.390 - ok_fail = delivery_failures(msg, msgout->rcpt_list, 1.391 - "while connected with %s, the server replied\n\t%s", host, psb->buffer); 1.392 - 1.393 - if ((psb->error == smtp_eof) 1.394 - || (psb->error == smtp_timeout)) { 1.395 - /* connection lost */ 1.396 - break; 1.397 - } else if (psb->error != smtp_ok) { 1.398 - if (g_list_next(msgout_node) != NULL) 1.399 - if (!smtp_out_rset(psb)) 1.400 - break; 1.401 - } 1.402 - ok_msg = (psb->error == smtp_ok); 1.403 - 1.404 - if (flag) 1.405 - msg_free_data(msg); 1.406 - if (ok_msg) 1.407 - ok = TRUE; 1.408 - if (ok_msg || ok_fail) { 1.409 - deliver_finish(msgout); 1.410 - } 1.411 - } 1.412 - if (psb->error == smtp_ok || (psb->error == smtp_fail) 1.413 - || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { 1.414 - smtp_out_quit(psb); 1.415 - } 1.416 - } else { 1.417 - /* smtp_out_init() failed */ 1.418 - if ((psb->error == smtp_fail) || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { 1.419 - smtp_out_quit(psb); 1.420 - 1.421 - foreach(msgout_list, msgout_node) { 1.422 - msg_out *msgout = (msg_out *) (msgout_node->data); 1.423 - smtp_out_mark_rcpts(psb, msgout->rcpt_list); 1.424 - 1.425 - if (delivery_failures(msgout->msg, msgout->rcpt_list, 1.426 - "while connected with %s, the server replied\n\t%s", host, psb->buffer)) 1.427 - deliver_finish(msgout); 1.428 - } 1.429 - } 1.430 - } 1.431 - destroy_smtpbase(psb); 1.432 - } else { 1.433 + if (!psb) { 1.434 /* smtp_out_open() failed */ 1.435 foreach(msgout_list, msgout_node) { 1.436 msg_out *msgout = (msg_out *) (msgout_node->data); 1.437 GList *rcpt_node; 1.438 1.439 - for (rcpt_node = g_list_first(msgout->rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) { 1.440 + for (rcpt_node = g_list_first(msgout->rcpt_list); 1.441 + rcpt_node; 1.442 + rcpt_node = g_list_next(rcpt_node)) { 1.443 address *rcpt = (address *) (rcpt_node->data); 1.444 + gboolean ret = FALSE; 1.445 1.446 addr_unmark_delivered(rcpt); 1.447 if (route->connect_error_fail) { 1.448 @@ -408,15 +379,96 @@ 1.449 } else { 1.450 addr_mark_defered(rcpt); 1.451 } 1.452 - if (route->wrapper 1.453 - ? delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", 1.454 - strerror(errno)) 1.455 - : delivery_failures(msgout->msg, msgout->rcpt_list, "could not open connection to %s:%d :\n\t%s", 1.456 - host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno))) 1.457 + if (route->wrapper) { 1.458 + ret = delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", strerror(errno)); 1.459 + } else { 1.460 + 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)); 1.461 + } 1.462 + if (ret) { 1.463 deliver_finish(msgout); 1.464 + } 1.465 } 1.466 } 1.467 + return ok; 1.468 } 1.469 + 1.470 + 1.471 + if (route->wrapper) { 1.472 + /* it seems as if the remote_host is only set for logging 1.473 + /* XXX: this could probably be moved into smtp_out_open_child() */ 1.474 + psb->remote_host = host; 1.475 + } 1.476 + 1.477 + set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo); 1.478 + 1.479 +#ifdef ENABLE_AUTH 1.480 + if ((route->auth_name) && (route->auth_login) && (route->auth_secret)) { 1.481 + set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); 1.482 + } 1.483 +#endif 1.484 + if (!smtp_out_init(psb, route->instant_helo)) { 1.485 + /* smtp_out_init() failed */ 1.486 + if ((psb->error==smtp_fail) || (psb->error==smtp_trylater) || (psb->error==smtp_syntax)) { 1.487 + smtp_out_quit(psb); 1.488 + 1.489 + foreach(msgout_list, msgout_node) { 1.490 + msg_out *msgout = (msg_out *) (msgout_node->data); 1.491 + smtp_out_mark_rcpts(psb, msgout->rcpt_list); 1.492 + 1.493 + if (delivery_failures(msgout->msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer)) { 1.494 + deliver_finish(msgout); 1.495 + } 1.496 + } 1.497 + } 1.498 + destroy_smtpbase(psb); 1.499 + return ok; 1.500 + } 1.501 + 1.502 + if (!route->do_pipelining) { 1.503 + psb->use_pipelining = FALSE; 1.504 + } 1.505 + 1.506 + foreach(msgout_list, msgout_node) { 1.507 + msg_out *msgout = (msg_out *) (msgout_node->data); 1.508 + gboolean flag, ok_msg = FALSE, ok_fail = FALSE; 1.509 + message *msg = msgout->msg; 1.510 + 1.511 + /* we may have to read the data at this point and remember if we did */ 1.512 + flag = (msg->data_list == NULL); 1.513 + if (flag && !spool_read_data(msg)) { 1.514 + logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); 1.515 + break; 1.516 + } 1.517 + 1.518 + smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); 1.519 + 1.520 + ok_fail = delivery_failures(msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer); 1.521 + 1.522 + if ((psb->error == smtp_eof) || (psb->error == smtp_timeout)) { 1.523 + /* connection lost */ 1.524 + break; 1.525 + } else if (psb->error != smtp_ok) { 1.526 + if (g_list_next(msgout_node) && !smtp_out_rset(psb)) { 1.527 + break; 1.528 + } 1.529 + } 1.530 + ok_msg = (psb->error == smtp_ok); 1.531 + 1.532 + if (flag) { 1.533 + msg_free_data(msg); 1.534 + } 1.535 + if (ok_msg) { 1.536 + ok = TRUE; 1.537 + } 1.538 + if (ok_msg || ok_fail) { 1.539 + deliver_finish(msgout); 1.540 + } 1.541 + } 1.542 + if (psb->error == smtp_ok || (psb->error == smtp_fail) 1.543 + || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) { 1.544 + smtp_out_quit(psb); 1.545 + } 1.546 + destroy_smtpbase(psb); 1.547 return ok; 1.548 } 1.549 1.550 @@ -439,37 +491,37 @@ 1.551 deliver_route_msgout_list(connect_route * route, GList * msgout_list) 1.552 { 1.553 gboolean ok = FALSE; 1.554 + GList *mo_ph_list; 1.555 + GList *mo_ph_node; 1.556 1.557 DEBUG(5) debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name); 1.558 1.559 if (route->mail_host) { 1.560 /* this is easy... deliver everything to a smart host for relay */ 1.561 - if (deliver_msglist_host(route, msgout_list, NULL, route->resolve_list)) 1.562 + return deliver_msglist_host(route, msgout_list, NULL, route->resolve_list); 1.563 + } 1.564 + 1.565 + /* this is not easy... */ 1.566 + 1.567 + mo_ph_list = route_msgout_list(route, msgout_list); 1.568 + /* okay, now we have ordered our messages by the hosts. */ 1.569 + if (!mo_ph_list) { 1.570 + return FALSE; 1.571 + } 1.572 + 1.573 + /* TODO: It would be nice to be able to fork for each host. 1.574 + We cannot do that yet because of complications with finishing the 1.575 + messages. Threads could be a solution because they use the same 1.576 + memory. But we are not thread safe yet... 1.577 + */ 1.578 + foreach(mo_ph_list, mo_ph_node) { 1.579 + msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data); 1.580 + if (deliver_msglist_host(route, mo_ph->msgout_list, mo_ph->host, route->resolve_list)) { 1.581 ok = TRUE; 1.582 - 1.583 - } else { 1.584 - /* this is not easy... */ 1.585 - GList *mo_ph_list; 1.586 - 1.587 - mo_ph_list = route_msgout_list(route, msgout_list); 1.588 - /* okay, now we have ordered our messages by the hosts. */ 1.589 - if (mo_ph_list != NULL) { 1.590 - GList *mo_ph_node; 1.591 - /* TODO: It would be nice to be able to fork for each host. 1.592 - We cannot do that yet because of complications with finishing the 1.593 - messages. Threads could be a solution because they use the same 1.594 - memory. But we are not thread safe yet... 1.595 - */ 1.596 - foreach(mo_ph_list, mo_ph_node) { 1.597 - msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data); 1.598 - if (deliver_msglist_host (route, mo_ph->msgout_list, mo_ph->host, route->resolve_list)) 1.599 - ok = TRUE; 1.600 - 1.601 - destroy_msgout_perhost(mo_ph); 1.602 - } 1.603 - g_list_free(mo_ph_list); 1.604 } 1.605 + destroy_msgout_perhost(mo_ph); 1.606 } 1.607 + g_list_free(mo_ph_list); 1.608 return ok; 1.609 } 1.610 1.611 @@ -492,50 +544,59 @@ 1.612 GList *rcpt_list_non_delivered = NULL; 1.613 GList *rcpt_node; 1.614 1.615 - /* we have to delete already delivered rcpt's because a previous route may have delivered to it */ 1.616 + /* we have to delete already delivered rcpt's because a 1.617 + previous route may have delivered to it */ 1.618 foreach(msgout_cloned->rcpt_list, rcpt_node) { 1.619 address *rcpt = (address *) (rcpt_node->data); 1.620 - /* failed addresses already have been bounced - there should be a better way to handle those. */ 1.621 + /* failed addresses already have been bounced; 1.622 + there should be a better way to handle those. */ 1.623 if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) 1.624 - && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) 1.625 + && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) { 1.626 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); 1.627 + } 1.628 } 1.629 g_list_free(msgout_cloned->rcpt_list); 1.630 msgout_cloned->rcpt_list = rcpt_list_non_delivered; 1.631 1.632 - if (msgout_cloned->rcpt_list) { 1.633 - if (route_is_allowed_mail_local(route, msgout->msg->return_path) 1.634 - && route_is_allowed_return_path(route, msgout->msg-> return_path)) { 1.635 - GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; 1.636 - msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); 1.637 + if (!msgout_cloned->rcpt_list) { 1.638 + destroy_msg_out(msgout_cloned); 1.639 + continue; 1.640 + } 1.641 1.642 - if (rcpt_list_allowed != NULL) { 1.643 - logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); 1.644 + if (!route_is_allowed_mail_local(route, msgout->msg->return_path) 1.645 + || !route_is_allowed_return_path(route, msgout->msg-> return_path)) { 1.646 + destroy_msg_out(msgout_cloned); 1.647 + continue; 1.648 + } 1.649 1.650 - g_list_free(msgout_cloned->rcpt_list); 1.651 - msgout_cloned->rcpt_list = rcpt_list_allowed; 1.652 + GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; 1.653 + msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed); 1.654 1.655 - if (route->last_route) { 1.656 - GList *rcpt_node; 1.657 - foreach(msgout_cloned->rcpt_list, rcpt_node) { 1.658 - address *rcpt = (address *) (rcpt_node->data); 1.659 - rcpt->flags |= ADDR_FLAG_LAST_ROUTE; 1.660 - } 1.661 - } 1.662 + if (!rcpt_list_allowed) { 1.663 + destroy_msg_out(msgout_cloned); 1.664 + continue; 1.665 + } 1.666 + logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); 1.667 1.668 - route_prepare_msgout(route, msgout_cloned); 1.669 - msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); 1.670 - } else 1.671 - destroy_msg_out(msgout_cloned); 1.672 - } else 1.673 - destroy_msg_out(msgout_cloned); 1.674 - } else 1.675 - destroy_msg_out(msgout_cloned); 1.676 + g_list_free(msgout_cloned->rcpt_list); 1.677 + msgout_cloned->rcpt_list = rcpt_list_allowed; 1.678 + 1.679 + if (route->last_route) { 1.680 + GList *rcpt_node; 1.681 + foreach(msgout_cloned->rcpt_list, rcpt_node) { 1.682 + address *rcpt = (address *) (rcpt_node->data); 1.683 + rcpt->flags |= ADDR_FLAG_LAST_ROUTE; 1.684 + } 1.685 + } 1.686 + 1.687 + route_prepare_msgout(route, msgout_cloned); 1.688 + msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); 1.689 } 1.690 1.691 - if (msgout_list_deliver != NULL) { 1.692 - if (deliver_route_msgout_list(route, msgout_list_deliver)) 1.693 + if (msgout_list_deliver) { 1.694 + if (deliver_route_msgout_list(route, msgout_list_deliver)) { 1.695 ok = TRUE; 1.696 + } 1.697 destroy_msg_out_list(msgout_list_deliver); 1.698 } 1.699 return ok; 1.700 @@ -552,15 +613,16 @@ 1.701 1.702 foreach(msgout->rcpt_list, rcpt_node) { 1.703 address *rcpt = (address *) (rcpt_node->data); 1.704 - if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) 1.705 + if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) { 1.706 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); 1.707 + } 1.708 } 1.709 } 1.710 1.711 -/* after delivery attempts, we check if there are any rcpt addresses left in the message. 1.712 - If all addresses have been completed, the spool files will be deleted, 1.713 - otherwise the header spool will be written back. 1.714 - We never changed the data spool, so there is no need to write that back. 1.715 +/* after delivery attempts, we check if there are any rcpt addresses left in 1.716 + the message. If all addresses have been completed, the spool files will be 1.717 + deleted, otherwise the header spool will be written back. We never changed 1.718 + the data spool, so there is no need to write that back. 1.719 1.720 returns TRUE if all went well. 1.721 */ 1.722 @@ -568,7 +630,6 @@ 1.723 deliver_finish(msg_out * msgout) 1.724 { 1.725 GList *rcpt_node; 1.726 - gboolean ok = FALSE; 1.727 message *msg = msgout->msg; 1.728 gboolean finished = TRUE; 1.729 1.730 @@ -578,11 +639,13 @@ 1.731 were always set on the original address structs */ 1.732 foreach(msg->rcpt_list, rcpt_node) { 1.733 address *rcpt = (address *) (rcpt_node->data); 1.734 - if (!addr_is_finished_children(rcpt)) 1.735 + if (!addr_is_finished_children(rcpt)) { 1.736 finished = FALSE; 1.737 - else { 1.738 - /* if ALL children have been delivered, mark parent as delivered. 1.739 - if there is one or more not delivered, it must have failed, we mark the parent as failed as well. 1.740 + } else { 1.741 + /* if ALL children have been delivered, mark parent as 1.742 + delivered. if there is one or more not delivered, 1.743 + it must have failed, we mark the parent as failed 1.744 + as well. 1.745 */ 1.746 if (addr_is_delivered_children(rcpt)) { 1.747 addr_mark_delivered(rcpt); 1.748 @@ -592,19 +655,22 @@ 1.749 } 1.750 } 1.751 1.752 - if (!finished) { 1.753 - /* one not delivered address was found */ 1.754 - if (spool_write(msg, FALSE)) { 1.755 - ok = TRUE; 1.756 - DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); 1.757 - } else 1.758 - logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid); 1.759 - } else { 1.760 - ok = spool_delete_all(msg); 1.761 - if (ok) 1.762 + if (finished) { 1.763 + if (spool_delete_all(msg)) { 1.764 logwrite(LOG_NOTICE, "%s completed.\n", msg->uid); 1.765 + return TRUE; 1.766 + } 1.767 + return FALSE; 1.768 } 1.769 - return ok; 1.770 + 1.771 + /* one not delivered address was found */ 1.772 + if (!spool_write(msg, FALSE)) { 1.773 + logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid); 1.774 + return FALSE; 1.775 + } 1.776 + 1.777 + DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); 1.778 + return TRUE; 1.779 } 1.780 1.781 gboolean 1.782 @@ -614,8 +680,9 @@ 1.783 GList *msgout_node; 1.784 foreach(msgout_list, msgout_node) { 1.785 msg_out *msgout = (msg_out *) (msgout_node->data); 1.786 - if (!deliver_finish(msgout)) 1.787 + if (!deliver_finish(msgout)) { 1.788 ok = FALSE; 1.789 + } 1.790 } 1.791 return ok; 1.792 } 1.793 @@ -624,28 +691,36 @@ 1.794 deliver_msgout_list_online(GList * msgout_list) 1.795 { 1.796 GList *rf_list = NULL; 1.797 - gchar *connect_name = detect_online(); 1.798 + gchar *connect_name = NULL; 1.799 gboolean ok = FALSE; 1.800 1.801 - if (connect_name != NULL) { 1.802 - logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); 1.803 - /* we are online! */ 1.804 - rf_list = (GList *) table_find(conf.connect_routes, connect_name); 1.805 - if (rf_list != NULL) { 1.806 - GList *route_list = read_route_list(rf_list, FALSE); 1.807 - if (route_list) { 1.808 - GList *route_node; 1.809 - foreach(route_list, route_node) { 1.810 - connect_route *route = (connect_route *) (route_node->data); 1.811 - ok = deliver_route_msg_list(route, msgout_list); 1.812 - } 1.813 - destroy_route_list(route_list); 1.814 - } else 1.815 - logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name); 1.816 - } else { 1.817 - logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); 1.818 - } 1.819 + connect_name = detect_online(); 1.820 + if (!connect_name) { 1.821 + return FALSE; 1.822 } 1.823 + 1.824 + /* we are online! */ 1.825 + logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); 1.826 + 1.827 + rf_list = (GList *) table_find(conf.connect_routes, connect_name); 1.828 + if (!rf_list) { 1.829 + logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); 1.830 + return FALSE; 1.831 + } 1.832 + 1.833 + GList *route_list = read_route_list(rf_list, FALSE); 1.834 + if (!route_list) { 1.835 + logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name); 1.836 + return FALSE; 1.837 + } 1.838 + 1.839 + GList *route_node; 1.840 + foreach(route_list, route_node) { 1.841 + connect_route *route = (connect_route *) (route_node->data); 1.842 + /* TODO: ok gets overwritten */ 1.843 + ok = deliver_route_msg_list(route, msgout_list); 1.844 + } 1.845 + destroy_route_list(route_list); 1.846 return ok; 1.847 } 1.848 1.849 @@ -653,7 +728,9 @@ 1.850 deliver_msg_list(GList * msg_list, guint flags) 1.851 { 1.852 GList *msgout_list = create_msg_out_list(msg_list); 1.853 - GList *local_msgout_list = NULL, *localnet_msgout_list = NULL, *other_msgout_list = NULL; 1.854 + GList *local_msgout_list = NULL; 1.855 + GList *localnet_msgout_list = NULL; 1.856 + GList *other_msgout_list = NULL; 1.857 GList *msgout_node; 1.858 GList *alias_table = NULL; 1.859 gboolean ok = TRUE; 1.860 @@ -679,8 +756,11 @@ 1.861 rcpt_list = g_list_copy(msgout->msg->rcpt_list); 1.862 if (conf.log_user) { 1.863 address *addr = create_address_qualified(conf.log_user, TRUE, conf.host_name); 1.864 - if (addr) 1.865 + if (addr) { 1.866 rcpt_list = g_list_prepend(rcpt_list, addr); 1.867 + } else { 1.868 + logwrite(LOG_ALERT, "invalid log_user address `%s', ignoring\n", conf.log_user); 1.869 + } 1.870 } 1.871 if (alias_table) { 1.872 GList *aliased_rcpt_list; 1.873 @@ -714,8 +794,9 @@ 1.874 } 1.875 } 1.876 1.877 - if (alias_table) 1.878 + if (alias_table) { 1.879 destroy_table(alias_table); 1.880 + } 1.881 1.882 /* actual delivery */ 1.883 1.884 @@ -723,8 +804,9 @@ 1.885 DEBUG(5) debugf("local_msgout_list\n"); 1.886 foreach(local_msgout_list, msgout_node) { 1.887 msg_out *msgout = (msg_out *) (msgout_node->data); 1.888 - if (!deliver_local(msgout)) 1.889 + if (!deliver_local(msgout)) { 1.890 ok = FALSE; 1.891 + } 1.892 } 1.893 destroy_msg_out_list(local_msgout_list); 1.894 } 1.895 @@ -734,15 +816,17 @@ 1.896 GList *route_node; 1.897 1.898 DEBUG(5) debugf("localnet_msgout_list\n"); 1.899 - if (conf.local_net_routes) 1.900 + if (conf.local_net_routes) { 1.901 route_list = read_route_list(conf.local_net_routes, TRUE); 1.902 - else 1.903 + } else { 1.904 route_list = g_list_append(NULL, create_local_route()); 1.905 + } 1.906 1.907 foreach(route_list, route_node) { 1.908 connect_route *route = (connect_route *) (route_node->data); 1.909 - if (!deliver_route_msg_list(route, localnet_msgout_list)) 1.910 + if (!deliver_route_msg_list(route, localnet_msgout_list)) { 1.911 ok = FALSE; 1.912 + } 1.913 } 1.914 destroy_msg_out_list(localnet_msgout_list); 1.915 destroy_route_list(route_list); 1.916 @@ -750,8 +834,9 @@ 1.917 1.918 if (other_msgout_list) { 1.919 DEBUG(5) debugf("other_msgout_list\n"); 1.920 - if (!deliver_msgout_list_online(other_msgout_list)) 1.921 + if (!deliver_msgout_list_online(other_msgout_list)) { 1.922 ok = FALSE; 1.923 + } 1.924 destroy_msg_out_list(other_msgout_list); 1.925 } 1.926