Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 Dec 2017 16:42:39 +0000 (UTC)
From:      Mark Felder <feld@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r457706 - in head/mail/sendmail: . files
Message-ID:  <201712311642.vBVGgdMD031974@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: feld
Date: Sun Dec 31 16:42:39 2017
New Revision: 457706
URL: https://svnweb.freebsd.org/changeset/ports/457706

Log:
  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

Added:
  head/mail/sendmail/files/extrapatch-smtputf8   (contents, props changed)
  head/mail/sendmail/files/site.config.m4.smtputf8   (contents, props changed)
Modified:
  head/mail/sendmail/Makefile

Modified: head/mail/sendmail/Makefile
==============================================================================
--- head/mail/sendmail/Makefile	Sun Dec 31 16:26:46 2017	(r457705)
+++ head/mail/sendmail/Makefile	Sun Dec 31 16:42:39 2017	(r457706)
@@ -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)
@@ -101,6 +103,10 @@ EXTRA_PATCHES+=	${FILESDIR}/cyruslookup.patch
 .if ${PORT_OPTIONS:MTLS}
 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 \

Added: head/mail/sendmail/files/extrapatch-smtputf8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/mail/sendmail/files/extrapatch-smtputf8	Sun Dec 31 16:42:39 2017	(r457706)
@@ -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))
+ 	{

Added: head/mail/sendmail/files/site.config.m4.smtputf8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/mail/sendmail/files/site.config.m4.smtputf8	Sun Dec 31 16:42:39 2017	(r457706)
@@ -0,0 +1,2 @@
+APPENDDEF(`confLIBS', ` -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata')
+define(`conf_sendmail_ENVDEF', `-D_FFR_EAI')



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712311642.vBVGgdMD031974>