summaryrefslogtreecommitdiffstats
path: root/qmail-remote.c
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2017-08-17 13:17:22 +0200
committermanuel <manuel@mausz.at>2017-08-17 13:17:22 +0200
commit1cafb5eab0b30e5f5a05737a075123af53153cb1 (patch)
treec6d4774169f7676385eca916eef3e4087693e0a2 /qmail-remote.c
parent3ee3b980a23b79479a650343a0fa876f68cad4bc (diff)
downloadqmail-1cafb5eab0b30e5f5a05737a075123af53153cb1.tar.gz
qmail-1cafb5eab0b30e5f5a05737a075123af53153cb1.tar.bz2
qmail-1cafb5eab0b30e5f5a05737a075123af53153cb1.zip
add support for SMTPUTF8
Diffstat (limited to 'qmail-remote.c')
-rw-r--r--qmail-remote.c96
1 files changed, 91 insertions, 5 deletions
diff --git a/qmail-remote.c b/qmail-remote.c
index 94c6c0d..f8e60ad 100644
--- a/qmail-remote.c
+++ b/qmail-remote.c
@@ -46,6 +46,7 @@ stralloc helohost = {0};
46stralloc routes = {0}; 46stralloc routes = {0};
47struct constmap maproutes; 47struct constmap maproutes;
48stralloc host = {0}; 48stralloc host = {0};
49stralloc idnhost = {0};
49stralloc sender = {0}; 50stralloc sender = {0};
50stralloc auth_smtp_user = {0}; 51stralloc auth_smtp_user = {0};
51stralloc auth_smtp_pass = {0}; 52stralloc auth_smtp_pass = {0};
@@ -77,13 +78,19 @@ struct val_danestatus *dane_status = NULL;
77struct val_ssl_data *dane_ssl_data = NULL; 78struct val_ssl_data *dane_ssl_data = NULL;
78#endif 79#endif
79 80
81#ifdef SMTPUTF8
82# include <idn2.h>
83int flagutf8 = 0;
84stralloc header = {0};
85#endif
86
80void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } 87void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
81void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } 88void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
82void zeroflush() { zero(); substdio_flush(subfdoutsmall); } 89void zeroflush() { zero(); substdio_flush(subfdoutsmall); }
83void zerodie() { zeroflush(); _exit(0); } 90void zerodie() { zeroflush(); _exit(0); }
84void outsafe(sa) stralloc *sa; { int i; char ch; 91void outsafe(sa) stralloc *sa; { int i; unsigned char ch;
85for (i = 0;i < sa->len;++i) { 92for (i = 0;i < sa->len;++i) {
86ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; 93ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126 && ch <= 127) ch = '?';
87if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } 94if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
88 95
89void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } 96void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
@@ -346,6 +353,10 @@ void blast()
346 int r; 353 int r;
347 char ch; 354 char ch;
348 355
356#ifdef SMTPUTF8
357 substdio_put(&smtpto,header.s,header.len);
358#endif
359
349 for (;;) { 360 for (;;) {
350 r = substdio_get(&ssin,&ch,1); 361 r = substdio_get(&ssin,&ch,1);
351 if (r == 0) break; 362 if (r == 0) break;
@@ -634,11 +645,60 @@ int tls_init()
634 645
635stralloc recip = {0}; 646stralloc recip = {0};
636 647
648#ifdef SMTPUTF8
649int utf8string(unsigned char *ch, int len)
650{
651 int i = 0;
652 while (i < len)
653 if (ch[i++] > 127) return 1;
654 return 0;
655}
656
657int utf8received()
658{
659 int r, i, received = 0;
660 char ch;
661 stralloc receivedline = {0};
662
663 for (;;) { /* we consider only our own last written header */
664 r = substdio_get(&ssin,&ch,1);
665 if (r == 0) break;
666 if (r == -1) temp_read();
667
668 if (ch == '\n') {
669 if (!stralloc_append(&header,"\r")) temp_nomem(); /* received.c does not add '\r' */
670 if (!stralloc_append(&header,"\n")) temp_nomem();
671 if (case_startb(receivedline.s,5,"Date:")) return 0; /* header to quit asap */
672 if (case_startb(receivedline.s,14,"Received: from")) received++; /* found Received header */
673 if (received) {
674 if (case_startb(receivedline.s,5," by ")) {
675 for (i = 6; i < receivedline.len-6; ++i)
676 if (*(receivedline.s+i) == ' ')
677 if (case_startb(receivedline.s+i+1,9,"with UTF8")) return 1;
678 return 0;
679 }
680 }
681 if (!stralloc_copys(&receivedline,"")) temp_nomem();
682 receivedline.len = 0;
683 } else {
684 if (!stralloc_append(&header,&ch)) temp_nomem();
685 if (!stralloc_catb(&receivedline,&ch,1)) temp_nomem();
686 }
687 }
688 return 0;
689}
690#endif
691
637void mail_without_auth() 692void mail_without_auth()
638{ 693{
639 substdio_puts(&smtpto,"MAIL FROM:<"); 694 substdio_puts(&smtpto,"MAIL FROM:<");
640 substdio_put(&smtpto,sender.s,sender.len); 695 substdio_put(&smtpto,sender.s,sender.len);
641 substdio_puts(&smtpto,">\r\n"); 696 substdio_put(&smtpto,">",1);
697#ifdef SMTPUTF8
698 if (flagutf8 || utf8received())
699 substdio_puts(&smtpto, " SMTPUTF8");
700#endif
701 substdio_puts(&smtpto,"\r\n");
642 substdio_flush(&smtpto); 702 substdio_flush(&smtpto);
643} 703}
644 704
@@ -730,7 +790,12 @@ void smtp()
730 substdio_put(&smtpto,sender.s,sender.len); 790 substdio_put(&smtpto,sender.s,sender.len);
731 substdio_puts(&smtpto,"> AUTH=<"); 791 substdio_puts(&smtpto,"> AUTH=<");
732 substdio_put(&smtpto,sender.s,sender.len); 792 substdio_put(&smtpto,sender.s,sender.len);
733 substdio_puts(&smtpto,">\r\n"); 793 substdio_put(&smtpto,">",1);
794#ifdef SMTPUTF8
795 if (flagutf8 || utf8received())
796 substdio_puts(&smtpto, " SMTPUTF8");
797#endif
798 substdio_puts(&smtpto,"\r\n");
734 substdio_flush(&smtpto); 799 substdio_flush(&smtpto);
735 if(!stralloc_copys(&auth_status, "Delivered with authenticated connection to \n")) temp_nomem(); 800 if(!stralloc_copys(&auth_status, "Delivered with authenticated connection to \n")) temp_nomem();
736 if(!stralloc_0(&auth_status)) temp_nomem(); 801 if(!stralloc_0(&auth_status)) temp_nomem();
@@ -902,7 +967,12 @@ stralloc *saout; /* host has to be canonical, box has to be quoted */
902char *s; 967char *s;
903{ 968{
904 int j; 969 int j;
905 970
971#ifdef SMTPUTF8
972 if (!flagutf8)
973 flagutf8 = utf8string(s, str_len(s));
974#endif
975
906 j = str_rchr(s,'@'); 976 j = str_rchr(s,'@');
907 if (!s[j]) { 977 if (!s[j]) {
908 if (!stralloc_copys(saout,s)) temp_nomem(); 978 if (!stralloc_copys(saout,s)) temp_nomem();
@@ -983,6 +1053,18 @@ char **argv;
983 relayhost[i] = 0; 1053 relayhost[i] = 0;
984 } 1054 }
985 if (!stralloc_copys(&host,relayhost)) temp_nomem(); 1055 if (!stralloc_copys(&host,relayhost)) temp_nomem();
1056 } else {
1057#ifdef SMTPUTF8
1058 char *asciihost = 0;
1059 if (!stralloc_0(&host)) temp_nomem();
1060 switch (idn2_lookup_u8(host.s,(uint8_t**)&asciihost,IDN2_NFC_INPUT)) {
1061 case IDN2_OK: break;
1062 case IDN2_MALLOC: temp_nomem();
1063 default: perm_dns();
1064 }
1065 if (!stralloc_copys(&idnhost,asciihost)) temp_nomem();
1066 if (!stralloc_0(&idnhost)) temp_nomem();
1067#endif
986 } 1068 }
987 1069
988 1070
@@ -1002,7 +1084,11 @@ char **argv;
1002 1084
1003 1085
1004 random = now() + (getpid() << 16); 1086 random = now() + (getpid() << 16);
1087#ifdef SMTPUTF8
1088 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&idnhost,random)) {
1089#else
1005 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) { 1090 switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) {
1091#endif
1006 case DNS_MEM: temp_nomem(); 1092 case DNS_MEM: temp_nomem();
1007 case DNS_SOFT: temp_dns(); 1093 case DNS_SOFT: temp_dns();
1008 case DNS_HARD: perm_dns(); 1094 case DNS_HARD: perm_dns();