-/* $Cambridge: exim/src/src/acl.c,v 1.71 2007/02/06 11:16:21 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.75 2007/03/01 11:17:00 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
ACLC_BMI_OPTIN,
#endif
ACLC_CONDITION,
+ ACLC_CONTINUE,
ACLC_CONTROL,
#ifdef WITH_CONTENT_SCAN
ACLC_DECODE,
#endif
ACLC_VERIFY };
-/* ACL conditions/modifiers: "delay", "control", "endpass", "message",
-"log_message", "log_reject_target", "logwrite", and "set" are modifiers that
-look like conditions but always return TRUE. They are used for their side
-effects. */
+/* ACL conditions/modifiers: "delay", "control", "continue", "endpass",
+"message", "log_message", "log_reject_target", "logwrite", and "set" are
+modifiers that look like conditions but always return TRUE. They are used for
+their side effects. */
static uschar *conditions[] = {
US"acl",
US"bmi_optin",
#endif
US"condition",
+ US"continue",
US"control",
#ifdef WITH_CONTENT_SCAN
US"decode",
CONTROL_FAKEREJECT,
CONTROL_NO_MULTILINE,
CONTROL_NO_PIPELINING,
- CONTROL_NO_DELAY_FLUSH
+ CONTROL_NO_DELAY_FLUSH,
+ CONTROL_NO_CALLOUT_FLUSH
};
/* ACL control names; keep in step with the table above! This list is used for
US"fakereject",
US"no_multiline",
US"no_pipelining",
- US"no_delay_flush"
+ US"no_delay_flush",
+ US"no_callout_flush"
};
/* Flags to indicate for which conditions/modifiers a string expansion is done
TRUE, /* bmi_optin */
#endif
TRUE, /* condition */
+ TRUE, /* continue */
TRUE, /* control */
#ifdef WITH_CONTENT_SCAN
TRUE, /* decode */
TRUE, /* bmi_optin */
#endif
FALSE, /* condition */
+ TRUE, /* continue */
TRUE, /* control */
#ifdef WITH_CONTENT_SCAN
FALSE, /* decode */
FALSE /* verify */
};
-/* Bit map vector of which conditions are not allowed at certain times. For
-each condition, there's a bitmap of dis-allowed times. For some, it is easier
-to specify the negation of a small number of allowed times. */
+/* Bit map vector of which conditions and modifiers are not allowed at certain
+times. For each condition, there's a bitmap of dis-allowed times. For some, it
+is easier to specify the negation of a small number of allowed times. */
static unsigned int cond_forbids[] = {
0, /* acl */
0, /* condition */
+ 0, /* continue */
+
/* Certain types of control are always allowed, so we let it through
always and check in the control processing itself. */
(1<<ACL_WHERE_NOTSMTP_START),
(1<<ACL_WHERE_NOTSMTP)| /* no_delay_flush */
+ (1<<ACL_WHERE_NOTSMTP_START),
+
+ (1<<ACL_WHERE_NOTSMTP)| /* no_callout_flush */
(1<<ACL_WHERE_NOTSMTP_START)
};
{ US"caselower_local_part", CONTROL_CASELOWER_LOCAL_PART, FALSE },
{ US"enforce_sync", CONTROL_ENFORCE_SYNC, FALSE },
{ US"freeze", CONTROL_FREEZE, TRUE },
+ { US"no_callout_flush", CONTROL_NO_CALLOUT_FLUSH, FALSE },
{ US"no_delay_flush", CONTROL_NO_DELAY_FLUSH, FALSE },
{ US"no_enforce_sync", CONTROL_NO_ENFORCE_SYNC, FALSE },
{ US"no_multiline_responses", CONTROL_NO_MULTILINE, FALSE },
callout_overall, callout_connect, se_mailfrom, pm_mailfrom, NULL);
HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
+ *basic_errno = addr2.basic_errno;
*log_msgptr = addr2.message;
*user_msgptr = (addr2.user_message != NULL)?
addr2.user_message : addr2.message;
- *basic_errno = addr2.basic_errno;
+
+ /* Allow details for temporary error if the address is so flagged. */
+ if (testflag((&addr2), af_pass_message)) acl_temp_details = TRUE;
/* Make $address_data visible */
deliver_address_data = addr2.p.address_data;
*log_msgptr = string_sprintf("invalid \"condition\" value \"%s\"", arg);
break;
+ case ACLC_CONTINUE: /* Always succeeds */
+ break;
+
case ACLC_CONTROL:
control_type = decode_control(arg, &p, where, log_msgptr);
disable_delay_flush = TRUE;
break;
+ case CONTROL_NO_CALLOUT_FLUSH:
+ disable_callout_flush = TRUE;
+ break;
+
case CONTROL_FAKEDEFER:
case CONTROL_FAKEREJECT:
fake_response = (control_type == CONTROL_FAKEDEFER) ? DEFER : FAIL;
/* Before giving a response, take a look at the length of any user message, and
split it up into multiple lines if possible. */
-if (*user_msgptr != NULL && Ustrlen(*user_msgptr) > 75)
- {
- uschar *s = *user_msgptr = string_copy(*user_msgptr);
- uschar *ss = s;
-
- for (;;)
- {
- int i = 0;
- while (i < 75 && *ss != 0 && *ss != '\n') ss++, i++;
- if (*ss == 0) break;
- if (*ss == '\n')
- s = ++ss;
- else
- {
- uschar *t = ss + 1;
- uschar *tt = NULL;
- while (--t > s + 35)
- {
- if (*t == ' ')
- {
- if (t[-1] == ':') { tt = t; break; }
- if (tt == NULL) tt = t;
- }
- }
-
- if (tt == NULL) /* Can't split behind - try ahead */
- {
- t = ss + 1;
- while (*t != 0)
- {
- if (*t == ' ' || *t == '\n')
- { tt = t; break; }
- t++;
- }
- }
-
- if (tt == NULL) break; /* Can't find anywhere to split */
- *tt = '\n';
- s = ss = tt+1;
- }
- }
- }
+*user_msgptr = string_split_message(*user_msgptr);
+if (fake_response != OK)
+ fake_response_text = string_split_message(fake_response_text);
return rc;
}