X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Fdeliver.c;h=e588ee4a446976e158bfa225b44b5717b314192e;hp=6a3df89bb2170abbfac927b4e8b22c0ee0993a9d;hb=939c3e349db9662100c7cafa8bc1298dfd8d3798;hpb=fa41615da7020d4d951ed3a0b98464bed66ff58b diff --git a/src/src/deliver.c b/src/src/deliver.c index 6a3df89bb..e588ee4a4 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -703,7 +703,7 @@ if (LOGGING(incoming_interface) && LOGGING(outgoing_interface) s = LOGGING(outgoing_port) ? string_append(s, sizep, ptrp, 2, US"]:", string_sprintf("%d", sending_port)) - : string_cat(s, sizep, ptrp, "]", 1); + : string_cat(s, sizep, ptrp, US"]", 1); } return s; } @@ -718,11 +718,24 @@ s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, if (LOGGING(outgoing_port)) s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", addr->host_used->port)); + +#ifdef SUPPORT_SOCKS +if (LOGGING(proxy) && proxy_local_address) + { + s = string_append(s, sizep, ptrp, 3, US" PRX=[", proxy_local_address, US"]"); + if (LOGGING(outgoing_port)) + s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", + proxy_local_port)); + } +#endif + return d_log_interface(s, sizep, ptrp); } + + #ifdef SUPPORT_TLS static uschar * d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr) @@ -750,7 +763,7 @@ return s; -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT uschar * event_raise(uschar * action, const uschar * event, uschar * ev_data) { @@ -785,12 +798,14 @@ if (action) return NULL; } -static void +void msg_event_raise(const uschar * event, const address_item * addr) { const uschar * save_domain = deliver_domain; uschar * save_local = deliver_localpart; const uschar * save_host = deliver_host; +const uschar * save_address = deliver_host_address; +const int save_port = deliver_host_port; if (!addr->transport) return; @@ -802,15 +817,19 @@ deliver_localpart = addr->local_part; deliver_host = addr->host_used ? addr->host_used->name : NULL; (void) event_raise(addr->transport->event_action, event, - addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0 - ? addr->message : NULL); + addr->host_used + || Ustrcmp(addr->transport->driver_name, "smtp") == 0 + || Ustrcmp(addr->transport->driver_name, "lmtp") == 0 + ? addr->message : NULL); +deliver_host_port = save_port; +deliver_host_address = save_address; deliver_host = save_host; deliver_localpart = save_local; deliver_domain = save_domain; router_name = transport_name = NULL; } -#endif /*EXPERIMENTAL_EVENT*/ +#endif /*DISABLE_EVENT*/ @@ -835,7 +854,7 @@ the log line, and reset the store afterwards. Remote deliveries should always have a pointer to the host item that succeeded; local deliveries can have a pointer to a single host item in their host list, for use by the transport. */ -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT /* presume no successful remote delivery */ lookup_dnssec_authenticated = NULL; #endif @@ -853,7 +872,7 @@ else if (LOGGING(sender_on_delivery) || msg) s = string_append(s, &size, &ptr, 3, US" F=<", -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N testflag(addr, af_utf8_downcvt) ? string_address_utf8_to_alabel(sender_address, NULL) : @@ -909,7 +928,7 @@ else if (continue_sequence > 1) s = string_cat(s, &size, &ptr, US"*", 1); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT deliver_host_address = addr->host_used->address; deliver_host_port = addr->host_used->port; deliver_host = addr->host_used->name; @@ -980,7 +999,7 @@ store we used to build the line after writing it. */ s[ptr] = 0; log_write(0, flags, "%s", s); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT if (!msg) msg_event_raise(US"msg:delivery", addr); #endif @@ -1066,9 +1085,7 @@ if (addr->message) ) && ( Ustrstr(s, "mysql") != NULL || Ustrstr(s, "pgsql") != NULL -#ifdef EXPERIMENTAL_REDIS || Ustrstr(s, "redis") != NULL -#endif || Ustrstr(s, "sqlite") != NULL || Ustrstr(s, "ldap:") != NULL || Ustrstr(s, "ldapdn:") != NULL @@ -1288,9 +1305,17 @@ else if (result == DEFER || result == PANIC) US strerror(addr->basic_errno)); if (addr->host_used) + { s = string_append(s, &size, &ptr, 5, US" H=", addr->host_used->name, US" [", addr->host_used->address, US"]"); + if (LOGGING(outgoing_port)) + { + int port = addr->host_used->port; + s = string_append(s, &size, &ptr, 2, + US":", port == PORT_NONE ? US"25" : string_sprintf("%d", port)); + } + } if (addr->message) s = string_append(s, &size, &ptr, 2, US": ", addr->message); @@ -1412,7 +1437,7 @@ else log_write(0, LOG_MAIN, "** %s", s); -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT msg_event_raise(US"msg:fail:delivery", addr); #endif @@ -1929,7 +1954,7 @@ address. This feature is not available for shadow transports. */ if ( !shadowing && ( tp->return_output || tp->return_fail_output - || tp->log_output || tp->log_fail_output + || tp->log_output || tp->log_fail_output || tp->log_defer_output ) ) { uschar *error; @@ -2315,17 +2340,47 @@ if (addr->special_action == SPECIAL_WARN && addr->transport->warn_message) -/* Put the chain of addrs on the defer list. Retry will happen -on the next queue run, earlier if triggered by a new message. -Loop for the next set of addresses. */ +/* Check transport for the given concurrency limit. Return TRUE if over +the limit (or an expansion failure), else FALSE and if there was a limit, +the key for the hints database used for the concurrency count. */ -static void -deferlist_chain(address_item * addr) +static BOOL +tpt_parallel_check(transport_instance * tp, address_item * addr, uschar ** key) { -address_item * next; -for (next = addr; next->next; next = next->next) ; -next->next = addr_defer; -addr_defer = addr; +unsigned max_parallel; + +if (!tp->max_parallel) return FALSE; + +max_parallel = (unsigned) expand_string_integer(tp->max_parallel, TRUE); +if (expand_string_message) + { + log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand max_parallel option " + "in %s transport (%s): %s", tp->name, addr->address, + expand_string_message); + return TRUE; + } + +if (max_parallel > 0) + { + uschar * serialize_key = string_sprintf("tpt-serialize-%s", tp->name); + if (!enq_start(serialize_key, max_parallel)) + { + address_item * next; + DEBUG(D_transport) + debug_printf("skipping tpt %s because concurrency limit %u reached\n", + tp->name, max_parallel); + do + { + next = addr->next; + addr->message = US"concurrency limit reached for transport"; + addr->basic_errno = ERRNO_TRETRY; + post_process_one(addr, DEFER, LOG_MAIN, DTYPE_TRANSPORT, 0); + } while ((addr = next)); + return TRUE; + } + *key = serialize_key; + } +return FALSE; } @@ -2632,33 +2687,18 @@ while (addr_local) We use a hints DB entry, incremented here and decremented after the transport (and any shadow transport) completes. */ - if (tp->max_parallel) + if (tpt_parallel_check(tp, addr, &serialize_key)) { - int_eximarith_t max_parallel = - expand_string_integer(tp->max_parallel, TRUE); if (expand_string_message) { logflags |= LOG_PANIC; - log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand max_parallel option " - "in %s transport (%s): %s", tp->name, addr->address, - expand_string_message); - for (addr2 = addr->next; addr; addr = addr2, addr2 = addr2->next) + do + { + addr = addr->next; post_process_one(addr, DEFER, logflags, DTYPE_TRANSPORT, 0); - continue; - } - if ( max_parallel > 0 - && !enq_start( - serialize_key = string_sprintf("tpt-serialize-%s", tp->name), - (unsigned) max_parallel) - ) - { - DEBUG(D_transport) - debug_printf("skipping tpt %s because parallelism limit %u reached\n", - tp->name, (unsigned) max_parallel); - - deferlist_chain(addr); - continue; + } while ((addr = addr2)); } + continue; /* Loop for the next set of addresses. */ } @@ -3045,7 +3085,7 @@ while (!done) /* copy and read header */ memcpy(header, ptr, PIPE_HEADER_SIZE); - header[PIPE_HEADER_SIZE] = '\0'; + header[PIPE_HEADER_SIZE] = '\0'; id = header[0]; subid = header[1]; required = Ustrtol(header + 2, &endc, 10) + PIPE_HEADER_SIZE; /* header + data */ @@ -3058,7 +3098,7 @@ while (!done) } DEBUG(D_deliver) - debug_printf("header read id:%c,subid:%c,size:%s,required:%d,remaining:%d,unfinished:%d\n", + debug_printf("header read id:%c,subid:%c,size:%s,required:%d,remaining:%d,unfinished:%d\n", id, subid, header+2, required, remaining, unfinished); /* is there room for the dataset we want to read ? */ @@ -3071,16 +3111,16 @@ while (!done) break; } - /* we wrote all datasets with atomic write() calls + /* we wrote all datasets with atomic write() calls remaining < required only happens if big_buffer was too small - to get all available data from pipe. unfinished has to be true + to get all available data from pipe. unfinished has to be true as well. */ if (remaining < required) { if (unfinished) continue; msg = string_sprintf("failed to read pipe from transport process " - "%d for transport %s: required size=%d > remaining size=%d and unfinished=false", + "%d for transport %s: required size=%d > remaining size=%d and unfinished=false", pid, addr->transport->driver_name, required, remaining); done = TRUE; break; @@ -3088,7 +3128,7 @@ while (!done) /* step behind the header */ ptr += PIPE_HEADER_SIZE; - + /* Handle each possible type of item, assuming the complete item is available in store. */ @@ -3268,6 +3308,21 @@ while (!done) switch (subid) { +#ifdef SUPPORT_SOCKS + case '2': /* proxy information; must arrive before A0 and applies to that addr XXX oops*/ + proxy_session = TRUE; /*XXX shouod this be cleared somewhere? */ + if (*ptr == 0) + ptr++; + else + { + proxy_local_address = string_copy(ptr); + while(*ptr++); + memcpy(&proxy_local_port, ptr, sizeof(proxy_local_port)); + ptr += sizeof(proxy_local_port); + } + break; +#endif + #ifdef EXPERIMENTAL_DSN_INFO case '1': /* must arrive before A0, and applies to that addr */ /* Two strings: smtp_greeting and helo_response */ @@ -3807,7 +3862,7 @@ int header_length; if (size > 99999) { - log_write(0, LOG_MAIN|LOG_PANIC_DIE, + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Failed writing transport result to pipe: can't handle buffers > 99999 bytes. truncating!\n"); size = 99999; } @@ -3823,7 +3878,7 @@ if (header_length != PIPE_HEADER_SIZE) writebuffer[0] = '\0'; } -DEBUG(D_deliver) debug_printf("header write id:%c,subid:%c,size:%d,final:%s\n", +DEBUG(D_deliver) debug_printf("header write id:%c,subid:%c,size:%d,final:%s\n", id, subid, size, writebuffer); if (buf && size > 0) @@ -4091,29 +4146,11 @@ for (delivery_count = 0; addr_remote; delivery_count++) The hints DB entry is decremented in par_reduce(), when we reap the transport process. */ - if (tp->max_parallel) - { - int_eximarith_t max_parallel = - expand_string_integer(tp->max_parallel, TRUE); - if (expand_string_message) - { - panicmsg = expand_string_message; + if (tpt_parallel_check(tp, addr, &serialize_key)) + if ((panicmsg = expand_string_message)) goto panic_continue; - } - if ( max_parallel > 0 - && !enq_start( - serialize_key = string_sprintf("tpt-serialize-%s", tp->name), - (unsigned) max_parallel) - ) - { - DEBUG(D_transport) - debug_printf("skipping tpt %s because parallelism limit %u reached\n", - tp->name, (unsigned) max_parallel); - - deferlist_chain(addr); - continue; - } - } + else + continue; /* Loop for the next set of addresses. */ /* Set up the expansion variables for this set of addresses */ @@ -4207,7 +4244,11 @@ for (delivery_count = 0; addr_remote; delivery_count++) } else - deferlist_chain(addr); + { + while (next->next) next = next->next; + next->next = addr_defer; + addr_defer = addr; + } continue; } @@ -4426,15 +4467,13 @@ for (delivery_count = 0; addr_remote; delivery_count++) #ifdef SUPPORT_TLS if (addr->cipher) { - ptr = big_buffer; - sprintf(CS ptr, "%.128s", addr->cipher); - while(*ptr++); + ptr = big_buffer + sprintf(CS big_buffer, "%.128s", addr->cipher) + 1; if (!addr->peerdn) *ptr++ = 0; else { - sprintf(CS ptr, "%.512s", addr->peerdn); - while(*ptr++); + ptr += sprintf(CS ptr, "%.512s", addr->peerdn); + ptr++; } rmt_dlv_checked_write(fd, 'X', '1', big_buffer, ptr - big_buffer); @@ -4460,9 +4499,7 @@ for (delivery_count = 0; addr_remote; delivery_count++) # ifndef DISABLE_OCSP if (addr->ocsp > OCSP_NOT_REQ) { - ptr = big_buffer; - sprintf(CS ptr, "%c", addr->ocsp + '0'); - while(*ptr++); + ptr = big_buffer + sprintf(CS big_buffer, "%c", addr->ocsp + '0') + 1; rmt_dlv_checked_write(fd, 'X', '4', big_buffer, ptr - big_buffer); } # endif @@ -4470,23 +4507,17 @@ for (delivery_count = 0; addr_remote; delivery_count++) if (client_authenticator) { - ptr = big_buffer; - sprintf(CS big_buffer, "%.64s", client_authenticator); - while(*ptr++); + ptr = big_buffer + sprintf(CS big_buffer, "%.64s", client_authenticator) + 1; rmt_dlv_checked_write(fd, 'C', '1', big_buffer, ptr - big_buffer); } if (client_authenticated_id) { - ptr = big_buffer; - sprintf(CS big_buffer, "%.64s", client_authenticated_id); - while(*ptr++); + ptr = big_buffer + sprintf(CS big_buffer, "%.64s", client_authenticated_id) + 1; rmt_dlv_checked_write(fd, 'C', '2', big_buffer, ptr - big_buffer); } if (client_authenticated_sender) { - ptr = big_buffer; - sprintf(CS big_buffer, "%.64s", client_authenticated_sender); - while(*ptr++); + ptr = big_buffer + sprintf(CS big_buffer, "%.64s", client_authenticated_sender) + 1; rmt_dlv_checked_write(fd, 'C', '3', big_buffer, ptr - big_buffer); } @@ -4517,19 +4548,34 @@ for (delivery_count = 0; addr_remote; delivery_count++) rmt_dlv_checked_write(fd, 'R', '0', big_buffer, ptr - big_buffer); } +#ifdef SUPPORT_SOCKS + if (LOGGING(proxy) && proxy_session) + { + ptr = big_buffer; + if (proxy_local_address) + { + DEBUG(D_deliver) debug_printf("proxy_local_address '%s'\n", proxy_local_address); + ptr = big_buffer + sprintf(CS ptr, "%.128s", proxy_local_address) + 1; + DEBUG(D_deliver) debug_printf("proxy_local_port %d\n", proxy_local_port); + memcpy(ptr, &proxy_local_port, sizeof(proxy_local_port)); + ptr += sizeof(proxy_local_port); + } + else + *ptr++ = '\0'; + rmt_dlv_checked_write(fd, 'A', '2', big_buffer, ptr - big_buffer); + } +#endif + #ifdef EXPERIMENTAL_DSN_INFO /*um, are they really per-addr? Other per-conn stuff is not (auth, tls). But host_used is! */ if (addr->smtp_greeting) { - ptr = big_buffer; DEBUG(D_deliver) debug_printf("smtp_greeting '%s'\n", addr->smtp_greeting); - sprintf(CS ptr, "%.128s", addr->smtp_greeting); - while(*ptr++); + ptr = big_buffer + sprintf(CS big_buffer, "%.128s", addr->smtp_greeting) + 1; if (addr->helo_response) { DEBUG(D_deliver) debug_printf("helo_response '%s'\n", addr->helo_response); - sprintf(CS ptr, "%.128s", addr->helo_response); - while(*ptr++); + ptr += sprintf(CS ptr, "%.128s", addr->helo_response) + 1; } else *ptr++ = '\0'; @@ -4539,8 +4585,7 @@ for (delivery_count = 0; addr_remote; delivery_count++) /* The rest of the information goes in an 'A0' item. */ - sprintf(CS big_buffer, "%c%c", addr->transport_return, - addr->special_action); + sprintf(CS big_buffer, "%c%c", addr->transport_return, addr->special_action); ptr = big_buffer + 2; memcpy(ptr, &(addr->basic_errno), sizeof(addr->basic_errno)); ptr += sizeof(addr->basic_errno); @@ -4550,23 +4595,15 @@ for (delivery_count = 0; addr_remote; delivery_count++) ptr += sizeof(addr->flags); if (!addr->message) *ptr++ = 0; else - { - sprintf(CS ptr, "%.1024s", addr->message); - while(*ptr++); - } + ptr += sprintf(CS ptr, "%.1024s", addr->message) + 1; if (!addr->user_message) *ptr++ = 0; else - { - sprintf(CS ptr, "%.1024s", addr->user_message); - while(*ptr++); - } + ptr += sprintf(CS ptr, "%.1024s", addr->user_message) + 1; if (!addr->host_used) *ptr++ = 0; else { - sprintf(CS ptr, "%.256s", addr->host_used->name); - while(*ptr++); - sprintf(CS ptr, "%.64s", addr->host_used->address); - while(*ptr++); + ptr += sprintf(CS ptr, "%.256s", addr->host_used->name) + 1; + ptr += sprintf(CS ptr, "%.64s", addr->host_used->address) + 1; memcpy(ptr, &(addr->host_used->port), sizeof(addr->host_used->port)); ptr += sizeof(addr->host_used->port); @@ -4585,12 +4622,9 @@ for (delivery_count = 0; addr_remote; delivery_count++) if (LOGGING(incoming_interface) && sending_ip_address) #endif { - uschar * ptr = big_buffer; - sprintf(CS ptr, "%.128s", sending_ip_address); - while(*ptr++); - sprintf(CS ptr, "%d", sending_port); - while(*ptr++); - + uschar * ptr; + ptr = big_buffer + sprintf(CS big_buffer, "%.128s", sending_ip_address) + 1; + ptr += sprintf(CS ptr, "%d", sending_port) + 1; rmt_dlv_checked_write(fd, 'I', '0', big_buffer, ptr - big_buffer); } @@ -5735,7 +5769,7 @@ if (process_recipients != RECIP_IGNORE) recipient_item *r = recipients_list + i; address_item *new = deliver_make_addr(r->address, FALSE); new->prop.errors_address = r->errors_to; -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N if ((new->prop.utf8_msg = message_smtputf8)) { new->prop.utf8_downcvt = message_utf8_downconvert == 1; @@ -5750,7 +5784,7 @@ if (process_recipients != RECIP_IGNORE) if (r->pno >= 0) new->onetime_parent = recipients_list[r->pno].address; - /* If DSN support is enabled, set the dsn flags and the original receipt + /* If DSN support is enabled, set the dsn flags and the original receipt to be passed on to other DSN enabled MTAs */ new->dsn_flags = r->dsn_flags & rf_dsnflags; new->dsn_orcpt = r->orcpt; @@ -5826,7 +5860,7 @@ if (process_recipients != RECIP_IGNORE) break; } -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT if (process_recipients != RECIP_ACCEPT) { uschar * save_local = deliver_localpart; @@ -6674,7 +6708,6 @@ if (addr_local) so just queue them all. */ if (queue_run_local) - { while (addr_remote) { address_item *addr = addr_remote; @@ -6684,7 +6717,6 @@ if (queue_run_local) addr->message = US"remote deliveries suppressed"; (void)post_process_one(addr, DEFER, LOG_MAIN, DTYPE_TRANSPORT, 0); } - } /* Handle remote deliveries */ @@ -6808,16 +6840,13 @@ prevents actual delivery. */ else if (!dont_deliver) retry_update(&addr_defer, &addr_failed, &addr_succeed); -/* Send DSN for successful messages */ -addr_dsntmp = addr_succeed; +/* Send DSN for successful messages if requested */ addr_senddsn = NULL; -while(addr_dsntmp) +for (addr_dsntmp = addr_succeed; addr_dsntmp; addr_dsntmp = addr_dsntmp->next) { /* af_ignore_error not honored here. it's not an error */ - DEBUG(D_deliver) - { - debug_printf("DSN: processing router : %s\n" + DEBUG(D_deliver) debug_printf("DSN: processing router : %s\n" "DSN: processing successful delivery address: %s\n" "DSN: Sender_address: %s\n" "DSN: orcpt: %s flags: %d\n" @@ -6832,7 +6861,6 @@ while(addr_dsntmp) addr_dsntmp->address, addr_dsntmp->dsn_aware ); - } /* send report if next hop not DSN aware or a router flagged "last DSN hop" and a report was requested */ @@ -6851,9 +6879,7 @@ while(addr_dsntmp) addr_senddsn->next = addr_next; } else - DEBUG(D_deliver) debug_printf("DSN: not sending DSN success message\n"); - - addr_dsntmp = addr_dsntmp->next; + DEBUG(D_deliver) debug_printf("DSN: not sending DSN success message\n"); } if (addr_senddsn) @@ -6861,11 +6887,11 @@ if (addr_senddsn) pid_t pid; int fd; - /* create exim process to send message */ + /* create exim process to send message */ pid = child_open_exim(&fd); DEBUG(D_deliver) debug_printf("DSN: child_open_exim returns: %d\n", pid); - + if (pid < 0) /* Creation of child failed */ { log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to " @@ -6873,24 +6899,24 @@ if (addr_senddsn) getppid(), strerror(errno)); DEBUG(D_deliver) debug_printf("DSN: child_open_exim failed\n"); - } + } else /* Creation of child succeeded */ { FILE *f = fdopen(fd, "wb"); /* header only as required by RFC. only failure DSN needs to honor RET=FULL */ int topt = topt_add_return_path | topt_no_body; uschar * bound; - + DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address); - + /* build unique id for MIME boundary */ bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand()); DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", bound); - + if (errors_reply_to) fprintf(f, "Reply-To: %s\n", errors_reply_to); - + fprintf(f, "Auto-Submitted: auto-generated\n" "From: Mail Delivery System \n" "To: %s\n" @@ -6900,7 +6926,7 @@ if (addr_senddsn) "--%s\n" "Content-type: text/plain; charset=us-ascii\n\n" - + "This message was created automatically by mail delivery software.\n" " ----- The following addresses had successful delivery notifications -----\n", qualify_domain_sender, sender_address, bound, bound); @@ -6952,11 +6978,11 @@ if (addr_senddsn) } fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", bound); - + fflush(f); transport_filter_argv = NULL; /* Just in case */ return_path = sender_address; /* In case not previously set */ - + /* Write the original email out */ transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0); fflush(f); @@ -7293,7 +7319,7 @@ wording. */ } /* output machine readable part */ -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N if (message_smtputf8) fprintf(f, "--%s\n" "Content-type: message/global-delivery-status\n\n" @@ -7316,7 +7342,7 @@ wording. */ fprintf(f, "X-Original-Envelope-ID: error decoding xtext formated ENVID\n"); } fputc('\n', f); - + for (addr = handled_addr; addr; addr = addr->next) { host_item * hu; @@ -7327,8 +7353,7 @@ wording. */ if ((hu = addr->host_used) && hu->name) { const uschar * s; - fprintf(f, "Remote-MTA: dns; %s\n", - hu->name); + fprintf(f, "Remote-MTA: dns; %s\n", hu->name); #ifdef EXPERIMENTAL_DSN_INFO if (hu->address) { @@ -7356,16 +7381,16 @@ wording. */ emf_text = next_emf(emf, US"copy"); /* add message body - we ignore the intro text from template and add + we ignore the intro text from template and add the text for bounce_return_size_limit at the end. - + bounce_return_message is ignored in case RET= is defined we honor these values otherwise bounce_return_body is honored. - + bounce_return_size_limit is always honored. */ - + fprintf(f, "--%s\n", bound); dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned"; @@ -7376,6 +7401,9 @@ wording. */ if (dsn_ret == dsn_ret_hdrs) topt |= topt_no_body; else + { + struct stat statbuf; + /* no full body return at all? */ if (!bounce_return_body) { @@ -7384,18 +7412,20 @@ wording. */ if (dsn_ret == dsn_ret_full) dsnnotifyhdr = dsnlimitmsg; } + /* line length limited... return headers only if oversize */ /* size limited ... return headers only if limit reached */ - else if (bounce_return_size_limit > 0) - { - struct stat statbuf; - if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max) - { - topt |= topt_no_body; - dsnnotifyhdr = dsnlimitmsg; - } + else if ( max_received_linelength > bounce_return_linesize_limit + || ( bounce_return_size_limit > 0 + && fstat(deliver_datafile, &statbuf) == 0 + && statbuf.st_size > max + ) ) + { + topt |= topt_no_body; + dsnnotifyhdr = dsnlimitmsg; } - -#ifdef EXPERIMENTAL_INTERNATIONAL + } + +#ifdef SUPPORT_I18N if (message_smtputf8) fputs(topt & topt_no_body ? "Content-type: message/global-headers\n\n" : "Content-type: message/global\n\n", @@ -7412,11 +7442,11 @@ wording. */ transport_write_message(NULL, fileno(f), topt, 0, dsnnotifyhdr, NULL, NULL, NULL, NULL, 0); fflush(f); - + /* we never add the final text. close the file */ if (emf) (void)fclose(emf); - + fprintf(f, "\n--%s--\n", bound); /* Close the file, which should send an EOF to the child process @@ -7531,7 +7561,7 @@ if (!addr_defer) /* Unset deliver_freeze so that we won't try to move the spool files further down */ deliver_freeze = FALSE; -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT (void) event_raise(event_action, US"msg:complete", NULL); #endif } @@ -7723,6 +7753,7 @@ else if (addr_defer != (address_item *)(+1)) FILE *wmf = NULL; FILE *f = fdopen(fd, "wb"); uschar * bound; + int topt; if (warn_message_file) if (!(wmf = Ufopen(warn_message_file, "rb"))) @@ -7832,7 +7863,7 @@ else if (addr_defer != (address_item *)(+1)) "Reporting-MTA: dns; %s\n", bound, smtp_active_hostname); - + if (dsn_envid) { @@ -7856,7 +7887,7 @@ else if (addr_defer != (address_item *)(+1)) addr_dsndefer->address); if (addr_dsndefer->host_used && addr_dsndefer->host_used->name) { - fprintf(f, "Remote-MTA: dns; %s\n", + fprintf(f, "Remote-MTA: dns; %s\n", addr_dsndefer->host_used->name); print_dsn_diagnostic_code(addr_dsndefer, f); } @@ -7869,7 +7900,7 @@ else if (addr_defer != (address_item *)(+1)) fflush(f); /* header only as required by RFC. only failure DSN needs to honor RET=FULL */ - int topt = topt_add_return_path | topt_no_body; + topt = topt_add_return_path | topt_no_body; transport_filter_argv = NULL; /* Just in case */ return_path = sender_address; /* In case not previously set */ /* Write the original email out */ @@ -8041,7 +8072,7 @@ if (!regex_PRDR) regex_PRDR = regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE); #endif -#ifdef EXPERIMENTAL_INTERNATIONAL +#ifdef SUPPORT_I18N if (!regex_UTF8) regex_UTF8 = regex_must_compile(US"\\n250[\\s\\-]SMTPUTF8(\\s|\\n|$)", FALSE, TRUE); #endif