mail-mta/netqmail: Add SMTPUTF8 support for qmail

SMTPUTF8 (RFCs 6531 and 6532, plus several that aren't relevant to qmail)
allows using unencoded UTF8 almost everywhere in email, including in
localparts, domains, subjects and message bodies.

Thanks to cnnic.cn for sponsoring this work.

(cherry picked from commit 5116b83a9bf93f59fb7b7d3fcd286f7b2c4da438)
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
This commit is contained in:
Arnt Gulbrandsen
2016-11-15 14:20:37 +00:00
committed by Robin H. Johnson
parent 7904c4ff51
commit 656ae3db88
3 changed files with 426 additions and 0 deletions

View File

@@ -5,3 +5,4 @@ DIST netqmail-1.06.tar.gz 260941 SHA256 8e7d98d15211fc9f9c28109e942e2268f42a6672
DIST qmail-103.patch 2104 SHA256 4cad53c7a6628a600c74c36bfee327db5052ca24c222d4013e4dfcd7f427653d SHA512 b81062bb0b0023f474c0b6af40601926e1c04ad395de480d114809e48a8060c06d99bdbdeb6f44d9e24ae1acedabb094b979193d305371aed958f18fc6eee354 WHIRLPOOL 5785684b98b9d9732ed14aa1b53910746bd09aa93514e0e6ef3d74831c3df8ed0a55f257057488f34a3d462e485b7a4417ed255f66abaff6dd63d881b9230063
DIST qmail-spp-0.42.tar.gz 18689 SHA256 1518e7e82d10fbbb8ecc520f51daf503edeb9c3a9fb935be65a8185e7b53808d SHA512 03449862886a0ca20fbadab4c94b34b55d185f8df3261bd68aea99e9ded9edfab4477c6b38a8e0295e9b38b0045615da8b1a906a458f28745eadd3c4d882bcbf WHIRLPOOL 2f8525bb264fbec4b057bad6d92968e29085fdf10b8538b8e572d81ea8793e74c07c6093d0cc2a34de00b629e797b048007b30e3845dce76829037fdb44f527c
DIST vu555316.patch 617 SHA256 cc7b2876ecb183fe55c280404c1c825a6bd1f6ccc87db67e7cfc8bc6336f9b0f SHA512 5d7810360e5eaa8e8ee141fe92c765d9458aa12198a8d0ac702e0630e08d060ad4a1d33690d434f20f5aff79eb200cd8173bebc334c411e340c0198b5d8d1a65 WHIRLPOOL 2564d5622576b89918e247de5dd830011e8ef18a50fd03e6f48e98ebf4a53db2f4994eb0fb22a76c4cd0cbb35b457ac2a5507e05159130a72685866137c5ebc1
DIST qmail-smtputf8.patch 6693 SHA256 cf3a802d439fe53e9cecbeb82a6ce6ff5c71b5fcd0b053eac5a19df918724cfa SHA512 8cafdf1a4f1fd41e6b11ee2abddac5c3da4a1d2ab17b5d3847433875a91f867a26eb358ae8c41791f1e77758e5a2c311134a286d888ccd23fbede6d9f0b475c4 WHIRLPOOL 36d2a822cf42efbe34e0e95da6e171a3394c049cfbcf2a3b68efe789b4199f00fcdb942d1e93268283a4eec15ad3ead7a58df31a327ade517c218fb18f8a7801

View File

@@ -0,0 +1,242 @@
This patch adds EAI support to qmail; EAI allows UTF8 almost everywhere in
email.
Thanks for CNNIC for sponsoring this work.
--- /dev/null
+++ netqmail-1.06/Makefile
@@ -1446,7 +1446,7 @@ substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
- str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib`
+ str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` -lidn2
qmail-remote.0: \
qmail-remote.8
--- /dev/null
+++ netqmail-1.06/qmail-remote.c
@@ -2,6 +2,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <idn2.h>
#include "sig.h"
#include "stralloc.h"
#include "substdio.h"
@@ -42,6 +43,7 @@
stralloc routes = {0};
struct constmap maproutes;
stralloc host = {0};
+stralloc asciihost = {0};
stralloc sender = {0};
saa reciplist = {0};
@@ -53,12 +55,13 @@
# include "tls.h"
# include "ssl_timeoutio.h"
# include <openssl/x509v3.h>
-# define EHLO 1
int tls_init();
const char *ssl_err_str = 0;
#endif
+# define EHLO 1
+
void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
@@ -156,6 +159,7 @@
substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf);
stralloc smtptext = {0};
+stralloc firstpart = {0};
void get(ch)
char *ch;
@@ -308,6 +312,8 @@
int r;
char ch;
+ substdio_put(&smtpto,firstpart.s,firstpart.len);
+
for (;;) {
r = substdio_get(&ssin,&ch,1);
if (r == 0) break;
@@ -518,6 +524,88 @@
stralloc recip = {0};
+int containsutf8(p, l) unsigned char * p; int l;
+{
+ int i = 0;
+ while (i<l)
+ if(p[i++] > 127) return 1;
+ return 0;
+}
+
+int utf8message;
+
+void checkutf8message()
+{
+ int pos;
+ int i;
+ int r;
+ char ch;
+ int state;
+
+ if (containsutf8(sender.s, sender.len)) { utf8message = 1; return; }
+ for (i = 0;i < reciplist.len;++i)
+ if (containsutf8(reciplist.sa[i].s, reciplist.sa[i].len)) {
+ utf8message = 1;
+ return;
+ }
+
+ state = 0;
+ pos = 0;
+ for (;;) {
+ r = substdio_get(&ssin,&ch,1);
+ if (r == 0) break;
+ if (r == -1) temp_read();
+
+ if (!stralloc_append(&firstpart,&ch)) temp_nomem();
+
+ if (ch == '\r')
+ continue;
+ if (ch == '\t')
+ ch = ' ';
+
+ switch (state) {
+ case 6: /* in Received, at LF but before WITH clause */
+ if (ch == ' ') { state = 3; pos = 1; continue; }
+ state = 0;
+ /* FALL THROUGH */
+
+ case 0: /* start of header field */
+ if (ch == '\n') return;
+ state = 1;
+ pos = 0;
+ /* FALL THROUGH */
+
+ case 1: /* partway through "Received:" */
+ if (ch != "RECEIVED:"[pos] && ch != "received:"[pos]) { state = 2; continue; }
+ if (++pos == 9) { state = 3; pos = 0; }
+ continue;
+
+ case 2: /* other header field */
+ if (ch == '\n') state = 0;
+ continue;
+
+ case 3: /* in Received, before WITH clause or partway though " with " */
+ if (ch == '\n') { state = 6; continue; }
+ if (ch != " WITH "[pos] && ch != " with "[pos]) { pos = 0; continue; }
+ if (++pos == 6) { state = 4; pos = 0; }
+ continue;
+
+ case 4: /* in Received, having seen with, before the argument */
+ if (pos == 0 && (ch == ' ' || ch == '\t')) continue;
+ if (ch != "UTF8"[pos] && ch != "utf8"[pos]) { state = 5; continue; }
+ if(++pos == 4) { utf8message = 1; state = 5; continue; }
+ continue;
+
+ case 5: /* after the RECEIVED WITH argument */
+ /* blast() assumes that it copies whole lines */
+ if (ch == '\n') return;
+ state = 1;
+ pos = 0;
+ continue;
+ }
+ }
+}
+
void smtp()
{
unsigned long code;
@@ -571,9 +659,12 @@
}
#endif
+ checkutf8message();
substdio_puts(&smtpto,"MAIL FROM:<");
substdio_put(&smtpto,sender.s,sender.len);
- substdio_puts(&smtpto,">\r\n");
+ substdio_puts(&smtpto,">");
+ if (utf8message) substdio_puts(&smtpto," SMTPUTF8");
+ substdio_puts(&smtpto,"\r\n");
substdio_flush(&smtpto);
code = smtpcode();
if (code >= 500) quit("DConnected to "," but sender was rejected");
@@ -702,9 +793,17 @@
relayhost[i] = 0;
}
if (!stralloc_copys(&host,relayhost)) temp_nomem();
+ } else {
+ char * ascii = 0;
+ host.s[host.len] = '\0';
+ switch (idn2_lookup_u8(host.s, (uint8_t**)&ascii, IDN2_NFC_INPUT)) {
+ case IDN2_OK: break;
+ case IDN2_MALLOC: temp_nomem();
+ default: perm_dns();
+ }
+ if (!stralloc_copys(&asciihost, ascii)) temp_nomem();
}
-
addrmangle(&sender,argv[2],&flagalias,0);
if (!saa_readyplus(&reciplist,0)) temp_nomem();
@@ -723,7 +822,7 @@
random = now() + (getpid() << 16);
- switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) {
+ switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&asciihost,random)) {
case DNS_MEM: temp_nomem();
case DNS_SOFT: temp_dns();
case DNS_HARD: perm_dns();
--- /dev/null
+++ netqmail-1.06/qmail-smtpd.c
@@ -273,6 +273,7 @@
stralloc rcptto = {0};
stralloc fuser = {0};
stralloc mfparms = {0};
+int smtputf8 = 0;
int mailfrom_size(arg) char *arg;
{
@@ -323,6 +324,7 @@
while (len) {
arg++; len--;
if (*arg == ' ' || *arg == '\0' ) {
+ if (case_starts(mfparms.s,"SMTPUTF8")) smtputf8 = 1;
if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);
if (!stralloc_copys(&mfparms,"")) die_nomem;
@@ -351,7 +353,7 @@
out("\r\n250-STARTTLS");
#endif
size[fmt_ulong(size,(unsigned int) databytes)] = 0;
- out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
+ out("\r\n250-PIPELINING\r\n250-SMTPUTF8\r\n250-8BITMIME\r\n");
out("250-SIZE "); out(size); out("\r\n");
#ifdef CRAM_MD5
out("250 AUTH LOGIN PLAIN CRAM-MD5\r\n");
@@ -516,7 +518,15 @@
if (qmail_open(&qqt) == -1) { err_qqt(); return; }
qp = qmail_qp(&qqt);
out("354 go ahead\r\n");
-
+
+ if (smtputf8) {
+ stralloc utf8proto = {0};
+ if ('E' == *protocol) protocol++;
+ if (!stralloc_copys(&utf8proto, "UTF8")) die_nomem();
+ if (!stralloc_cats(&utf8proto, protocol)) die_nomem();
+ utf8proto.s[utf8proto.len] = '\0';
+ protocol = utf8proto.s;
+ }
received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
blast(&hops);
hops = (hops >= MAXHOPS);

View File

@@ -0,0 +1,183 @@
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
EAPI=5
GENQMAIL_PV=20080406
QMAIL_SPP_PV=0.42
QMAIL_TLS_PV=20070417
QMAIL_TLS_F=${PN}-1.05-tls-smtpauth-${QMAIL_TLS_PV}.patch
QMAIL_TLS_CVE=vu555316.patch
QMAIL_BIGTODO_PV=103
QMAIL_BIGTODO_F=big-todo.${QMAIL_BIGTODO_PV}.patch
QMAIL_LARGE_DNS='qmail-103.patch'
QMAIL_SMTPUTF8='qmail-smtputf8.patch'
inherit eutils qmail
DESCRIPTION="qmail -- a secure, reliable, efficient, simple message transfer agent"
HOMEPAGE="
http://netqmail.org
http://cr.yp.to/qmail.html
http://qmail.org
"
SRC_URI="mirror://qmail/${P}.tar.gz
https://dev.gentoo.org/~hollow/distfiles/${GENQMAIL_F}
http://www.ckdhr.com/ckd/${QMAIL_LARGE_DNS}
http://inoa.net/qmail-tls/${QMAIL_TLS_CVE}
http://arnt.gulbrandsen.priv.no/qmail/qmail-smtputf8.patch
!vanilla? (
highvolume? ( mirror://qmail/${QMAIL_BIGTODO_F} )
qmail-spp? ( mirror://sourceforge/qmail-spp/${QMAIL_SPP_F} )
ssl? ( http://shupp.org/patches/${QMAIL_TLS_F} )
)
"
LICENSE="public-domain"
SLOT="0"
KEYWORDS="~alpha ~amd64 ~arm ~hppa ~mips ~ppc ~ppc64 ~x86"
IUSE="authcram gencertdaily highvolume libressl qmail-spp ssl vanilla"
REQUIRED_USE='vanilla? ( !ssl !qmail-spp !highvolume )'
RESTRICT="test"
DEPEND="
!mail-mta/qmail
net-mail/queue-repair
ssl? (
!libressl? ( dev-libs/openssl:0 )
libressl? ( dev-libs/libressl )
)
sys-apps/gentoo-functions
sys-apps/groff
net-dns/libidn2
"
RDEPEND="
!mail-mta/courier
!mail-mta/esmtp
!mail-mta/exim
!mail-mta/mini-qmail
!mail-mta/msmtp[mta]
!mail-mta/nullmailer
!mail-mta/postfix
!mail-mta/qmail-ldap
!mail-mta/sendmail
!<mail-mta/ssmtp-2.64-r2
!>=mail-mta/ssmtp-2.64-r2[mta]
>=sys-apps/ucspi-tcp-0.88-r17
ssl? ( >=sys-apps/ucspi-ssl-0.70-r1 )
virtual/daemontools
>=net-mail/dot-forward-0.71-r3
virtual/checkpassword
authcram? ( >=net-mail/cmd5checkpw-0.30 )
${DEPEND}
"
pkg_setup() {
if [[ -n "${QMAIL_PATCH_DIR}" ]]; then
eerror
eerror "The QMAIL_PATCH_DIR variable for custom patches"
eerror "has been removed from ${PN}. If you need custom patches"
eerror "you should create a copy of this ebuild in an overlay."
eerror
die "QMAIL_PATCH_DIR is not supported anymore"
fi
qmail_create_users
}
src_unpack() {
genqmail_src_unpack
use qmail-spp && qmail_spp_src_unpack
unpack ${P}.tar.gz
}
src_prepare() {
epatch "${FILESDIR}"/${PV}-exit.patch
epatch "${FILESDIR}"/${PV}-readwrite.patch
epatch "${DISTDIR}"/${QMAIL_LARGE_DNS}
epatch "${FILESDIR}"/${PV}-fbsd-utmpx.patch
ht_fix_file Makefile*
if ! use vanilla; then
# This patch contains relative paths and needs to be cleaned up.
sed 's~^--- ../../~--- ~g' \
<"${DISTDIR}"/${QMAIL_TLS_F} \
>"${T}"/${QMAIL_TLS_F} || die
use ssl && epatch "${T}"/${QMAIL_TLS_F}
use ssl && epatch "${DISTDIR}"/${QMAIL_TLS_CVE}
use highvolume && epatch "${DISTDIR}"/${QMAIL_BIGTODO_F}
if use qmail-spp; then
if use ssl; then
epatch "${QMAIL_SPP_S}"/qmail-spp-smtpauth-tls-20060105.diff
else
epatch "${QMAIL_SPP_S}"/netqmail-spp.diff
fi
cd "${WORKDIR}" || die
epatch "${FILESDIR}"/genqmail-20080406-ldflags.patch
cd - || die
fi
fi
cd "${WORKDIR}" || die
epatch "${FILESDIR}"/use-new-path-for-functions.sh.patch
epatch "${FILESDIR}"/qmail-smtputf8.patch
cd - || die
qmail_src_postunpack
# Fix bug #33818 but for netqmail (Bug 137015)
if ! use authcram; then
einfo "Disabled CRAM_MD5 support"
sed -e 's,^#define CRAM_MD5$,/*&*/,' -i "${S}"/qmail-smtpd.c || die
else
einfo "Enabled CRAM_MD5 support"
fi
}
src_compile() {
qmail_src_compile
use qmail-spp && qmail_spp_src_compile
}
src_install() {
qmail_src_install
}
pkg_postinst() {
qmail_queue_setup
qmail_rootmail_fixup
qmail_tcprules_build
qmail_config_notice
qmail_supervise_config_notice
elog
elog "If you are looking for documentation, check those links:"
elog "https://www.gentoo.org/doc/en/qmail-howto.xml"
elog " -- qmail/vpopmail Virtual Mail Hosting System Guide"
elog "http://www.lifewithqmail.com/"
elog " -- Life with qmail"
elog
}
pkg_preinst() {
qmail_tcprules_fixup
}
pkg_config() {
# avoid some weird locale problems
export LC_ALL=C
qmail_config_fast
qmail_tcprules_config
qmail_tcprules_build
use ssl && qmail_ssl_generate
}