goodrcptto

If you saw this URL in an email bounce message you received please read the following paragraph

I cannot help you with your bounced email. Really. I cannot unsubscribe you from a mailing list, I cannot stop your credit card from being charged. Please do not email me to ask me to do these things. Unless you were trying to email me personally, I am nothing to do with the site that is rejecting your email, I just wrote a bit of code that people are free to use to try to stop spam emails

If you are thinking of applying this patch to qmail:

Don't! Since I wrote this in Jan 2001 a far better solution has appeared to achieve the same thing, go here to Eben Pratt's qmail page and use his goodrcptto patch.

If you try to apply the patch and can't

That's because I put raw diff output up, not a format compatible witht he patch command. You will have to interpret the diff output youself. I know better nowdays

If you really insist on applying this patch

Please put postmaster (always) and webmaster (if the domain has a website) in the goodrcptto file.

Anyway, with that lot out of the way, here it is.

Here is a patch for qmail I wrote. It's inspiration was the bardrcptto patch and like that patch uses the badmailfrom code, although with some modifications to allow a user to be accepted based soley on the username and not the full email address.

The problem it sets out to solve is that qmail downloads the entire message before rejecting it if it is not for a valid address on the system. I have worked around this by having a file called control/goodrcptto which lists all the allowed addresses that mail can be recieved for, so the message is rejected based on the SMTP envelope when the RCPT TO command is recieved. The reason for this patch is that about 90% of the mail I recieve is for non existant users on a domain I own which is a simple mistype away from the domain used by a US cable ISP for all it's customer email addresses. More fool me for not checking befor registering it but I have to live with it now!

The solution is not elegant! You must create a file called goodrcptto in the qmail control directory. This can list acceptable email addresses in the following forms:

  • full address ie someone@somedomain.com means that email that is for someone@somedomain.com will be accepted
  • domains ie @otherdomain.com means that all mail @otherdomain.com will be accepted
  • usernames ie foo means that any mail addressed to foo at any of the domains for which mail is accepted by this server is accepted (domains usually listed in control/me or control/rcpthosts or control/locals)

    It solves my problem of downloading entire messages then bouncing them (often to have the bounce bounced) admirably and has vastly cut down on the amount of bandwidth I use.

    Note that obviously every time a user or alias is added the goodrcptto file must be updated or their mail will be bounced. Checking the user list and .qmail files instead of using a separate file which must be manually updated is a "thing to do".

    This is the raw output from diff on the modified and original versions of qmail-smtpd.c. You cannot use patch with this, sorry!

    Revision History

    28 Jan 01 - original page
    27 Apr 06 - some text, link to Eben Pratt's page added

    53d52
    < void err_grt() { out("553 sorry, that name is not in my list of allowed recipients.  See http://www.chater.demon.co.uk/qmail/index.htm for more information\r\n"); }
    100,102d98
    < int grtok = 0;
    < stralloc grt = {0};
    < struct constmap mapgrt;
    123,127d118
    < 
    <   grtok = control_readfile(&grt,"control/goodrcptto",0);
    <   if (grtok == -1) die_control();
    <   if (grtok)
    <     if (!constmap_init(&mapgrt,grt.s,grt.len,0)) die_nomem();
    220,241d210
    < int grtcheck()
    < {
    < char *nameto;
    < int j;
    < 
    <   if (!grtok) return 0;
    < 
    <   if (constmap(&mapgrt,addr.s,addr.len - 1)) return 0;
    <   j = byte_rchr(addr.s,addr.len,'@');
    <   if (j < addr.len)
    <     {
    <     if (constmap(&mapgrt,addr.s + j,addr.len - j - 1)) return 0;
    <     if (!(nameto = (char *)malloc(j+1))) die_nomem();
    <     memcpy(nameto,addr.s,j);
    <     nameto[j]=0;
    <     if (constmap(&mapgrt,nameto, j )) {free((void *)nameto); return 0;}
    <     free((void *)nameto);
    <     }
    <   else return 0; 
    <   return 1;
    < }
    < 
    291d259
    <     {
    293,295d260
    <     /* old check if recipient bad if not relaying*/
    <     if (grtcheck()) { err_grt(); return; }
    <     }
    

    I can be contacted at mark@chater.demon.co.uk , a response is not guaranteed.

    GPL-ed