mail/sendmail: Add port option for SMTPUTF8 support, enabled by default.

Postfix has had support for quite some time, compiled in by default
http://www.postfix.org/SMTPUTF8_README.html

Exim has support but it's not a default build option
http://www.exim.org/exim-html-current/doc/html/spec_html/ch-internationalisation.html

Sendmail had no support until Arnt produced this patch.

As far as commercial access to SMTPUTF8 email goes:

GMail has support for SMTPUTF8 for 3 years
Outlook.com will have support shortly

The world is moving forward with SMPTUTF8 and if it does not get wider
distribution it will restrict the ability to self-host email as the only
solution to send and receive email from these users will be to use a
commercial cloud-hosted email platform.

This patch is a no-op unless you are sending mail that requires the
SMTPUTF8 extension. If you are running a Sendmail server and you did not
have this patch you would have received errors and the messages would
have been undeliverable.

More info: http://rant.gulbrandsen.priv.no/eai/one-minute-guide

PR:		224452
Reviewed by:	Gregory Shapiro, Claus Assmann (private mails from Arnt)
Obtained from:	Arnt Gulbrandsen
Sponsored by:	CNNIC
This commit is contained in:
Mark Felder 2017-12-31 16:42:39 +00:00
parent 642b5e5454
commit b7664d180a
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=457706
3 changed files with 611 additions and 3 deletions

View file

@ -2,7 +2,7 @@
PORTNAME= sendmail
PORTVERSION= 8.15.2
PORTREVISION= 3
PORTREVISION= 4
CATEGORIES= mail ipv6
MASTER_SITES= ftp://ftp.sendmail.org/pub/sendmail/
PKGNAMESUFFIX?= ${TLS_SUFFIX}${SASL_SUFFIX}${LDAP_SUFFIX}${BDB_SUFFIX}${PKGNAMESUFFIX2}
@ -46,9 +46,9 @@ BASEMAIL= /usr/libexec/sendmail/sendmail
MILTER_SOVER?= 6
OPTIONS_DEFINE?= SHMEM SEM LA NIS IPV6 TLS SASL SASLAUTHD LDAP BDB \
GDBM SOCKETMAP CYRUSLOOKUP BLACKLISTD \
GDBM SOCKETMAP CYRUSLOOKUP BLACKLISTD SMTPUTF8 \
PICKY_HELO_CHECK MILTER DOCS
OPTIONS_DEFAULT?= SHMEM SEM LA NIS TLS SASL SASLAUTHD BDB1 \
OPTIONS_DEFAULT?= SHMEM SEM LA NIS TLS SASL SASLAUTHD BDB1 SMTPUTF8 \
PICKY_HELO_CHECK MILTER
NO_OPTIONS_SORT=yes
SHMEM_DESC= System V shared memory support
@ -62,6 +62,7 @@ BLACKLISTD_DESC= Enable blacklistd support
CYRUSLOOKUP_DESC= Enable cyruslookup feature
PICKY_HELO_CHECK_DESC= Enable picky HELO check
MILTER_DESC= Enable milter support
SMTPUTF8_DESC= Enable unicode address support
TLS_USES= ssl
SASL_LIB_DEPENDS= libsasl2.so:security/cyrus-sasl2
@ -70,6 +71,7 @@ LDAP_USE= OPENLDAP=yes
BDB_USES= bdb
GDBM_LIB_DEPENDS= libgdbm.so:databases/gdbm
GDBM_CONFIGURE_WITH= compat
SMTPUTF8_LIB_DEPENDS= libidn2.so:dns/libidn2 libicui18n.so:devel/icu
.include <bsd.port.options.mk>
.if ${PORT_OPTIONS:MSHMEM} && !defined(BUILDING_INDEX)
@ -102,6 +104,10 @@ EXTRA_PATCHES+= ${FILESDIR}/cyruslookup.patch
TLS_SUFFIX?= +tls
CONFLICTS+= sendmail-ldap-8.* sendmail-sasl2-8.*
.endif
.if ${PORT_OPTIONS:MSMTPUTF8}
EXTRA_PATCHES+= ${FILESDIR}/extrapatch-smtputf8
SITE+= ${FILESDIR}/site.config.m4.smtputf8
.endif
MAKE_PKGNAMES= for i in "" +tls; do \
for j in "" +sasl2; do \

