This patch makes two unrelated but useful changes to rblsmtpd, the altreply patch and a new detour patch. The altreply patch handles DNSBLs with A records but no TXT records. You say: -r some.dnsbl.org:The rejection message The string %IP% is replaced by the current IP in the rejection message. The detour patch adds a -d flag that changes the interpretation of DNSBLs. Rather than running the rejection server, it sets an environemnt variable, given as the argument to the -d flag and runs the usual smtp daemon. Normally you set RELAYCLIENT to make qmail-smtpd detour the mail into a locally handled virtual domain, e.g.: /usr/local/bin/rblsmtpd -b \ -d 'RELAYCLIENT=@detour'" \ -r'sbl.spamhaus.org' \ -d "" -r'relays.visi.com' \ /var/qmail/bin/qmail-smtpd 2>&1 A -d flag with a null argument turns off -d, so in this case, mail from hosts in the SBL is detoured, mail in the visi list is rejected. John Levine, johnl@taugh.com, 4/04 diff ucspi-tcp-0.88-dist/rblsmtpd.c ucspi-tcp-0.88/rblsmtpd.c 58a59,61 > static char *dflag; > static char *detour; > 62a66,67 > int i; > char *altreply = 0; 64a70,74 > i = str_chr(base, ':'); > if (base[i]) { > base[i] = 0; > altreply = base+i+1; > } 66,70c76,112 < if (dns_txt(&text,&tmp) == -1) { < flagmustnotbounce = 1; < if (flagfailclosed) { < if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem(); < decision = 2; --- > if (altreply) { > if (dns_ip4(&text,&tmp) == -1) { > flagmustnotbounce = 1; > if (flagfailclosed) { > if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem(); > decision = 2; > } > return; > } > if (text.len) { > if(!stralloc_copys(&text, "")) nomem(); > while(*altreply) { > char *x; > i = str_chr(altreply, '%'); > if(!stralloc_catb(&text, altreply, i)) nomem(); > if(altreply[i] && > altreply[i+1]=='I' && > altreply[i+2]=='P' && > altreply[i+3]=='%') { > if(!stralloc_catb(&text, ip_env, str_len(ip_env))) nomem(); > altreply+=i+4; > } else if(altreply[i]) { > if(!stralloc_cats(&text, "%")) nomem(); > altreply+=i+1; > } else { > altreply+=i; > } > } > } > } else { > if (dns_txt(&text,&tmp) == -1) { > flagmustnotbounce = 1; > if (flagfailclosed) { > if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem(); > decision = 2; > } > return; 72d113 < return; 75c116,118 < if (flagrblbounce) --- > if(dflag && *dflag) { > detour = dflag; decision = 1; > } else if (flagrblbounce) 178c221 < while ((opt = getopt(argc,argv,"bBcCt:r:a:")) != opteof) --- > while ((opt = getopt(argc,argv,"bBcCt:r:a:d:")) != opteof) 186a230 > case 'd': dflag = optarg; break; 196c240,242 < pathexec_run(*argv,argv,envp); --- > if (detour) if (!pathexec_env(detour, 0)) nomem(); > > pathexec(argv);