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);