Mercurial > masqmail
comparison src/deliver.c @ 15:f671821d8222
code beautifying; 0 -> \0 if appropriate
author | meillo@marmaro.de |
---|---|
date | Thu, 06 Nov 2008 09:18:38 +0100 |
parents | 9fb7ddbaf129 |
children | 6c59dedd06be |
comparison
equal
deleted
inserted
replaced
14:a8f3424347dc | 15:f671821d8222 |
---|---|
14 You should have received a copy of the GNU General Public License | 14 You should have received a copy of the GNU General Public License |
15 along with this program; if not, write to the Free Software | 15 along with this program; if not, write to the Free Software |
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 */ | 17 */ |
18 | 18 |
19 #include "masqmail.h" | |
20 #include "smtp_out.h" | |
21 #include <fnmatch.h> | 19 #include <fnmatch.h> |
22 #include <sysexits.h> | 20 #include <sysexits.h> |
23 #include <netdb.h> | 21 #include <netdb.h> |
24 | 22 |
23 #include "masqmail.h" | |
24 #include "smtp_out.h" | |
25 | |
25 /* collect failed/defered rcpts for failure/warning messages */ | 26 /* collect failed/defered rcpts for failure/warning messages */ |
26 /* returns TRUE if either there are no failures or a | 27 /* returns TRUE if either there are no failures or a failure message has been successfully sent */ |
27 failure message has been successfully sent */ | |
28 gboolean | 28 gboolean |
29 delivery_failures(message * msg, GList * rcpt_list, gchar * err_fmt, ...) | 29 delivery_failures(message * msg, GList * rcpt_list, gchar * err_fmt, ...) |
30 { | 30 { |
31 gboolean ok_fail = TRUE, ok_warn = TRUE; | 31 gboolean ok_fail = TRUE, ok_warn = TRUE; |
32 time_t now = time(NULL); | 32 time_t now = time(NULL); |
90 address *rcpt = (address *) (rcpt_node->data); | 90 address *rcpt = (address *) (rcpt_node->data); |
91 address *env_addr = addr_find_ancestor(rcpt); | 91 address *env_addr = addr_find_ancestor(rcpt); |
92 address *ret_path = msg->return_path; | 92 address *ret_path = msg->return_path; |
93 header *retpath_hdr, *envto_hdr; | 93 header *retpath_hdr, *envto_hdr; |
94 | 94 |
95 /* we need a private copy of the hdr list because we add headers here | 95 /* we need a private copy of the hdr list because we add headers here that belong to the rcpt only. |
96 that belong to the rcpt only. | 96 g_list_copy copies only the nodes, so it is safe to g_list_free it */ |
97 g_list_copy copies only the nodes, so it is safe to | |
98 g_list_free it | |
99 */ | |
100 hdr_list = g_list_copy(msg->hdr_list); | 97 hdr_list = g_list_copy(msg->hdr_list); |
101 retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr)); | 98 retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr)); |
102 envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path)); | 99 envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path)); |
103 | 100 |
104 hdr_list = g_list_prepend(hdr_list, envto_hdr); | 101 hdr_list = g_list_prepend(hdr_list, envto_hdr); |
107 if (rcpt->local_part[0] == '|') { | 104 if (rcpt->local_part[0] == '|') { |
108 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); | 105 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); |
109 if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), | 106 if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), |
110 (conf.pipe_fromline ? MSGSTR_FROMLINE : 0) | 107 (conf.pipe_fromline ? MSGSTR_FROMLINE : 0) |
111 | (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))) { | 108 | (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))) { |
112 logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); | 109 logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", |
110 msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain); | |
113 addr_mark_delivered(rcpt); | 111 addr_mark_delivered(rcpt); |
114 ok = TRUE; | 112 ok = TRUE; |
115 } else { | 113 } else { |
116 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { | 114 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) { |
117 addr_mark_failed(rcpt); | 115 addr_mark_failed(rcpt); |
214 deliver_finish(msgout); | 212 deliver_finish(msgout); |
215 | 213 |
216 return ok; | 214 return ok; |
217 } | 215 } |
218 | 216 |
219 /* make a list of rcpt's of a message that are local | 217 /* make a list of rcpt's of a message that are local return a new copy of the list */ |
220 return a new copy of the list | |
221 */ | |
222 void | 218 void |
223 msg_rcptlist_local(GList * rcpt_list, GList ** p_local_list, GList ** p_nonlocal_list) | 219 msg_rcptlist_local(GList * rcpt_list, GList ** p_local_list, GList ** p_nonlocal_list) |
224 { | 220 { |
225 GList *rcpt_node; | 221 GList *rcpt_node; |
226 | 222 |
313 } | 309 } |
314 | 310 |
315 return ok; | 311 return ok; |
316 } | 312 } |
317 | 313 |
318 /* deliver list of messages to one host | 314 /* deliver list of messages to one host and finishes them if the message was delivered to at least one rcpt. |
319 and finishes them if the message was delivered to at least one rcpt. | |
320 Returns TRUE if at least one msg was delivered to at least one rcpt. | 315 Returns TRUE if at least one msg was delivered to at least one rcpt. |
321 */ | 316 */ |
322 | |
323 gboolean | 317 gboolean |
324 deliver_msglist_host_smtp(connect_route * route, GList * msgout_list, gchar * host, GList * res_list) | 318 deliver_msglist_host_smtp(connect_route * route, GList * msgout_list, gchar * host, GList * res_list) |
325 { | 319 { |
326 gboolean ok = FALSE; | 320 gboolean ok = FALSE; |
327 GList *msgout_node; | 321 GList *msgout_node; |
366 foreach(msgout_list, msgout_node) { | 360 foreach(msgout_list, msgout_node) { |
367 msg_out *msgout = (msg_out *) (msgout_node->data); | 361 msg_out *msgout = (msg_out *) (msgout_node->data); |
368 gboolean flag, ok_msg = FALSE, ok_fail = FALSE; | 362 gboolean flag, ok_msg = FALSE, ok_fail = FALSE; |
369 message *msg = msgout->msg; | 363 message *msg = msgout->msg; |
370 | 364 |
371 /* we may have to read the data at this point | 365 /* we may have to read the data at this point and remember if we did */ |
372 and remember if we did */ | |
373 flag = (msg->data_list == NULL); | 366 flag = (msg->data_list == NULL); |
374 if (flag) { | 367 if (flag) { |
375 if (!spool_read_data(msg)) { | 368 if (!spool_read_data(msg)) { |
376 logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); | 369 logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid); |
377 break; | 370 break; |
378 } | 371 } |
379 } | 372 } |
380 | 373 |
381 smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); | 374 smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list); |
382 | 375 |
383 ok_fail = delivery_failures(msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer); | 376 ok_fail = delivery_failures(msg, msgout->rcpt_list, |
377 "while connected with %s, the server replied\n\t%s", host, psb->buffer); | |
384 | 378 |
385 if ((psb->error == smtp_eof) | 379 if ((psb->error == smtp_eof) |
386 || (psb->error == smtp_timeout)) { | 380 || (psb->error == smtp_timeout)) { |
387 /* connection lost */ | 381 /* connection lost */ |
388 break; | 382 break; |
435 addr_mark_failed(rcpt); | 429 addr_mark_failed(rcpt); |
436 } else { | 430 } else { |
437 addr_mark_defered(rcpt); | 431 addr_mark_defered(rcpt); |
438 } | 432 } |
439 if (route->wrapper | 433 if (route->wrapper |
440 ? delivery_failures(msgout->msg, msgout->rcpt_list, | 434 ? delivery_failures(msgout->msg, msgout->rcpt_list, "could not open wrapper:\n\t%s", |
441 "could not open wrapper:\n\t%s", | |
442 strerror(errno)) | 435 strerror(errno)) |
443 : delivery_failures(msgout->msg, msgout->rcpt_list, | 436 : delivery_failures(msgout->msg, msgout->rcpt_list, "could not open connection to %s:%d :\n\t%s", |
444 "could not open connection to %s:%d :\n\t%s", | |
445 host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno))) | 437 host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno))) |
446 deliver_finish(msgout); | 438 deliver_finish(msgout); |
447 } | 439 } |
448 } | 440 } |
449 } | 441 } |
468 gboolean | 460 gboolean |
469 deliver_route_msgout_list(connect_route * route, GList * msgout_list) | 461 deliver_route_msgout_list(connect_route * route, GList * msgout_list) |
470 { | 462 { |
471 gboolean ok = FALSE; | 463 gboolean ok = FALSE; |
472 | 464 |
473 DEBUG(5) | 465 DEBUG(5) debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name); |
474 debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name); | |
475 | 466 |
476 if (route->mail_host != NULL) { | 467 if (route->mail_host != NULL) { |
477 /* this is easy... */ | 468 /* this is easy... */ |
478 if (deliver_msglist_host(route, msgout_list, NULL, route->resolve_list)) | 469 if (deliver_msglist_host(route, msgout_list, NULL, route->resolve_list)) |
479 ok = TRUE; | 470 ok = TRUE; |
504 return ok; | 495 return ok; |
505 } | 496 } |
506 | 497 |
507 /* | 498 /* |
508 calls route_prepare_msg() | 499 calls route_prepare_msg() |
509 delivers messages in msg_list using route | 500 delivers messages in msg_list using route by calling deliver_route_msgout_list() |
510 by calling deliver_route_msgout_list() | |
511 */ | 501 */ |
512 gboolean | 502 gboolean |
513 deliver_route_msg_list(connect_route * route, GList * msgout_list) | 503 deliver_route_msg_list(connect_route * route, GList * msgout_list) |
514 { | 504 { |
515 GList *msgout_list_deliver = NULL; | 505 GList *msgout_list_deliver = NULL; |
522 msg_out *msgout = (msg_out *) (msgout_node->data); | 512 msg_out *msgout = (msg_out *) (msgout_node->data); |
523 msg_out *msgout_cloned = clone_msg_out(msgout); | 513 msg_out *msgout_cloned = clone_msg_out(msgout); |
524 GList *rcpt_list_non_delivered = NULL; | 514 GList *rcpt_list_non_delivered = NULL; |
525 GList *rcpt_node; | 515 GList *rcpt_node; |
526 | 516 |
527 /* we have to delete already delivered rcpt's | 517 /* we have to delete already delivered rcpt's because a previous route may have delivered to it */ |
528 because a previous route may have delivered to it */ | |
529 foreach(msgout_cloned->rcpt_list, rcpt_node) { | 518 foreach(msgout_cloned->rcpt_list, rcpt_node) { |
530 address *rcpt = (address *) (rcpt_node->data); | 519 address *rcpt = (address *) (rcpt_node->data); |
531 /* failed addresses already have been bounced | 520 /* failed addresses already have been bounced - there should be a better way to handle those. */ |
532 - there should be a better way to handle those. */ | |
533 if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) | 521 if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) |
534 && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) | 522 && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) |
535 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); | 523 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); |
536 } | 524 } |
537 g_list_free(msgout_cloned->rcpt_list); | 525 g_list_free(msgout_cloned->rcpt_list); |
589 if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) | 577 if (addr_is_delivered(rcpt) || addr_is_failed(rcpt)) |
590 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); | 578 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); |
591 } | 579 } |
592 } | 580 } |
593 | 581 |
594 /* after delivery attempts, we check if there are any | 582 /* after delivery attempts, we check if there are any rcpt addresses left in the message. |
595 rcpt addresses left in the message. | 583 If all addresses have been completed, the spool files will be deleted, |
596 If all addresses have been completed, the spool files will | 584 otherwise the header spool will be written back. |
597 be deleted, otherwise the header spool will be written back. | |
598 We never changed the data spool, so there is no need to write that back. | 585 We never changed the data spool, so there is no need to write that back. |
599 | 586 |
600 returns TRUE if all went well. | 587 returns TRUE if all went well. |
601 */ | 588 */ |
602 gboolean | 589 gboolean |
614 foreach(msg->rcpt_list, rcpt_node) { | 601 foreach(msg->rcpt_list, rcpt_node) { |
615 address *rcpt = (address *) (rcpt_node->data); | 602 address *rcpt = (address *) (rcpt_node->data); |
616 if (!addr_is_finished_children(rcpt)) | 603 if (!addr_is_finished_children(rcpt)) |
617 finished = FALSE; | 604 finished = FALSE; |
618 else { | 605 else { |
619 /* if ALL children have been delivered, | 606 /* if ALL children have been delivered, mark parent as delivered. |
620 mark parent as delivered. | 607 if there is one or more not delivered, it must have failed, we mark the parent as failed as well. |
621 if there is one or more not delivered, | |
622 it must have failed, we mark the parent as failed as well. | |
623 */ | 608 */ |
624 if (addr_is_delivered_children(rcpt)) { | 609 if (addr_is_delivered_children(rcpt)) { |
625 addr_mark_delivered(rcpt); | 610 addr_mark_delivered(rcpt); |
626 } else { | 611 } else { |
627 addr_mark_failed(rcpt); | 612 addr_mark_failed(rcpt); |