* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
/* See the file NOTICE for conditions of use and distribution. */
/* The main code for delivering a message. */
s = LOGGING(outgoing_port)
? string_append(s, sizep, ptrp, 2, US"]:",
string_sprintf("%d", sending_port))
- : string_cat(s, sizep, ptrp, "]", 1);
+ : string_catn(s, sizep, ptrp, US"]", 1);
}
return s;
}
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)
-#ifdef EXPERIMENTAL_EVENT
+#ifndef DISABLE_EVENT
uschar *
event_raise(uschar * action, const uschar * event, uschar * ev_data)
{
deliver_domain = save_domain;
router_name = transport_name = NULL;
}
-#endif /*EXPERIMENTAL_EVENT*/
+#endif /*DISABLE_EVENT*/
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
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)
:
s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name);
s = d_log_interface(s, &size, &ptr);
if (addr->shadow_message)
- s = string_cat(s, &size, &ptr, addr->shadow_message,
- Ustrlen(addr->shadow_message));
+ s = string_cat(s, &size, &ptr, addr->shadow_message);
}
/* Remote delivery */
{
s = d_hostlog(s, &size, &ptr, addr);
if (continue_sequence > 1)
- s = string_cat(s, &size, &ptr, US"*", 1);
+ s = string_catn(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;
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
)
&& ( 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
log_address = string_log_address(addr, LOGGING(all_parents), result == OK);
- s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address));
+ s = string_cat(s, &size, &ptr, log_address);
/* Either driver_name contains something and driver_kind contains
" router" or " transport" (note the leading space), or driver_name is
s = string_append(s, &size, &ptr, 2, US" ", driver_kind);
sprintf(CS ss, " defer (%d)", addr->basic_errno);
- s = string_cat(s, &size, &ptr, ss, Ustrlen(ss));
+ s = string_cat(s, &size, &ptr, ss);
if (addr->basic_errno > 0)
s = string_append(s, &size, &ptr, 2, US": ",
log_address = string_log_address(addr, LOGGING(all_parents), result == OK);
- s = string_cat(s, &size, &ptr, log_address, Ustrlen(log_address));
+ s = string_cat(s, &size, &ptr, log_address);
if (LOGGING(sender_on_delivery))
s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">");
log_write(0, LOG_MAIN, "** %s", s);
-#ifdef EXPERIMENTAL_EVENT
+#ifndef DISABLE_EVENT
msg_event_raise(US"msg:fail:delivery", addr);
#endif
if (message_length > 0)
{
len = read(pfd[pipe_read], big_buffer, message_length);
+ big_buffer[big_buffer_size-1] = '\0'; /* guard byte */
if (len > 0) *sptr = string_copy(big_buffer);
}
}
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 */
rmt_dlv_checked_write(int fd, char id, char subid, void * buf, int size)
{
uschar writebuffer[PIPE_HEADER_SIZE + BIG_BUFFER_SIZE];
-int header_length;
+int header_length;
+int ret;
/* we assume that size can't get larger then BIG_BUFFER_SIZE which currently is set to 16k */
/* complain to log if someone tries with buffer sizes we can't handle*/
memcpy(writebuffer + PIPE_HEADER_SIZE, buf, size);
size += PIPE_HEADER_SIZE;
-int ret = write(fd, writebuffer, size);
-if(ret != size)
+if ((ret = write(fd, writebuffer, size)) != size)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Failed writing transport result to pipe: %s\n",
ret == -1 ? strerror(errno) : "short write");
}
addr_fallback = addr;
}
- else
+ else if (next)
{
while (next->next) next = next->next;
next->next = addr_defer;
#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);
# 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
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);
}
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';
/* 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);
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);
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);
}
para = store_get(size);
for (;;)
{
- para = string_cat(para, &size, &ptr, buffer, Ustrlen(buffer));
+ para = string_cat(para, &size, &ptr, buffer);
if (!Ufgets(buffer, sizeof(buffer), f) || Ustrcmp(buffer, "****\n") == 0)
break;
}
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;
break;
}
-#ifdef EXPERIMENTAL_EVENT
+#ifndef DISABLE_EVENT
if (process_recipients != RECIP_ACCEPT)
{
uschar * save_local = deliver_localpart;
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"
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 */
}
else
DEBUG(D_deliver) debug_printf("DSN: not sending DSN success message\n");
-
- addr_dsntmp = addr_dsntmp->next;
}
if (addr_senddsn)
if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
fprintf(f, "Original-Envelope-ID: %s\n", dsn_envid);
else
- fprintf(f, "X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
+ fprintf(f, "X-Original-Envelope-ID: error decoding xtext formatted ENVID\n");
}
fputc('\n', f);
}
/* 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"
if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
fprintf(f, "Original-Envelope-ID: %s\n", dsn_envid);
else
- fprintf(f, "X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
+ fprintf(f, "X-Original-Envelope-ID: error decoding xtext formatted ENVID\n");
}
fputc('\n', f);
if (dsn_ret == dsn_ret_hdrs)
topt |= topt_no_body;
else
+ {
+ struct stat statbuf;
+
/* no full body return at all? */
if (!bounce_return_body)
{
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",
/* 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
}
FILE *wmf = NULL;
FILE *f = fdopen(fd, "wb");
uschar * bound;
+ int topt;
if (warn_message_file)
if (!(wmf = Ufopen(warn_message_file, "rb")))
if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
fprintf(f,"Original-Envelope-ID: %s\n", dsn_envid);
else
- fprintf(f,"X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
+ fprintf(f,"X-Original-Envelope-ID: error decoding xtext formatted ENVID\n");
}
fputc('\n', f);
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 */
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