--- mua-wrapper
--- acl control?
+++ flag in spool file
+
+retries
+- apply to a-label or utf8 form?
+
dsn handling rfc6533
+
logging
++ - international msg
- presentation of local-part in log
- mail-time rejects get 550 mailbox unavailable
- bounces (see dsn handling)
-flag in spool file
-
++ expansions for to- and from-Alabel ? bug1567
enhanced status codes? rfc5248++
recipient_item *r = recipients_list + i;
address_item *new = deliver_make_addr(r->address, FALSE);
new->p.errors_address = r->errors_to;
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ new->p.utf8 = message_smtputf8;
+ DEBUG(D_deliver) debug_printf("utf8: %c\n", message_smtputf8 ? 'T':'F');
+#endif
if (r->pno >= 0)
new->onetime_parent = recipients_list[r->pno].address;
regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE);
#endif
+#ifdef SUPPORT_TLS
+if (!regex_UTF8) regex_UTF8 =
+ regex_must_compile(US"\\n250[\\s\\-]SMTPUTF8(\\s|\\n|$)", FALSE, TRUE);
+#endif
+
if (!regex_DSN) regex_DSN =
regex_must_compile(US"\\n250[\\s\\-]DSN(\\s|\\n|$)", FALSE, TRUE);
extern uschar *string_split_message(uschar *);
extern uschar *string_unprinting(uschar *);
#ifdef EXPERIMENTAL_INTERNATIONAL
+extern uschar *string_address_alabel_to_utf8(const uschar *, uschar **);
extern uschar *string_address_utf8_to_alabel(uschar *, uschar **, int *);
extern uschar *string_domain_alabel_to_utf8(const uschar *, uschar **);
extern uschar *string_domain_utf8_to_alabel(const uschar *, uschar **);
const pcre *regex_PRDR = NULL;
#endif
+#ifdef EXPERIMENTAL_INTERNATIONAL
+const pcre *regex_UTF8 = NULL;
+#endif
+
/* Input-reading functions for messages, so we can use special ones for
incoming TCP/IP. The defaults use stdin. We never need these for any
stand-alone tests. */
NULL, /* remove_headers */
#ifdef EXPERIMENTAL_SRS
NULL, /* srs_sender */
+#endif
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ FALSE, /* utf8 */
#endif
}
};
extern uschar *message_size_limit; /* As it says */
#ifdef EXPERIMENTAL_INTERNATIONAL
extern BOOL message_smtputf8; /* Internationalized mail handling */
+const extern pcre *regex_UTF8; /* For recognizing SMTPUTF8 settings */
#endif
extern uschar message_subdir[]; /* Subdirectory for messages */
extern uschar *message_reference; /* Reference for error messages */
#define ERRNO_MAIL4XX (-45) /* MAIL gave 4xx error */
#define ERRNO_DATA4XX (-46) /* DATA gave 4xx error */
#define ERRNO_PROXYFAIL (-47) /* Negotiation failed for proxy configured host */
-#define ERRNO_AUTHPROB (-48) /* Autheticator "other" failure */
+#define ERRNO_AUTHPROB (-48) /* Authenticator "other" failure */
+
+#ifdef EXPERIMENTAL_INTERNATIONAL
+# define ERRNO_UTF8_FWD (-49) /* target not supporting SMTPUTF8 */
+#endif
/* These must be last, so all retry deferments can easily be identified */
while (bracket_count-- > 0) if (*s++ != '>')
{
*errorptr = (s[-1] == 0)? US"'>' missing at end of address" :
- string_sprintf("malformed address A: %.32s may not follow %.*s",
+ string_sprintf("malformed address: %.32s may not follow %.*s",
s-1, s - (uschar *)mailbox - 1, mailbox);
goto PARSE_FAILED;
}
}
else
{
- *errorptr = string_sprintf("malformed address B: %.32s may not follow %.*s",
+ *errorptr = string_sprintf("malformed address: %.32s may not follow %.*s",
s, s - (uschar *)mailbox, mailbox);
goto PARSE_FAILED;
}
receive_add_recipient(recipient, -1);
/* Set the dsn flags in the recipients_list */
- if (orcpt != NULL)
- recipients_list[recipients_count-1].orcpt = orcpt;
- else
- recipients_list[recipients_count-1].orcpt = NULL;
+ recipients_list[recipients_count-1].orcpt = orcpt;
+ recipients_list[recipients_count-1].dsn_flags = flags;
- if (flags != 0)
- recipients_list[recipients_count-1].dsn_flags = flags;
- else
- recipients_list[recipients_count-1].dsn_flags = 0;
- DEBUG(D_receive) debug_printf("DSN: orcpt: %s flags: %d\n", recipients_list[recipients_count-1].orcpt, recipients_list[recipients_count-1].dsn_flags);
+ DEBUG(D_receive) debug_printf("DSN: orcpt: %s flags: %d\n",
+ recipients_list[recipients_count-1].orcpt,
+ recipients_list[recipients_count-1].dsn_flags);
}
/* The recipient was discarded */
spam_score_int = NULL;
#endif
+#if defined(EXPERIMENTAL_INTERNATIONAL) && !defined(COMPILE_UTILITY)
+message_smtputf8 = FALSE;
+#endif
+
dsn_ret = 0;
dsn_envid = NULL;
#ifdef WITH_CONTENT_SCAN
else if (Ustrncmp(p, "pam_score_int ", 14) == 0)
spam_score_int = string_copy(big_buffer + 16);
+#endif
+#if defined(EXPERIMENTAL_INTERNATIONAL) && !defined(COMPILE_UTILITY)
+ else if (Ustrncmp(p, "mtputf8", 7) == 0)
+ message_smtputf8 = TRUE;
#endif
break;
if (tls_in.ocsp) fprintf(f, "-tls_ocsp %d\n", tls_in.ocsp);
#endif
+#ifdef EXPERIMENTAL_INTERNATIONAL
+if (message_smtputf8) fprintf(f, "-smtputf8\n");
+#endif
+
/* Write the dsn flags to the spool header file */
DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_envid %s\n", dsn_envid);
if (dsn_envid != NULL) fprintf(f, "-dsn_envid %s\n", dsn_envid);
#ifdef EXPERIMENTAL_SRS
uschar *srs_sender; /* Change return path when delivering */
#endif
+ #ifdef EXPERIMENTAL_INTERNATIONAL
+ BOOL utf8; /* requires SMTPUTF8 processing */
+ #endif
} address_item_propagated;
/* Bits for the flags field below */
BOOL prdr_offered = FALSE;
BOOL prdr_active;
#endif
+#ifdef EXPERIMENTAL_INTERNATIONAL
+BOOL utf8_offered = FALSE;
+#endif
BOOL dsn_all_lasthop = TRUE;
#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
BOOL dane = FALSE;
if (prdr_offered)
{DEBUG(D_transport) debug_printf("PRDR usable\n");}
#endif
+
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ utf8_offered = esmtp
+ && addrlist->p.utf8
+ && pcre_exec(regex_UTF8, NULL, CS buffer, Ustrlen(buffer), 0,
+ PCRE_EOPT, NULL, 0) >= 0;
+#endif
}
/* For continuing deliveries down the same channel, the socket is the standard
#ifndef DISABLE_PRDR
prdr_offered = esmtp
&& pcre_exec(regex_PRDR, NULL, CS buffer, Ustrlen(CS buffer), 0,
- PCRE_EOPT, NULL, 0) >= 0
+ PCRE_EOPT, NULL, 0) >= 0
&& verify_check_given_host(&ob->hosts_try_prdr, host) == OK;
if (prdr_offered)
{DEBUG(D_transport) debug_printf("PRDR usable\n");}
#endif
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ utf8_offered = esmtp
+ && addrlist->p.utf8
+ && pcre_exec(regex_UTF8, NULL, CS buffer, Ustrlen(buffer), 0,
+ PCRE_EOPT, NULL, 0) >= 0;
+#endif
+
/* Note if the server supports DSN */
- smtp_use_dsn = esmtp && pcre_exec(regex_DSN, NULL, CS buffer, (int)Ustrlen(CS buffer), 0,
- PCRE_EOPT, NULL, 0) >= 0;
+ smtp_use_dsn = esmtp
+ && pcre_exec(regex_DSN, NULL, CS buffer, Ustrlen(CS buffer), 0,
+ PCRE_EOPT, NULL, 0) >= 0;
DEBUG(D_transport) debug_printf("use_dsn=%d\n", smtp_use_dsn);
/* Note if the response to EHLO specifies support for the AUTH extension.
setting_up = FALSE;
+#ifdef EXPERIMENTAL_INTERNATIONAL
+/* If this is an international message we need the host to speak SMTPUTF8 */
+if (addrlist->p.utf8 && !utf8_offered)
+ {
+ errno = ERRNO_UTF8_FWD;
+ goto RESPONSE_FAILED;
+ }
+#endif
+
/* If there is a filter command specified for this transport, we can now
set it up. This cannot be done until the identify of the host is known. */
}
#endif
+#ifdef EXPERIMENTAL_INTERNATIONAL
+if (addrlist->p.utf8)
+ sprintf(CS p, " SMTPUTF8"), p += 9;
+#endif
+
/* check if all addresses have lasthop flag */
/* do not send RET and ENVID if true */
-dsn_all_lasthop = TRUE;
-for (addr = first_addr;
+for (dsn_all_lasthop = TRUE, addr = first_addr;
address_count < max_rcpt && addr != NULL;
addr = addr->next)
if ((addr->dsn_flags & rf_dsnlasthop) != 1)
+ {
dsn_all_lasthop = FALSE;
+ break;
+ }
/* Add any DSN flags to the mail command */
-if ((smtp_use_dsn) && (dsn_all_lasthop == FALSE))
+if (smtp_use_dsn && !dsn_all_lasthop)
{
if (dsn_ret == dsn_ret_hdrs)
{
pending_MAIL = TRUE; /* The block starts with MAIL */
rc = smtp_write_command(&outblock, smtp_use_pipelining,
- "MAIL FROM:<%s>%s\r\n", return_path, buffer);
+ "MAIL FROM:<%s>%s\r\n", return_path, buffer);
mail_command = string_copy(big_buffer); /* Save for later error message */
switch(rc)
{
case -1: /* Transmission error */
- goto SEND_FAILED;
+ goto SEND_FAILED;
case +1: /* Block was sent */
- if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
+ if (!smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
ob->command_timeout))
- {
- if (errno == 0 && buffer[0] == '4')
{
- errno = ERRNO_MAIL4XX;
- addrlist->more_errno |= ((buffer[1] - '0')*10 + buffer[2] - '0') << 8;
+ if (errno == 0 && buffer[0] == '4')
+ {
+ errno = ERRNO_MAIL4XX;
+ addrlist->more_errno |= ((buffer[1] - '0')*10 + buffer[2] - '0') << 8;
+ }
+ goto RESPONSE_FAILED;
}
- goto RESPONSE_FAILED;
- }
- pending_MAIL = FALSE;
- break;
+ pending_MAIL = FALSE;
+ break;
}
/* Pass over all the relevant recipient addresses for this host, which are the
trusted_users = CALLER
log_selector = +received_recipients
+.ifdef SERVER
queue_only
queue_run_in_order
+.endif
smtputf8_advertise_hosts = *
begin routers
+.ifdef SERVER
+
fail_remote_domains:
driver = redirect
domains = ! +local_domains
driver = redirect
data = :blackhole:
+.else
+
+rmt:
+ driver = manualroute
+ route_data = <;[127.0.0.1]:PORT_D
+ transport = rmt_smtp
+ self = send
+
+.endif
+
# ----- Transports -----
begin transports
X-received-count: $received_count"
return_path_add
+rmt_smtp:
+ driver = smtp
+
# End
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
1999-03-02 09:44:33 10HmaX-0005vi-00 <= someone@some.domain H=(client) [127.0.0.1] P=utf8esmtp S=sss for userx@test.ex
1999-03-02 09:44:33 10HmaY-0005vi-00 <= ليهمابتكلموشعربي؟@czech.Pročprostěnemluvíčesky.com H=(client) [127.0.0.1] P=utf8esmtp S=sss for userx@test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= 他们为什么不说中文@hebrew.למההםפשוטלאמדבריםעברית.com U=CALLER P=utf8local-esmtp S=sss for usery@test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= 他们为什么不说中文@hebrew.למההםפשוטלאמדבריםעברית.com H=localhost (the.local.host.name) [127.0.0.1] P=utf8esmtp S=sss id=E10HmaZ-0005vi-00@the.local.host.name for usery@test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => usery@test.ex R=rmt T=rmt_smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbA-0005vi-00"
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
1999-03-02 09:44:33 Start queue run: pid=pppp -qq
1999-03-02 09:44:33 10HmaX-0005vi-00 => :blackhole: <userx@test.ex> R=localuser
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <userx@test.ex> R=localuser
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
-1999-03-02 09:44:33 End queue run: pid=pppp -qq
****
#
#
+# utf-8 from, -bs input and forwarding
+exim -bs -odi
+EHLO client.bh
+MAIL FROM: <他们为什么不说中文@hebrew.למההםפשוטלאמדבריםעברית.com> SMTPUTF8
+RCPT TO: <usery@test.ex>
+DATA
+Subject: test
+
+body
+.
+QUIT
+****
+#
+#
+#
killdaemon
exim -DSERVER=server -qq
****
??? 221
<<< 221 the.local.host.name closing connection
End of script
+220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-the.local.host.name Hello CALLER at client.bh\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250-SMTPUTF8\r
+250 HELP\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmaZ-0005vi-00\r
+221 the.local.host.name closing connection\r