X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/789f8a4f4046120b7ae2aafa45f7f45c3ae4c8f5..6b46ecc6a8f5e3ab97c62451646a6d6045205bb1:/src/src/deliver.c diff --git a/src/src/deliver.c b/src/src/deliver.c index a1fb602e9..202f7a400 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -76,8 +76,6 @@ static int return_count; static uschar *frozen_info = US""; static uschar *used_return_path = NULL; -static uschar spoolname[PATH_MAX]; - /************************************************* @@ -285,10 +283,9 @@ int fd = Uopen(filename, O_WRONLY|O_APPEND|O_CREAT, mode); if (fd < 0 && errno == ENOENT) { - uschar temp[16]; - sprintf(CS temp, "msglog/%s", message_subdir); - if (message_subdir[0] == 0) temp[6] = 0; - (void)directory_make(spool_directory, temp, MSGLOG_DIRECTORY_MODE, TRUE); + (void)directory_make(spool_directory, + spool_sname(US"msglog", message_subdir), + MSGLOG_DIRECTORY_MODE, TRUE); fd = Uopen(filename, O_WRONLY|O_APPEND|O_CREAT, mode); } @@ -711,25 +708,31 @@ return s; static uschar * -d_hostlog(uschar *s, int *sizep, int *ptrp, address_item *addr) +d_hostlog(uschar * s, int * sp, int * pp, address_item * addr) { -s = string_append(s, sizep, ptrp, 5, US" H=", addr->host_used->name, - US" [", addr->host_used->address, US"]"); +host_item * h = addr->host_used; + +s = string_append(s, sp, pp, 2, US" H=", h->name); + +if (LOGGING(dnssec) && h->dnssec == DS_YES) + s = string_cat(s, sp, pp, US" DS"); + +s = string_append(s, sp, pp, 3, US" [", h->address, US"]"); + if (LOGGING(outgoing_port)) - s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", - addr->host_used->port)); + s = string_append(s, sp, pp, 2, US":", string_sprintf("%d", h->port)); #ifdef SUPPORT_SOCKS if (LOGGING(proxy) && proxy_local_address) { - s = string_append(s, sizep, ptrp, 3, US" PRX=[", proxy_local_address, US"]"); + s = string_append(s, sp, pp, 3, US" PRX=[", proxy_local_address, US"]"); if (LOGGING(outgoing_port)) - s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d", + s = string_append(s, sp, pp, 2, US":", string_sprintf("%d", proxy_local_port)); } #endif -return d_log_interface(s, sizep, ptrp); +return d_log_interface(s, sp, pp); } @@ -880,6 +883,9 @@ if (LOGGING(sender_on_delivery) || msg) sender_address, US">"); +if (*queue_name) + s = string_append(s, &size, &ptr, 2, US" Q=", queue_name); + #ifdef EXPERIMENTAL_SRS if(addr->prop.srs_sender) s = string_append(s, &size, &ptr, 3, US" SRS=<", addr->prop.srs_sender, US">"); @@ -1076,21 +1082,9 @@ malformed, it won't ever have gone near LDAP.) */ if (addr->message) { const uschar * s = string_printing(addr->message); - if (s != addr->message) - addr->message = US s; - /* deconst cast ok as string_printing known to have alloc'n'copied */ - if ( ( Ustrstr(s, "failed to expand") != NULL - || Ustrstr(s, "expansion of ") != NULL - ) - && ( Ustrstr(s, "mysql") != NULL - || Ustrstr(s, "pgsql") != NULL - || Ustrstr(s, "redis") != NULL - || Ustrstr(s, "sqlite") != NULL - || Ustrstr(s, "ldap:") != NULL - || Ustrstr(s, "ldapdn:") != NULL - || Ustrstr(s, "ldapm:") != NULL - ) ) - addr->message = string_sprintf("Temporary internal error"); + + /* deconst cast ok as string_printing known to have alloc'n'copied */ + addr->message = expand_hide_passwords(US s); } /* If we used a transport that has one of the "return_output" options set, and @@ -1279,6 +1273,9 @@ else if (result == DEFER || result == PANIC) s = string_cat(s, &size, &ptr, log_address); + if (*queue_name) + s = string_append(s, &size, &ptr, 2, US" Q=", queue_name); + /* Either driver_name contains something and driver_kind contains " router" or " transport" (note the leading space), or driver_name is a null string and driver_kind contains "routing" without the leading @@ -1400,6 +1397,9 @@ else if (LOGGING(sender_on_delivery)) s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">"); + if (*queue_name) + s = string_append(s, &size, &ptr, 2, US" Q=", queue_name); + /* Return path may not be set if no delivery actually happened */ if (used_return_path && LOGGING(return_path_on_delivery)) @@ -1956,12 +1956,13 @@ if ( !shadowing || tp->log_output || tp->log_fail_output || tp->log_defer_output ) ) { - uschar *error; + uschar * error; + addr->return_filename = - string_sprintf("%s/msglog/%s/%s-%d-%d", spool_directory, message_subdir, - message_id, getpid(), return_count++); - addr->return_file = open_msglog_file(addr->return_filename, 0400, &error); - if (addr->return_file < 0) + spool_fname(US"msglog", message_subdir, message_id, + string_sprintf("-%d-%d", getpid(), return_count++)); + + if ((addr->return_file = open_msglog_file(addr->return_filename, 0400, &error)) < 0) { common_error(TRUE, addr, errno, US"Unable to %s file for %s transport " "to return message: %s", error, tp->name, strerror(errno)); @@ -4384,13 +4385,13 @@ for (delivery_count = 0; addr_remote; delivery_count++) a dup-with-new-file-pointer. */ (void)close(deliver_datafile); - sprintf(CS spoolname, "%s/input/%s/%s-D", spool_directory, message_subdir, - message_id); - deliver_datafile = Uopen(spoolname, O_RDWR | O_APPEND, 0); + { + uschar * fname = spool_fname(US"input", message_subdir, message_id, US"-D"); - if (deliver_datafile < 0) + if ((deliver_datafile = Uopen(fname, O_RDWR | O_APPEND, 0)) < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Failed to reopen %s for remote " - "parallel delivery: %s", spoolname, strerror(errno)); + "parallel delivery: %s", fname, strerror(errno)); + } /* Set the close-on-exec flag */ @@ -4721,13 +4722,17 @@ Returns: OK */ int -deliver_split_address(address_item *addr) +deliver_split_address(address_item * addr) { -uschar *address = addr->address; -uschar *domain = Ustrrchr(address, '@'); -uschar *t; -int len = domain - address; +uschar * address = addr->address; +uschar * domain; +uschar * t; +int len; +if (!(domain = Ustrrchr(address, '@'))) + return DEFER; /* should always have a domain, but just in case... */ + +len = domain - address; addr->domain = string_copylc(domain+1); /* Domains are always caseless */ /* The implication in the RFCs (though I can't say I've seen it spelled out @@ -4739,7 +4744,7 @@ removing quoting backslashes and any unquoted doublequotes. */ t = addr->cc_local_part = store_get(len+1); while(len-- > 0) { - register int c = *address++; + int c = *address++; if (c == '\"') continue; if (c == '\\') { @@ -5237,53 +5242,51 @@ store, and also the list of recipients and the tree of non-recipients and assorted flags. It updates message_size. If there is a reading or format error, give up; if the message has been around for sufficiently long, remove it. */ -sprintf(CS spoolname, "%s-H", id); -if ((rc = spool_read_header(spoolname, TRUE, TRUE)) != spool_read_OK) { - if (errno == ERRNO_SPOOLFORMAT) + uschar * spoolname = string_sprintf("%s-H", id); + if ((rc = spool_read_header(spoolname, TRUE, TRUE)) != spool_read_OK) { - struct stat statbuf; - sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir, - spoolname); - if (Ustat(big_buffer, &statbuf) == 0) - log_write(0, LOG_MAIN, "Format error in spool file %s: " - "size=" OFF_T_FMT, spoolname, statbuf.st_size); - else log_write(0, LOG_MAIN, "Format error in spool file %s", spoolname); - } - else - log_write(0, LOG_MAIN, "Error reading spool file %s: %s", spoolname, - strerror(errno)); + if (errno == ERRNO_SPOOLFORMAT) + { + struct stat statbuf; + if (Ustat(spool_fname(US"input", message_subdir, spoolname, US""), + &statbuf) == 0) + log_write(0, LOG_MAIN, "Format error in spool file %s: " + "size=" OFF_T_FMT, spoolname, statbuf.st_size); + else + log_write(0, LOG_MAIN, "Format error in spool file %s", spoolname); + } + else + log_write(0, LOG_MAIN, "Error reading spool file %s: %s", spoolname, + strerror(errno)); - /* If we managed to read the envelope data, received_time contains the - time the message was received. Otherwise, we can calculate it from the - message id. */ + /* If we managed to read the envelope data, received_time contains the + time the message was received. Otherwise, we can calculate it from the + message id. */ - if (rc != spool_read_hdrerror) - { - received_time = 0; - for (i = 0; i < 6; i++) - received_time = received_time * BASE_62 + tab62[id[i] - '0']; - } + if (rc != spool_read_hdrerror) + { + received_time = 0; + for (i = 0; i < 6; i++) + received_time = received_time * BASE_62 + tab62[id[i] - '0']; + } - /* If we've had this malformed message too long, sling it. */ + /* If we've had this malformed message too long, sling it. */ - if (now - received_time > keep_malformed) - { - sprintf(CS spoolname, "%s/msglog/%s/%s", spool_directory, message_subdir, id); - Uunlink(spoolname); - sprintf(CS spoolname, "%s/input/%s/%s-D", spool_directory, message_subdir, id); - Uunlink(spoolname); - sprintf(CS spoolname, "%s/input/%s/%s-H", spool_directory, message_subdir, id); - Uunlink(spoolname); - sprintf(CS spoolname, "%s/input/%s/%s-J", spool_directory, message_subdir, id); - Uunlink(spoolname); - log_write(0, LOG_MAIN, "Message removed because older than %s", - readconf_printtime(keep_malformed)); - } + if (now - received_time > keep_malformed) + { + Uunlink(spool_fname(US"msglog", message_subdir, id, US"")); + Uunlink(spool_fname(US"input", message_subdir, id, US"-D")); + Uunlink(spool_fname(US"input", message_subdir, id, US"-H")); + Uunlink(spool_fname(US"input", message_subdir, id, US"-J")); + log_write(0, LOG_MAIN, "Message removed because older than %s", + readconf_printtime(keep_malformed)); + } - (void)close(deliver_datafile); - deliver_datafile = -1; - return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ + (void)close(deliver_datafile); + deliver_datafile = -1; + return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ + } } /* The spool header file has been read. Look to see if there is an existing @@ -5295,37 +5298,39 @@ existence, as it will get further successful deliveries added to it in this run, and it will be deleted if this function gets to its end successfully. Otherwise it might be needed again. */ -sprintf(CS spoolname, "%s/input/%s/%s-J", spool_directory, message_subdir, id); -jread = Ufopen(spoolname, "rb"); -if (jread) { - while (Ufgets(big_buffer, big_buffer_size, jread)) + uschar * fname = spool_fname(US"input", message_subdir, id, US"-J"); + + if ((jread = Ufopen(fname, "rb"))) { - int n = Ustrlen(big_buffer); - big_buffer[n-1] = 0; - tree_add_nonrecipient(big_buffer); - DEBUG(D_deliver) debug_printf("Previously delivered address %s taken from " - "journal file\n", big_buffer); + while (Ufgets(big_buffer, big_buffer_size, jread)) + { + int n = Ustrlen(big_buffer); + big_buffer[n-1] = 0; + tree_add_nonrecipient(big_buffer); + DEBUG(D_deliver) debug_printf("Previously delivered address %s taken from " + "journal file\n", big_buffer); + } + (void)fclose(jread); + /* Panic-dies on error */ + (void)spool_write_header(message_id, SW_DELIVERING, NULL); + } + else if (errno != ENOENT) + { + log_write(0, LOG_MAIN|LOG_PANIC, "attempt to open journal for reading gave: " + "%s", strerror(errno)); + return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ } - (void)fclose(jread); - /* Panic-dies on error */ - (void)spool_write_header(message_id, SW_DELIVERING, NULL); - } -else if (errno != ENOENT) - { - log_write(0, LOG_MAIN|LOG_PANIC, "attempt to open journal for reading gave: " - "%s", strerror(errno)); - return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ - } -/* A null recipients list indicates some kind of disaster. */ + /* A null recipients list indicates some kind of disaster. */ -if (!recipients_list) - { - (void)close(deliver_datafile); - deliver_datafile = -1; - log_write(0, LOG_MAIN, "Spool error: no recipients for %s", spoolname); - return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ + if (!recipients_list) + { + (void)close(deliver_datafile); + deliver_datafile = -1; + log_write(0, LOG_MAIN, "Spool error: no recipients for %s", fname); + return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ + } } @@ -5413,16 +5418,14 @@ done by rewriting the header spool file. */ if (message_logs) { - uschar *error; + uschar * fname = spool_fname(US"msglog", message_subdir, id, US""); + uschar * error; int fd; - sprintf(CS spoolname, "%s/msglog/%s/%s", spool_directory, message_subdir, id); - fd = open_msglog_file(spoolname, SPOOL_MODE, &error); - - if (fd < 0) + if ((fd = open_msglog_file(fname, SPOOL_MODE, &error)) < 0) { log_write(0, LOG_MAIN|LOG_PANIC, "Couldn't %s message log %s: %s", error, - spoolname, strerror(errno)); + fname, strerror(errno)); return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ } @@ -5431,7 +5434,7 @@ if (message_logs) if (!(message_log = fdopen(fd, "a"))) { log_write(0, LOG_MAIN|LOG_PANIC, "Couldn't fdopen message log %s: %s", - spoolname, strerror(errno)); + fname, strerror(errno)); return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ } } @@ -6650,13 +6653,12 @@ therein are added to the non-recipients. */ if (addr_local || addr_remote) { - sprintf(CS spoolname, "%s/input/%s/%s-J", spool_directory, message_subdir, id); - journal_fd = Uopen(spoolname, O_WRONLY|O_APPEND|O_CREAT, SPOOL_MODE); - - if (journal_fd < 0) + uschar * fname = spool_fname(US"input", message_subdir, id, US"-J"); + + if ((journal_fd = Uopen(fname, O_WRONLY|O_APPEND|O_CREAT, SPOOL_MODE)) <0) { log_write(0, LOG_MAIN|LOG_PANIC, "Couldn't open journal file %s: %s", - spoolname, strerror(errno)); + fname, strerror(errno)); return DELIVER_NOT_ATTEMPTED; } @@ -6669,12 +6671,12 @@ if (addr_local || addr_remote) || fchmod(journal_fd, SPOOL_MODE) ) { - int ret = Uunlink(spoolname); + int ret = Uunlink(fname); log_write(0, LOG_MAIN|LOG_PANIC, "Couldn't set perms on journal file %s: %s", - spoolname, strerror(errno)); + fname, strerror(errno)); if(ret && errno != ENOENT) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s", - spoolname, strerror(errno)); + fname, strerror(errno)); return DELIVER_NOT_ATTEMPTED; } } @@ -6904,8 +6906,8 @@ if (addr_senddsn) { 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; + transport_ctx tctx; DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address); @@ -6984,7 +6986,10 @@ if (addr_senddsn) 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); + + bzero(&tctx, sizeof(tctx)); + tctx.options = topt_add_return_path | topt_no_body; + transport_write_message(fileno(f), &tctx, 0); fflush(f); fprintf(f,"\n--%s--\n", bound); @@ -7439,8 +7444,18 @@ wording. */ fflush(f); transport_filter_argv = NULL; /* Just in case */ return_path = sender_address; /* In case not previously set */ - transport_write_message(NULL, fileno(f), topt, - 0, dsnnotifyhdr, NULL, NULL, NULL, NULL, 0); + { /* Dummy transport for headers add */ + transport_ctx * tctx = + store_get(sizeof(*tctx) + sizeof(transport_instance)); + transport_instance * tb = (transport_instance *)(tctx+1); + + bzero(tctx, sizeof(*tctx)+sizeof(*tb)); + tctx->tblock = tb; + tctx->options = topt; + tb->add_headers = dsnnotifyhdr; + + transport_write_message(fileno(f), tctx, 0); + } fflush(f); /* we never add the final text. close the file */ @@ -7515,40 +7530,43 @@ Then delete the message itself. */ if (!addr_defer) { + uschar * fname; + if (message_logs) { - sprintf(CS spoolname, "%s/msglog/%s/%s", spool_directory, message_subdir, - id); + fname = spool_fname(US"msglog", message_subdir, id, US""); if (preserve_message_logs) { int rc; - sprintf(CS big_buffer, "%s/msglog.OLD/%s", spool_directory, id); - if ((rc = Urename(spoolname, big_buffer)) < 0) + uschar * moname = spool_fname(US"msglog.OLD", US"", id, US""); + + if ((rc = Urename(fname, moname)) < 0) { - (void)directory_make(spool_directory, US"msglog.OLD", - MSGLOG_DIRECTORY_MODE, TRUE); - rc = Urename(spoolname, big_buffer); + (void)directory_make(spool_directory, + spool_sname(US"msglog.OLD", US""), + MSGLOG_DIRECTORY_MODE, TRUE); + rc = Urename(fname, moname); } if (rc < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to move %s to the " - "msglog.OLD directory", spoolname); + "msglog.OLD directory", fname); } else - if (Uunlink(spoolname) < 0) + if (Uunlink(fname) < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s", - spoolname, strerror(errno)); + fname, strerror(errno)); } /* Remove the two message files. */ - sprintf(CS spoolname, "%s/input/%s/%s-D", spool_directory, message_subdir, id); - if (Uunlink(spoolname) < 0) + fname = spool_fname(US"input", message_subdir, id, US"-D"); + if (Uunlink(fname) < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s", - spoolname, strerror(errno)); - sprintf(CS spoolname, "%s/input/%s/%s-H", spool_directory, message_subdir, id); - if (Uunlink(spoolname) < 0) + fname, strerror(errno)); + fname = spool_fname(US"input", message_subdir, id, US"-H"); + if (Uunlink(fname) < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s", - spoolname, strerror(errno)); + fname, strerror(errno)); /* Log the end of this message, with queue time if requested. */ @@ -7753,7 +7771,9 @@ else if (addr_defer != (address_item *)(+1)) FILE *wmf = NULL; FILE *f = fdopen(fd, "wb"); uschar * bound; - int topt; + transport_ctx tctx; + + bzero(&tctx, sizeof(tctx)); if (warn_message_file) if (!(wmf = Ufopen(warn_message_file, "rb"))) @@ -7900,11 +7920,12 @@ else if (addr_defer != (address_item *)(+1)) fflush(f); /* header only as required by RFC. only failure DSN needs to honor RET=FULL */ - topt = topt_add_return_path | topt_no_body; + tctx.options = 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 */ - transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0); + transport_write_message(fileno(f), &tctx, 0); fflush(f); fprintf(f,"\n--%s--\n", bound); @@ -8015,9 +8036,10 @@ if (journal_fd >= 0) (void)close(journal_fd); if (remove_journal) { - sprintf(CS spoolname, "%s/input/%s/%s-J", spool_directory, message_subdir, id); - if (Uunlink(spoolname) < 0 && errno != ENOENT) - log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s", spoolname, + uschar * fname = spool_fname(US"input", message_subdir, id, US"-J"); + + if (Uunlink(fname) < 0 && errno != ENOENT) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s: %s", fname, strerror(errno)); /* Move the message off the spool if reqested */ @@ -8092,6 +8114,7 @@ int rc; uschar * new_sender_address, * save_sender_address; BOOL save_qr = queue_running; +uschar * spoolname; /* make spool_open_datafile non-noisy on fail */ @@ -8110,7 +8133,7 @@ spool_read_header() may change all of them. But OTOH, when this deliver_get_sender_address() gets called, the current message is done already and nobody needs the globals anymore. (HS12, 2015-08-21) */ -sprintf(CS spoolname, "%s-H", id); +spoolname = string_sprintf("%s-H", id); save_sender_address = sender_address; rc = spool_read_header(spoolname, TRUE, TRUE);