+/*************************************************
+* Send user response message *
+*************************************************/
+
+/* This function is passed a default response code and a user message. It calls
+smtp_message_code() to check and possibly modify the response code, and then
+calls smtp_respond() to transmit the response. I put this into a function
+just to avoid a lot of repetition.
+
+Arguments:
+ code the response code
+ user_msg the user message
+
+Returns: nothing
+*/
+
+static void
+smtp_user_msg(uschar *code, uschar *user_msg)
+{
+int len = 3;
+smtp_message_code(&code, &len, &user_msg, NULL);
+smtp_respond(code, len, TRUE, user_msg);
+}
+
+
+
+
+
/*************************************************
* Remove a recipient from the list *
*************************************************/
{
header_line *h, *next;
header_line *last_received = NULL;
-int sep = ':';
if (acl_removed_headers != NULL)
{
for (h = header_list; h != NULL; h = h->next)
{
- int i;
uschar *list;
BOOL include_header;
uschar *resent_prefix = US"";
uschar *blackholed_by = NULL;
uschar *blackhole_log_msg = US"";
-int cutthrough_done;
+int cutthrough_done = 0;
flock_t lock_data;
error_block *bad_addresses = NULL;
from_header = h;
if (!smtp_input)
{
+ int len;
uschar *s = Ustrchr(h->text, ':') + 1;
while (isspace(*s)) s++;
- if (strncmpic(s, originator_login, h->slen - (s - h->text) - 1) == 0)
+ len = h->slen - (s - h->text) - 1;
+ if (Ustrlen(originator_login) == len &&
+ strncmpic(s, originator_login, len) == 0)
{
uschar *name = is_resent? US"Resent-From" : US"From";
header_add(htype_from, "%s: %s <%s@%s>\n", name, originator_name,
/* Make sure the file's group is the Exim gid, and double-check the mode
because the group setting doesn't always get set automatically. */
-(void)fchown(data_fd, exim_uid, exim_gid);
+if (fchown(data_fd, exim_uid, exim_gid))
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+ "Failed setting ownership on spool file %s: %s",
+ spool_name, strerror(errno));
(void)fchmod(data_fd, SPOOL_MODE);
/* We now have data file open. Build a stream for it and lock it. We lock only
{
uschar *s = next->text;
int len = next->slen;
- (void)fwrite(s, 1, len, data_file);
+ len = fwrite(s, 1, len, data_file); len = len; /* compiler quietening */
body_linecount++; /* Assumes only 1 line */
}
goto TIDYUP;
#endif /* WITH_CONTENT_SCAN */
+#ifdef EXPERIMENTAL_PRDR
+ if (prdr_requested && recipients_count > 1 && acl_smtp_data_prdr != NULL )
+ {
+ unsigned int c;
+ int all_pass = OK;
+ int all_fail = FAIL;
+
+ smtp_printf("353 PRDR content analysis beginning\r\n");
+ /* Loop through recipients, responses must be in same order received */
+ for (c = 0; recipients_count > c; c++)
+ {
+ uschar * addr= recipients_list[c].address;
+ uschar * msg= US"PRDR R=<%s> %s";
+ uschar * code;
+ DEBUG(D_receive)
+ debug_printf("PRDR processing recipient %s (%d of %d)\n",
+ addr, c+1, recipients_count);
+ rc = acl_check(ACL_WHERE_PRDR, addr,
+ acl_smtp_data_prdr, &user_msg, &log_msg);
+
+ /* If any recipient rejected content, indicate it in final message */
+ all_pass |= rc;
+ /* If all recipients rejected, indicate in final message */
+ all_fail &= rc;
+
+ switch (rc)
+ {
+ case OK: case DISCARD: code = US"250"; break;
+ case DEFER: code = US"450"; break;
+ default: code = US"550"; break;
+ }
+ if (user_msg != NULL)
+ smtp_user_msg(code, user_msg);
+ else
+ {
+ switch (rc)
+ {
+ case OK: case DISCARD:
+ msg = string_sprintf(CS msg, addr, "acceptance"); break;
+ case DEFER:
+ msg = string_sprintf(CS msg, addr, "temporary refusal"); break;
+ default:
+ msg = string_sprintf(CS msg, addr, "refusal"); break;
+ }
+ smtp_user_msg(code, msg);
+ }
+ 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);
+
+ if (rc != OK) { receive_remove_recipient(addr); c--; }
+ }
+ /* Set up final message, used if data acl gives OK */
+ smtp_reply = string_sprintf("%s id=%s message %s",
+ all_fail == FAIL ? US"550" : US"250",
+ message_id,
+ all_fail == FAIL
+ ? US"rejected for all recipients"
+ : all_pass == OK
+ ? US"accepted"
+ : US"accepted for some recipients");
+ if (recipients_count == 0)
+ {
+ message_id[0] = 0; /* Indicate no message accepted */
+ goto TIDYUP;
+ }
+ }
+ else
+ prdr_requested = FALSE;
+#endif /* EXPERIMENTAL_PRDR */
+
/* Check the recipients count again, as the MIME ACL might have changed
them. */
{
s = string_append(s, &size, &sptr, 2, US" A=", sender_host_authenticated);
if (authenticated_id != NULL)
+ {
s = string_append(s, &size, &sptr, 2, US":", authenticated_id);
+ if (log_extra_selector & LX_smtp_mailauth && authenticated_sender != NULL)
+ s = string_append(s, &size, &sptr, 2, US":", authenticated_sender);
+ }
}
+#ifdef EXPERIMENTAL_PRDR
+if (prdr_requested)
+ s = string_append(s, &size, &sptr, 1, US" PRDR");
+#endif
+
sprintf(CS big_buffer, "%d", msg_size);
s = string_append(s, &size, &sptr, 2, US" S=", big_buffer);
+/* log 8BITMIME mode announced in MAIL_FROM
+ 0 ... no BODY= used
+ 7 ... 7BIT
+ 8 ... 8BITMIME */
+if (log_extra_selector & LX_8bitmime)
+ {
+ sprintf(CS big_buffer, "%d", body_8bitmime);
+ s = string_append(s, &size, &sptr, 2, US" M8S=", big_buffer);
+ }
+
/* If an addr-spec in a message-id contains a quoted string, it can contain
any characters except " \ and CR and so in particular it can contain NL!
Therefore, make sure we use a printing-characters only version for the log.
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 */
break;
}
}
-else
- cutthrough_done = 0;
-if(smtp_reply == NULL)
+if(smtp_reply == NULL
+#ifdef EXPERIMENTAL_PRDR
+ || prdr_requested
+#endif
+ )
{
log_write(0, LOG_MAIN |
(((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) |