View file

@ -0,0 +1,600 @@
diff --git a/sendmail/conf.c b/sendmail/conf.c
index c73334e..28328e6 100644
--- sendmail/conf.c.orig
+++ sendmail/conf.c
@@ -314,6 +314,9 @@ setdefaults(e)
e->e_xfqgrp = NOQGRP;
e->e_xfqdir = NOQDIR;
e->e_ctime = curtime();
+#if _FFR_EAI
+ e->e_smtputf8 = false;
+#endif
SevenBitInput = false; /* option 7 */
MaxMciCache = 1; /* option k */
MciCacheTimeout = 5 MINUTES; /* option K */
@@ -5746,6 +5749,9 @@ char *CompileOptions[] =
"DNSMAP",
# endif
#endif
+#if _FFR_EAI
+ "EAI",
+#endif
#if EGD
"EGD",
#endif
@@ -6590,3 +6596,6 @@ char *FFRCompileOptions[] =
NULL
};
+#if _FFR_EAI && _FFR_EIGHT_BIT_ADDR_OK
+#error "Cannot enable both of these FFRs"
+#endif
diff --git a/sendmail/domain.c b/sendmail/domain.c
index 4d1b92d..adaa6ac 100644
--- sendmail/domain.c.orig
+++ sendmail/domain.c
@@ -13,6 +13,9 @@
#include <sendmail.h>
#include "map.h"
+#if _FFR_EAI
+#include <unicode/uidna.h>
+#endif
#if NAMED_BIND
SM_RCSID("@(#)$Id: domain.c,v 8.205 2013-11-22 20:51:55 ca Exp $ (with name server)")
@@ -236,6 +239,26 @@ getmxrr(host, mxhosts, mxprefs, droplocalhost, rcode, tryfallback, pttl)
if (host[0] == '[')
goto punt;
+#if _FFR_EAI
+ if (!addr_is_ascii(host))
+ {
+ char buf[1024];
+ UErrorCode error = U_ZERO_ERROR;
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ UIDNA *idna;
+ int anl;
+
+ idna = uidna_openUTS46(UIDNA_NONTRANSITIONAL_TO_ASCII, &error);
+ anl = uidna_nameToASCII_UTF8(idna,
+ host, strlen(host),
+ buf, sizeof(buf) - 1,
+ &info,
+ &error);
+ uidna_close(idna);
+ host = sm_rpool_strdup_x(CurEnv->e_rpool, buf);
+ }
+#endif /* _FFR_EAI */
+
/*
** If we don't have MX records in our host switch, don't
** try for MX records. Note that this really isn't "right",
diff --git a/sendmail/err.c b/sendmail/err.c
index 0594eb9..67d0d09 100644
--- sendmail/err.c.orig
+++ sendmail/err.c
@@ -1010,15 +1010,23 @@ fmtmsg(eb, to, num, enhsc, eno, fmt, ap)
(void) sm_strlcpyn(eb, spaceleft, 2,
shortenstring(to, MAXSHORTSTR), "... ");
spaceleft -= strlen(eb);
+#if _FFR_EAI
+ eb += strlen(eb);
+#else
while (*eb != '\0')
*eb++ &= 0177;
+#endif
}
/* output the message */
(void) sm_vsnprintf(eb, spaceleft, fmt, ap);
spaceleft -= strlen(eb);
+#if _FFR_EAI
+ eb += strlen(eb);
+#else
while (*eb != '\0')
*eb++ &= 0177;
+#endif
/* output the error code, if any */
if (eno != 0)
diff --git a/sendmail/main.c b/sendmail/main.c
index 38eebbf..43e17a5 100644
--- sendmail/main.c.orig
+++ sendmail/main.c
@@ -1854,6 +1854,9 @@ main(argc, argv, envp)
/* MIME message/xxx subtypes that can be treated as messages */
setclass('s', "rfc822");
+#ifdef _FFR_EAI
+ setclass('s', "global");
+#endif
/* MIME Content-Transfer-Encodings that can be encoded */
setclass('e', "7bit");
diff --git a/sendmail/parseaddr.c b/sendmail/parseaddr.c
index 2adb39c..9ab0729 100644
--- sendmail/parseaddr.c.orig
+++ sendmail/parseaddr.c
@@ -273,12 +273,14 @@ invalidaddr(addr, delimptr, isrcpt)
}
for (; *addr != '\0'; addr++)
{
+#ifndef _FFR_EAI
if (!EightBitAddrOK && (*addr & 0340) == 0200)
{
setstat(EX_USAGE);
result = true;
*addr = BAD_CHAR_REPLACEMENT;
}
+#endif
if (++len > MAXNAME - 1)
{
char saved = *addr;
@@ -350,7 +352,7 @@ hasctrlchar(addr, isrcpt, complain)
}
result = "too long";
}
- if (!EightBitAddrOK && !quoted && (*addr < 32 || *addr == 127))
+ if (!quoted && ((unsigned char)*addr < 32 || *addr == 127))
{
result = "non-printable character";
*addr = BAD_CHAR_REPLACEMENT;
@@ -368,6 +370,7 @@ hasctrlchar(addr, isrcpt, complain)
break;
}
}
+#ifndef _FFR_EAI
if (!EightBitAddrOK && (*addr & 0340) == 0200)
{
setstat(EX_USAGE);
@@ -375,6 +378,7 @@ hasctrlchar(addr, isrcpt, complain)
*addr = BAD_CHAR_REPLACEMENT;
continue;
}
+#endif
}
if (quoted)
result = "unbalanced quote"; /* unbalanced quote */
diff --git a/sendmail/queue.c b/sendmail/queue.c
index a323301..95344d3 100644
--- sendmail/queue.c.orig
+++ sendmail/queue.c
@@ -665,6 +665,10 @@ queueup(e, announce, msync)
*p++ = 'n';
if (bitset(EF_SPLIT, e->e_flags))
*p++ = 's';
+#if _FFR_EAI
+ if (e->e_smtputf8)
+ *p++ = 'e';
+#endif
*p++ = '\0';
if (buf[0] != '\0')
(void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "F%s\n", buf);
@@ -4285,6 +4289,12 @@ readqf(e, openonly)
case 'w': /* warning sent */
e->e_flags |= EF_WARNING;
break;
+
+#if _FFR_EAI
+ case 'e': /* message requires EAI */
+ e->e_smtputf8 = true;
+ break;
+#endif /* _FFR_EAI */
}
}
break;
@@ -4550,6 +4560,23 @@ readqf(e, openonly)
/* other checks? */
#endif /* _FFR_QF_PARANOIA */
+#if _FFR_EAI
+ /*
+ ** If this message originates from something other than
+ ** srvrsmtp.c, then it might use UTF8 addresses but not be
+ ** marked. We'll just add the mark so we're sure that it
+ ** either can be delivered or will be returned.
+ */
+ if (!e->e_smtputf8) {
+ ADDRESS *q;
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ if (!addr_is_ascii(q->q_paddr) && !e->e_smtputf8)
+ e->e_smtputf8 = true;
+ if (!addr_is_ascii(e->e_from.q_paddr) && !e->e_smtputf8)
+ e->e_smtputf8 = true;
+ }
+#endif /* _FFR_EAI */
+
/* possibly set ${dsn_ret} macro */
if (bitset(EF_RET_PARAM, e->e_flags))
{
diff --git a/sendmail/recipient.c b/sendmail/recipient.c
index 3fad957..09eac64 100644
--- sendmail/recipient.c.orig
+++ sendmail/recipient.c
@@ -508,6 +508,11 @@ recipient(new, sendq, aliaslevel, e)
p = e->e_from.q_mailer->m_addrtype;
if (p == NULL)
p = "rfc822";
+#ifdef _FFR_EAI
+ if (sm_strcasecmp(p, "rfc822") == 0 &&
+ !addr_is_ascii(q->q_user))
+ p = "utf-8";
+#endif
if (sm_strcasecmp(p, "rfc822") != 0)
{
(void) sm_snprintf(frbuf, sizeof(frbuf), "%s; %.800s",
diff --git a/sendmail/savemail.c b/sendmail/savemail.c
index 6de8f2f..8a9df36 100644
--- sendmail/savemail.c.orig
+++ sendmail/savemail.c
@@ -744,6 +744,34 @@ returntosender(msg, returnq, flags, e)
return ret;
}
+
+/*
+** DSNTYPENAME -- Returns the DSN name of the addrtype for this address
+**
+** Sendmail's addrtypes are largely in different universes, and
+** 'fred' may be a valid address in different addrtype
+** universes.
+**
+** EAI extends the rfc822 universe rather than introduce a new
+** universe. Because of that, sendmail uses the rfc822 addrtype,
+** but names it utf-8 when the EAI DSN extension requires that.
+*/
+
+const char *
+dsntypename(addrtype, addr)
+ const char * addrtype;
+ const char * addr;
+{
+ if (sm_strcasecmp(addrtype, "rfc822") != 0)
+ return addrtype;
+#ifdef _FFR_EAI
+ if (!addr_is_ascii(addr))
+ return "utf-8";
+#endif
+ return "rfc822";
+}
+
+
/*
** ERRBODY -- output the body of an error message.
**
@@ -1082,7 +1110,13 @@ errbody(mci, e, separator)
(void) sm_strlcpyn(buf, sizeof(buf), 2, "--", e->e_msgboundary);
if (!putline("", mci) ||
!putline(buf, mci) ||
+#ifdef _FFR_EAI
+ !putline(e->e_parent->e_smtputf8
+ ? "Content-Type: message/global-delivery-status"
+ : "Content-Type: message/delivery-status", mci) ||
+#else
!putline("Content-Type: message/delivery-status", mci) ||
+#endif
!putline("", mci))
goto writeerr;
@@ -1223,7 +1257,8 @@ errbody(mci, e, separator)
(void) sm_snprintf(actual,
sizeof(actual),
"%s; %.700s@%.100s",
- p, q->q_user,
+ dsntypename(p, q->q_user),
+ q->q_user,
MyHostName);
}
else
@@ -1231,7 +1266,8 @@ errbody(mci, e, separator)
(void) sm_snprintf(actual,
sizeof(actual),
"%s; %.800s",
- p, q->q_user);
+ dsntypename(p, q->q_user),
+ q->q_user);
}
}
@@ -1248,6 +1284,21 @@ errbody(mci, e, separator)
actual);
}
+#ifdef _FFR_EAI
+ if (sm_strncasecmp("rfc822;", q->q_finalrcpt, 7) == 0 &&
+ !addr_is_ascii(q->q_user)) {
+ char utf8rcpt[1024];
+ char * a;
+ a = strchr(q->q_finalrcpt, ';');
+ while(*a == ';' || *a == ' ')
+ a++;
+ sm_snprintf(utf8rcpt, 1023,
+ "utf-8; %.800s", a);
+ q->q_finalrcpt = sm_rpool_strdup_x(e->e_rpool,
+ utf8rcpt);
+ }
+#endif
+
if (q->q_finalrcpt != NULL)
{
(void) sm_snprintf(buf, sizeof(buf),
@@ -1373,9 +1424,21 @@ errbody(mci, e, separator)
if (!putline(buf, mci))
goto writeerr;
+#ifdef _FFR_EAI
+ if (e->e_parent->e_smtputf8)
+ (void) sm_strlcpyn(buf, sizeof(buf), 2,
+ "Content-Type: message/global",
+ sendbody ? "" : "-headers");
+ else
+ (void) sm_strlcpyn(buf, sizeof(buf), 2,
+ "Content-Type: ",
+ sendbody ? "message/rfc822"
+ : "text/rfc822-headers");
+#else
(void) sm_strlcpyn(buf, sizeof(buf), 2, "Content-Type: ",
sendbody ? "message/rfc822"
: "text/rfc822-headers");
+#endif
if (!putline(buf, mci))
goto writeerr;
diff --git a/sendmail/sendmail.h b/sendmail/sendmail.h
index b2d0211..63a2378 100644
--- sendmail/sendmail.h.orig
+++ sendmail/sendmail.h
@@ -781,8 +781,13 @@ MCI
#else
# define MCIF_NOTSTICKY 0
#endif
+#if _FFR_EAI
+#define MCIF_EAI 0x40000000 /* SMTPUTF8 supported */
+#else
+#define MCIF_EAI 0x00000000 /* for MCIF_EXTENS */
+#endif /* _FFR_EAI */
-#define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT | MCIF_TLS | MCIF_AUTH2)
+#define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT | MCIF_TLS | MCIF_AUTH2 | MCIF_EAI)
/* states */
#define MCIS_CLOSED 0 /* no traffic on this connection */
@@ -921,6 +926,9 @@ struct envelope
ADDRESS e_from; /* the person it is from */
char *e_sender; /* e_from.q_paddr w comments stripped */
char **e_fromdomain; /* the domain part of the sender */
+#if _FFR_EAI
+ bool e_smtputf8; /* whether the sender demanded SMTPUTF8 */
+#endif
ADDRESS *e_sendqueue; /* list of message recipients */
ADDRESS *e_errorqueue; /* the queue for error responses */
@@ -1928,6 +1936,9 @@ struct termescape
#define D_CANONREQ 'c' /* canonification required (cf) */
#define D_IFNHELO 'h' /* use if name for HELO */
#define D_FQMAIL 'f' /* fq sender address required (cf) */
+#if _FFR_EAI
+#define D_EAI 'I' /* EAI supported */
+#endif
#define D_FQRCPT 'r' /* fq recipient address required (cf) */
#define D_SMTPS 's' /* SMTP over SSL (smtps) */
#define D_UNQUALOK 'u' /* unqualified address is ok (cf) */
@@ -2355,7 +2366,7 @@ EXTERN bool ForkQueueRuns; /* fork for each job when running the queue */
EXTERN bool FromFlag; /* if set, "From" person is explicit */
EXTERN bool FipsMode;
EXTERN bool GrabTo; /* if set, get recipients from msg */
-EXTERN bool EightBitAddrOK; /* we'll let 8-bit addresses through */
+EXTERN bool EightBitAddrOK; /* we'll let 8-bit addresses through */
EXTERN bool HasEightBits; /* has at least one eight bit input byte */
EXTERN bool HasWildcardMX; /* don't use MX records when canonifying */
EXTERN bool HoldErrs; /* only output errors to transcript */
@@ -2855,6 +2866,10 @@ extern bool xtextok __P((char *));
extern int xunlink __P((char *));
extern char *xuntextify __P((char *));
+#if _FFR_EAI
+extern bool addr_is_ascii __P((const char *));
+#endif
+
#if _FFR_RCPTFLAGS
extern bool newmodmailer __P((ADDRESS *, int));
#endif
diff --git a/sendmail/srvrsmtp.c b/sendmail/srvrsmtp.c
index b05348d..91e6956 100644
--- sendmail/srvrsmtp.c.orig
+++ sendmail/srvrsmtp.c
@@ -65,6 +65,9 @@ static bool NotFirstDelivery = false;
#define SRV_REQ_AUTH 0x0400 /* require AUTH */
#define SRV_REQ_SEC 0x0800 /* require security - equiv to AuthOptions=p */
#define SRV_TMP_FAIL 0x1000 /* ruleset caused a temporary failure */
+#if _FFR_EAI
+# define SRV_OFFER_EAI 0x2000 /* offer SMTPUTF* */
+#endif
static unsigned int srvfeatures __P((ENVELOPE *, char *, unsigned int));
@@ -122,6 +125,29 @@ extern ENVELOPE BlankEnvelope;
#define SKIP_SPACE(s) while (isascii(*s) && isspace(*s)) \
(s)++
+#if _FFR_EAI
+/*
+** ADDR_IS_ASCII -- check whether an address is 100% printable ASCII
+**
+** Parameters:
+** a -- an address (or other string)
+**
+** Returns:
+** TRUE if a is non-NULL and points to only printable ASCII
+** FALSE if a is NULL and points to printable ASCII
+** FALSE if a is non-NULL and points to something containing 8-bittery
+*/
+
+bool
+addr_is_ascii(a)
+ const char * a;
+{
+ while (a != NULL && *a != '\0' && *a >= ' ' && (unsigned char)*a < 127)
+ a++;
+ return (a != NULL && *a == '\0');
+}
+#endif
+
/*
** PARSE_ESMTP_ARGS -- parse EMSTP arguments (for MAIL, RCPT)
**
@@ -722,10 +748,21 @@ do \
#else
# define auth_active false
#endif
+#ifdef _FFR_EAI
+#define GET_PROTOCOL() \
+ (e->e_smtputf8 \
+ ? (auth_active \
+ ? (tls_active ? "UTF8SMTPSA" : "UTF8SMTPA") \
+ : (tls_active ? "UTF8SMTPS" : "UTF8SMTP")) \
+ : (auth_active \
+ ? (tls_active ? "ESMTPSA" : "ESMTPA") \
+ : (tls_active ? "ESMTPS" : "ESMTP")))
+#else
#define GET_PROTOCOL() \
(auth_active \
? (tls_active ? "ESMTPSA" : "ESMTPA") \
: (tls_active ? "ESMTPS" : "ESMTP"))
+#endif
static bool SevenBitInput_Saved; /* saved version of SevenBitInput */
@@ -898,6 +935,9 @@ smtp(nullserver, d_flags, e)
| (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
: SRV_VRFY_CLT)
#endif /* STARTTLS */
+#if _FFR_EAI
+ | SRV_OFFER_EAI
+#endif /* _FFR_EAI */
;
if (nullserver == NULL)
{
@@ -2523,6 +2563,10 @@ smtp(nullserver, d_flags, e)
if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
message("250-DSN");
#endif /* DSN */
+#if _FFR_EAI
+ if (bitset(SRV_OFFER_EAI, features))
+ message("250-SMTPUTF8");
+#endif /* _FFR_EAI */
if (bitset(SRV_OFFER_ETRN, features))
message("250-ETRN");
#if SASL
@@ -2696,6 +2740,18 @@ smtp(nullserver, d_flags, e)
if (Errors > 0)
sm_exc_raisenew_x(&EtypeQuickAbort, 1);
+#if _FFR_EAI
+ if (e->e_smtputf8) {
+ protocol = GET_PROTOCOL();
+ macdefine(&e->e_macro, A_PERM, 'r', protocol);
+ }
+ /* UTF8 addresses are only legal with SMTPUTF8 */
+ if (!e->e_smtputf8 && !addr_is_ascii(e->e_from.q_paddr)) {
+ usrerr("553 5.6.7 That address requires SMTPUTF8");
+ sm_exc_raisenew_x(&EtypeQuickAbort, 1);
+ }
+#endif
+
#if SASL
# if _FFR_AUTH_PASSING
/* set the default AUTH= if the sender didn't */
@@ -2933,6 +2989,13 @@ smtp(nullserver, d_flags, e)
usrerr("501 5.0.0 Missing recipient");
goto rcpt_done;
}
+#if _FFR_EAI
+ if (!e->e_smtputf8 && !addr_is_ascii(a->q_paddr))
+ {
+ usrerr("553 5.6.7 Address requires SMTPUTF8");
+ goto rcpt_done;
+ }
+#endif
if (delimptr != NULL && *delimptr != '\0')
*delimptr++ = '\0';
@@ -4820,6 +4883,17 @@ mail_esmtp_args(a, kp, vp, e)
/* XXX: check whether more characters follow? */
}
+#if _FFR_EAI
+ else if (sm_strcasecmp(kp, "smtputf8") == 0)
+ {
+ if (!bitset(SRV_OFFER_EAI, e->e_features))
+ {
+ usrerr("504 5.7.0 Sorry, SMTPUTF8 not supported/enabled");
+ /* NOTREACHED */
+ }
+ e->e_smtputf8 = true;
+ }
+#endif
else
{
usrerr("555 5.5.4 %s parameter unrecognized", kp);
@@ -5174,6 +5248,9 @@ static struct
{ 'C', SRV_REQ_SEC },
{ 'D', SRV_OFFER_DSN },
{ 'E', SRV_OFFER_ETRN },
+#if _FFR_EAI
+ { 'I', SRV_OFFER_EAI },
+#endif
{ 'L', SRV_REQ_AUTH },
#if PIPELINING
# if _FFR_NO_PIPE
diff --git a/sendmail/usersmtp.c b/sendmail/usersmtp.c
index 24d38ee..cbc6bb7 100644
--- sendmail/usersmtp.c.orig
+++ sendmail/usersmtp.c
@@ -465,6 +465,10 @@ helo_options(line, firstline, m, mci, e)
mci->mci_flags |= MCIF_PIPELINED;
else if (sm_strcasecmp(line, "verb") == 0)
mci->mci_flags |= MCIF_VERB;
+#if _FFR_EAI
+ else if (sm_strcasecmp(line, "smtputf8") == 0)
+ mci->mci_flags |= MCIF_EAI;
+#endif /* _FFR_EAI */
#if STARTTLS
else if (sm_strcasecmp(line, "starttls") == 0)
mci->mci_flags |= MCIF_TLS;
@@ -2027,6 +2031,19 @@ smtpmailfrom(m, mci, e)
return EX_TEMPFAIL;
}
+#if _FFR_EAI
+ /*
+ ** Abort right away if the message needs SMTPUTF8 and the
+ ** server does not advertise SMTPUTF8.
+ */
+
+ if (e->e_smtputf8 && !bitset(MCIF_EAI, mci->mci_flags)) {
+ usrerrenh("5.6.7", "%s does not support SMTPUTF8", CurHostName);
+ mci_setstat(mci, EX_NOTSTICKY, "5.6.7", NULL);
+ return EX_DATAERR;
+ }
+#endif /* _FFR_EAI */
+
/* set up appropriate options to include */
if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
{
@@ -2040,6 +2057,14 @@ smtpmailfrom(m, mci, e)
bufp = optbuf;
}
+#if _FFR_EAI
+ if (e->e_smtputf8) {
+ (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp),
+ " SMTPUTF8");
+ bufp += strlen(bufp);
+ }
+#endif /* _FFR_EAI */
+
bodytype = e->e_bodytype;
if (bitset(MCIF_8BITMIME, mci->mci_flags))
{

View file

@ -0,0 +1,2 @@
APPENDDEF(`confLIBS', ` -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata')
define(`conf_sendmail_ENVDEF', `-D_FFR_EAI')