* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for receiving a message and setting up spool files. */
#endif
#ifdef EXPERIMENTAL_DMARC
-#include "dmarc.h"
+# include "dmarc.h"
#endif /* EXPERIMENTAL_DMARC */
/*************************************************
/* reset optin string pointer for next recipient */
bmi_current_optin = NULL;
#endif
+#ifdef EXPERIMENTAL_DSN
+recipients_list[recipients_count].orcpt = NULL;
+recipients_list[recipients_count].dsn_flags = 0;
+#endif
recipients_list[recipients_count++].errors_to = NULL;
}
Returns: nothing
*/
-#ifdef EXPERIMENTAL_PRDR
+#ifndef DISABLE_PRDR
static void
smtp_user_msg(uschar *code, uschar *user_msg)
{
case 1: /* After written "\n" */
if (ch == '.') { ch_state = 3; continue; }
+ if (ch == '\r') { ch_state = 2; continue; }
if (ch != '\n') ch_state = 0; else linelength = -1;
break;
*/
static void
-add_acl_headers(uschar *acl_name)
+add_acl_headers(int where, uschar *acl_name)
{
header_line *h, *next;
header_line *last_received = NULL;
+switch(where)
+ {
+ case ACL_WHERE_DKIM:
+ case ACL_WHERE_MIME:
+ case ACL_WHERE_DATA:
+ if (cutthrough_fd >= 0 && (acl_removed_headers || acl_added_headers))
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC, "Header modification in data ACLs"
+ " will not take effect on cutthrough deliveries");
+ return;
+ }
+ }
+
if (acl_removed_headers != NULL)
{
DEBUG(D_receive|D_acl) debug_printf(">>Headers removed by %s ACL:\n", acl_name);
- for (h = header_list; h != NULL; h = h->next)
+ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
{
- uschar *list;
- BOOL include_header;
-
- if (h->type == htype_old) continue;
-
- include_header = TRUE;
- list = acl_removed_headers;
-
+ uschar * list = acl_removed_headers;
int sep = ':'; /* This is specified as a colon-separated list */
uschar *s;
uschar buffer[128];
- while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
- != NULL)
- {
- int len = Ustrlen(s);
- if (header_testname(h, s, len, FALSE))
+
+ while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+ if (header_testname(h, s, Ustrlen(s), FALSE))
{
h->type = htype_old;
DEBUG(D_receive|D_acl) debug_printf(" %s", h->text);
}
- }
}
acl_removed_headers = NULL;
DEBUG(D_receive|D_acl) debug_printf(">>\n");
if (rc == OK)
{
uschar temp_path[1024];
- int n;
struct dirent *entry;
DIR *tempdir;
message_id);
tempdir = opendir(CS temp_path);
- n = 0;
do
{
entry = readdir(tempdir);
}
END_MIME_ACL:
-add_acl_headers(US"MIME");
+add_acl_headers(ACL_WHERE_MIME, US"MIME");
if (rc == DISCARD)
{
recipients_count = 0;
#ifdef EXPERIMENTAL_DCC
dcc_ok = 0;
#endif
- if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
+ if (smtp_input && smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0) {
*smtp_yield_ptr = FALSE; /* No more messsages after dropped connection */
- *smtp_reply_ptr = US""; /* Indicate reply already sent */
+ *smtp_reply_ptr = US""; /* Indicate reply already sent */
+ }
message_id[0] = 0; /* Indicate no message accepted */
return FALSE; /* Cause skip to end of receive function */
}
uschar *resent_prefix = US"";
uschar *blackholed_by = NULL;
uschar *blackhole_log_msg = US"";
-int cutthrough_done = 0;
+enum {NOT_TRIED, TMP_REJ, PERM_REJ, ACCEPTED} cutthrough_done = NOT_TRIED;
flock_t lock_data;
error_block *bad_addresses = NULL;
goto TIDYUP; /* Skip to end of function */
}
received_header_gen();
- add_acl_headers(US"MAIL or RCPT");
+ add_acl_headers(ACL_WHERE_RCPT, US"MAIL or RCPT");
(void) cutthrough_headers_send();
}
/* If an ACL from any RCPT commands set up any warning headers to add, do so
now, before running the DATA ACL. */
- add_acl_headers(US"MAIL or RCPT");
+ add_acl_headers(ACL_WHERE_RCPT, US"MAIL or RCPT");
}
else
message_body_size = (fstat(data_fd, &statbuf) == 0)?
break;
}
}
- add_acl_headers(US"DKIM");
+ add_acl_headers(ACL_WHERE_DKIM, US"DKIM");
if (rc == DISCARD)
{
recipients_count = 0;
}
}
}
+#endif /* DISABLE_DKIM */
#ifdef WITH_CONTENT_SCAN
if (recipients_count > 0 &&
dmarc_up = dmarc_store_data(from_header);
#endif /* EXPERIMENTAL_DMARC */
-#ifdef EXPERIMENTAL_PRDR
- if (prdr_requested && recipients_count > 1 && acl_smtp_data_prdr != NULL )
+#ifndef DISABLE_PRDR
+ if (prdr_requested && recipients_count > 1 && acl_smtp_data_prdr)
{
unsigned int c;
int all_pass = OK;
}
if (log_msg) log_write(0, LOG_MAIN, "PRDR %s %s", addr, log_msg);
else if (user_msg) log_write(0, LOG_MAIN, "PRDR %s %s", addr, user_msg);
- else log_write(0, LOG_MAIN, CS msg);
+ else log_write(0, LOG_MAIN, "%s", CS msg);
if (rc != OK) { receive_remove_recipient(addr); c--; }
}
}
else
prdr_requested = FALSE;
-#endif /* EXPERIMENTAL_PRDR */
+#endif /* !DISABLE_PRDR */
/* Check the recipients count again, as the MIME ACL might have changed
them. */
if (acl_smtp_data != NULL && recipients_count > 0)
{
rc = acl_check(ACL_WHERE_DATA, NULL, acl_smtp_data, &user_msg, &log_msg);
- add_acl_headers(US"DATA");
+ add_acl_headers(ACL_WHERE_DATA, US"DATA");
if (rc == DISCARD)
{
recipients_count = 0;
/* Does not return */
}
}
- add_acl_headers(US"non-SMTP");
+ add_acl_headers(ACL_WHERE_NOTSMTP, US"non-SMTP");
}
}
-#endif /* DISABLE_DKIM */
-
/* The applicable ACLs have been run */
if (deliver_freeze) frozen_by = US"ACL"; /* for later logging */
s = add_host_info_for_log(s, &size, &sptr);
#ifdef SUPPORT_TLS
-if ((log_extra_selector & LX_tls_cipher) != 0 && tls_in.cipher != NULL)
+if (log_extra_selector & LX_tls_cipher && tls_in.cipher)
s = string_append(s, &size, &sptr, 2, US" X=", tls_in.cipher);
-if ((log_extra_selector & LX_tls_certificate_verified) != 0 &&
- tls_in.cipher != NULL)
+if (log_extra_selector & LX_tls_certificate_verified && tls_in.cipher)
s = string_append(s, &size, &sptr, 2, US" CV=",
tls_in.certificate_verified? "yes":"no");
-if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_in.peerdn != NULL)
+if (log_extra_selector & LX_tls_peerdn && tls_in.peerdn)
s = string_append(s, &size, &sptr, 3, US" DN=\"",
string_printing(tls_in.peerdn), US"\"");
-if ((log_extra_selector & LX_tls_sni) != 0 && tls_in.sni != NULL)
+if (log_extra_selector & LX_tls_sni && tls_in.sni)
s = string_append(s, &size, &sptr, 3, US" SNI=\"",
string_printing(tls_in.sni), US"\"");
#endif
-if (sender_host_authenticated != NULL)
+if (sender_host_authenticated)
{
s = string_append(s, &size, &sptr, 2, US" A=", sender_host_authenticated);
if (authenticated_id != NULL)
}
}
-#ifdef EXPERIMENTAL_PRDR
+#ifndef DISABLE_PRDR
if (prdr_requested)
s = string_append(s, &size, &sptr, 1, US" PRDR");
#endif
+#ifdef EXPERIMENTAL_PROXY
+if (proxy_session && log_extra_selector & LX_proxy)
+ s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address);
+#endif
+
sprintf(CS big_buffer, "%d", msg_size);
s = string_append(s, &size, &sptr, 2, US" S=", big_buffer);
XXX We do not handle queue-only, freezing, or blackholes.
*/
-cutthrough_done = 0;
if(cutthrough_fd >= 0)
{
uschar * msg= cutthrough_finaldot(); /* Ask the target system to accept the messsage */
switch(msg[0])
{
case '2': /* Accept. Do the same to the source; dump any spoolfiles. */
- cutthrough_done = 3;
+ cutthrough_done = ACCEPTED;
break; /* message_id needed for SMTP accept below */
default: /* Unknown response, or error. Treat as temp-reject. */
case '4': /* Temp-reject. Keep spoolfiles and accept. */
- cutthrough_done = 1; /* Avoid the usual immediate delivery attempt */
+ cutthrough_done = TMP_REJ; /* Avoid the usual immediate delivery attempt */
break; /* message_id needed for SMTP accept below */
case '5': /* Perm-reject. Do the same to the source. Dump any spoolfiles */
smtp_reply= msg; /* Pass on the exact error */
- cutthrough_done = 2;
+ cutthrough_done = PERM_REJ;
break;
}
}
-if(smtp_reply == NULL
-#ifdef EXPERIMENTAL_PRDR
- || prdr_requested
+#ifndef DISABLE_PRDR
+if(!smtp_reply || prdr_requested)
+#else
+if(!smtp_reply)
#endif
- )
{
log_write(0, LOG_MAIN |
(((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) |
switch (cutthrough_done)
{
- case 3: log_write(0, LOG_MAIN, "Completed"); /* Delivery was done */
- case 2: { /* Delete spool files */
+ case ACCEPTED: log_write(0, LOG_MAIN, "Completed");/* Delivery was done */
+ case PERM_REJ: { /* Delete spool files */
sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory,
message_subdir, message_id);
Uunlink(spool_name);
message_subdir, message_id);
Uunlink(spool_name);
}
- case 1: message_id[0] = 0; /* Prevent a delivery from starting */
+ case TMP_REJ: message_id[0] = 0; /* Prevent a delivery from starting */
default:break;
}
cutthrough_delivery = FALSE;