# (qmail-spp) vpopmail_check_recipient and ezmlm

## toniocartonio

Hi folks

I run a small server at home that takes care of my email as well as a few other domains. The server runs qmail+vpopmail+courier and ezmlm to provide 2 mailing lists to one of the managed domains.

I recently found and enabled the vpopmail_check_recipient plugin for qmail-spp, which works like a charm for the vpopmail mailboxes. However, it is unable to find any of the ezmlm-based mailboxes and thus rejects emails sent to the mailing lists saying that the mailbox does not exist.

I have looked a bit on the documentation on the website and in the mailing-list for qmail-spp but could not find anybody else with a similar problem.

Since I think it is not very easy to change the plugin to consider all ezmlm mailboxes (and combinations of commands), does anybody know if and how can I make an exception to the use of this qmail-spp plugin, and tell it not to run for the specific domain name that uses the mailing lists, and just let mail through as normal?

Looking at the short documentation page on qmail-spp´s website it looks like it is possible... but I could not find any example on how to configure it.

In case even a rule to add to the actual script would be fine with me.

Thanks  :Smile: 

----------

## DennisBagley

I have exactly the same problem and my remote queue is chock full of bounce messages...

Am looking for a fix so will post it here as and when I find / write one [am thinking strip the -command off the end then looking .qmail-name-default file in /var/vpopmail/domains/{domain}/ dir - a bit cludgy and would allow some incorrect ezmlm address's through, but would stop valid mail being bounced]

----------

## DennisBagley

have been put onto chkuser [ http://www.interazioni.it/opensource/chkuser/ ] as a qmail patch which should allow you to check validity of address's including ezmlm address's not just vpop ones. Am yet to test it - as i am still looking for a function/app in that will allow me to just query ezmlm address's so it can be added to the vpopmail_check_recipient.sh script - and i can feel like i actually gave something back for once - but if you do give this a whirl then let me know - i will keep updating this thread with my progress

also - am stuck emerge -e system && emerge -e world, after accidently updateing gcc from 3.x to 4.1 due to not paying attention when emerge -u courier-imap so - may not get back to this until next weekend  :Wink: 

Den

----------

## danman

Hi Dennis!

Ok, so ezmlm maillists are created with .qmail-listname files. You need to check whether the file exists.

----

# get the user-name

BOX=${RECIPIENT%%@*}

BOX2=`echo $BOX | /bin/sed "s/\./\:/g"`

HOMEPATH="`${VDOMAININFO} ${DOMAIN} | /bin/grep dir | /bin/sed -e 's#dir: *##'`"

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOX} 2> /dev/null`" ]; then

  [ "${SPP}" == "1" ] && echo "${MSG_OK}"

  exit 0

fi

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOX2} 2> /dev/null`" ]; then

  [ "${SPP}" == "1" ] && echo "${MSG_OK}"

  exit 0

fi

----

BOX2 replaces . with :, because that's how .qmail files work (i.e.: .qmail-dennis:bagley is for dennis.bagley@...).

custom.ls is a copy of the real /bin/ls put into /var/vpopmail/bin with the following rights:

-rwsr-xr-x 1 root root      98928 Nov 26 15:14 custom.ls

This is needed, because otherwise vpopmail can't read in the dirs.

BTW ezmlm isn't that simple :-) For instance you may need to send mails to addresses like listname-accept-db172db172@domain.tld.

For this I made the following trick:

RECIPIENTPERIG=`${VECHO} "${RECIPIENT}" | ${VCUT} -d "-" -f -1`

BOXPERIG=${RECIPIENTPERIG%%@*}

BOX2PERIG=`echo $BOX | /bin/sed "s/\./\:/g"`

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOXPERIG} 2> /dev/null`" ]; then

  [ "${SPP}" == "1" ] && echo "${MSG_OK}"

  exit 0

fi

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOX2PERIG} 2> /dev/null`" ]; then

  [ "${SPP}" == "1" ] && echo "${MSG_OK}"

  exit 0

fi

You'll have to sort that out, but tell me if you need any assistance!

Anyway, this vpopmail_check_recipient.sh script is a nice thing to have, because if you get it really customized, then there is almost nothing you can't do with it :-) The default version just lacks a "few" features, but the main idea is great.

GCC3 -> GCC4 with emerge -e system/world is a nightmare. Every config file regarding qmail gets overwrited without question. I had the same problem, and had a great time sorting it out :-) I will never do emerge -e system/world again without paying attention. I think it's better to emerge the packages with lists from emerge -p...

Hope this helped!

Bye,

DanMan

p.s.: I guess I'll take a look at this chkuser script, because I've never heard of it. Thx!

----------

## DennisBagley

i will give that a go  - but it looks like it will do the job

as for the emerge -e and file overwrites i have been through that already on another box - so i made copies of /etc /var before starting - including all my tweeks to qmail-queue-scanner.pl [would hate to start that from scratch]

anyways - thanks again;

i will return with my progress....

[... once i have removed a line from the ezmlm code that stops it compiling under gcc 4.1.1 !!

see https://forums.gentoo.org/viewtopic-t-498823-highlight-.html ]

--- EDIT 1 ---

Nice one danman - that is working mainly [now i have custom.ls not ls.custom as my first try - was cursing you for a moment   :Twisted Evil:  ]

though i am still having problems with listname-faq@domain.tld / listname-help@ etc etc - but listname-owner@ works - as does listname@ - will test with subscribe and unsubscribe when i get a mo

-------------------------------

for anyone else reading this - get the custom.ls by the following

cp /bin/ls /var/vpopmail/bin/custom.ls

chown root:root /var/vpopmail/bin/custom.ls <--- i think this could be vpopmail:vpopmail depending on who runs the script, bit more secure

chmod 755 /var/vpopmail/bin/custom.ls

chmod u+s /var/vpopmail/bin/custom.ls

am guessing the sticky bit on /var/vpopmail/bin/custom.ls is a bit of a security no no - so will looking at a change there - but is certainly a very good start

--- EDIT 2 ---

ok- I now realise i need to point vcut and vecho at something - i have made copies of /usr/bin/cut and /usr/bin/echo with v's on the front in /var/vpopmail/bin/ - given them the sticky bit and chmod treatment - and replaced ${VECHO} with /var/vpopmail/bin/vecho , and replaced ${VCUT} with /var/vpopmail/bin/vcut

[will tidy these to be set at top of script when i can be arsed]

so - now list-subscribe etc and moderator commands work - however subscribe confirm is not working - i think this is becasue the @ in the confirming email is changed to an equals sign - so I imagine that this just needs quoting or escaping on the vecho command - but have stopped for lunch - will update again later - and post the full script with install instructions when done [ps : i would like your comments on changing the sticky files to be owned by vpopmail - as that is the owner of the dirs and files being ls'd]

--- EDIT 3 ---

Nailed it - the equals is causing the script to declaire the address invalid, so just adding that to the regex on the username part of the address adding hoping i can finally get on with my life - then off to read rfc 2821 - but based on the wikipedia entry [ http://en.wikipedia.org/wiki/E-mail_address ] I would say that the spp script is actually too limiting in what it considers a valid address

--- EDIT END ---

Cheers,

Den

----------

## DennisBagley

OK - here it is - finished article

---START /var/qmail/plugins/vpopmail_check_recipient.sh ---

```
#!/bin/sh

#*

#* Copyright (C) 2004 Perolo Silantico <per.sil@gmx.it> and

#*                    Pawel Foremski <pjf@gna.org>, et al.

#*

#* This program is free software; you can redistribute it and/or

#* modify it under the terms of the GNU General Public License

#* as published by the Free Software Foundation; either

#* version 2 of the License, or (at your option) any later

#* version.

#*

#* This program is distributed in the hope that it will be useful,

#* but WITHOUT ANY WARRANTY; without even the implied warranty of

#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

#* GNU General Public License for more details.

#*

#* You should have received a copy of the GNU General Public License

#* along with this program; if not, write to the Free Software Foundation,

#* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#***

#*

#* $Id$

#*

#*

# checks an email address provided as parameter with vpopmail or

# if called as a qmail-spp plugin using ${SMTPRCPTTO}

# returns

#   0   ... in case the email exists

#   1   ... in case this email does not exists

# path to vpopmail directory

VPOPMAIL_BINDIR=/var/vpopmail/bin

VDOMAININFO=${VPOPMAIL_BINDIR}/vdominfo

VALIAS=${VPOPMAIL_BINDIR}/valias

VUSERINFO="${VPOPMAIL_BINDIR}/vuserinfo -n"

VGREP=${VPOPMAIL_BINDIR}/vgrep

# the recipient to check is the only parameter on the command line - if any present

RECIPIENT="$1"

## --- LOG settings

# trigger log messages

LOG_USE=1

LOG_PREFIX="qmail-spp (`basename $0`) [$$]: "

## --- qmail-spp settings

MSG_ERROR="E511 Sorry, no mailbox here by that name - plugin (#5.1.1)"

MSG_OK=""

# if this is a qmail-spp plugin. recipient is passed via environement

if [ ! -z "${SMTPRCPTTO}" ]; then

  RECIPIENT="${SMTPRCPTTO}"

  SPP=1

else

  SPP=0

fi

# if the recipient is empty it does not exist :)

if [ -z "${RECIPIENT}" ]; then

  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}invalid empty recipient" 1>&2

  [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"

  exit 1

fi

# get the domain name of the recipient

#DOMAIN=`/bin/echo $RECIPIENT | /bin/sed -e 's#.*@##'`

DOMAIN=${RECIPIENT##*@}

# get the user-name

BOX=${RECIPIENT%%@*}

# check if the box name contains invalid characters

if [ ! -z "`/bin/echo ${RECIPIENT} | /bin/grep '[^-0-9A-Za-z\+\.@_\=]'`" ]; then

  [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}invalid characters in recipient name: ${RECIPIENT}" 1>&2

  [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"

  exit 1

fi

# check if the domain exists. If the domain is not on this host, this is

# an relay-attempt

if [ "`${VDOMAININFO} ${DOMAIN} > /dev/null; echo $?`" != "0" ]; then

  # if RELAYCLIENT is set, then the user has authenticated before

  # relaying is allowed

  if [ "`set | /bin/grep RELAYCLIENT > /dev/null; echo $?`" == "0" -o ! -z "${SMTPAUTHUSER}" ]; then

    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}relaying email to: ${RECIPIENT}"  1>&2

    [ "${SPP}" == "1" ] && echo "${MSG_OK}"

    exit 0

  else

    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}no such domain: ${DOMAIN}"  1>&2

    [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"

    exit 1

  fi

else

    # domain found. but is it the correct domain or is it an alias domain?

    DOM=`${VDOMAININFO} ${DOMAIN} | $VGREP -e "^domain: " | cut -f 2 -d " "`

    if [ "$DOM" != "$DOMAIN" ]

        then

        DOMAIN=$DOM

        RECIPIENT=$BOX@$DOM

    fi 

fi

# check the existence of the user

[ "`${VUSERINFO} ${RECIPIENT} > /dev/null; echo $?`" == "0" ] && exit 0

# check with valias if an alias or an e-mail address of that name exists

if [ ! -z "`${VALIAS} -s ${RECIPIENT} | /bin/grep ^${RECIPIENT}`" ]; then

  [ "${SPP}" == "1" ] && echo "${MSG_OK}"

  exit 0

fi

# no alias for that recipient email address has been recorded

# and no such user exists.

### get the home directory for that domain and check the existence of

### a .qmail-${BOX} file

HOMEPATH="`${VDOMAININFO} ${DOMAIN} | /bin/grep dir | /bin/sed -e 's#dir: *##'`"

# if a .qmail-${BOX} file exists, then delivery is possible

#if [ -e "${HOMEPATH}/.qmail-${BOX}" ]; then

if [ ! -z "`/bin/ls ${HOMEPATH}/.qmail-${BOX} 2> /dev/null`" ]; then

  [ "${SPP}" == "1" ] && echo "${MSG_OK}"

  exit 0

fi

### custom addition for ezmlm

# get the user-name

BOX=${RECIPIENT%%@*}

BOX2=`echo $BOX | /bin/sed "s/\./\:/g"`

HOMEPATH="`${VDOMAININFO} ${DOMAIN} | /bin/grep dir | /bin/sed -e 's#dir: *##'`"

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOX} 2> /dev/null`" ]; then

[ "${SPP}" == "1" ] && echo "${MSG_OK}"

exit 0

fi

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOX2} 2> /dev/null`" ]; then

[ "${SPP}" == "1" ] && echo "${MSG_OK}"

exit 0

fi

RECIPIENTPERIG=`/var/vpopmail/bin/vecho "${RECIPIENT}" | /var/vpopmail/bin/vcut -d "-" -f -1`

BOXPERIG=${RECIPIENTPERIG%%@*}

BOX2PERIG=`echo $BOX | /bin/sed "s/\./\:/g"`

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOXPERIG} 2> /dev/null`" ]; then

[ "${SPP}" == "1" ] && echo "${MSG_OK}"

exit 0

fi

if [ ! -z "`/var/vpopmail/bin/custom.ls ${HOMEPATH}/.qmail-${BOX2PERIG} 2> /dev/null`" ]; then

[ "${SPP}" == "1" ] && echo "${MSG_OK}"

exit 0

fi

# no other checks have prooven the existence of this email address

[ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}no such recipient: ${RECIPIENT} (${HOMEPATH}/.qmail-${BOX})" 1>&2

[ "${SPP}" == "1" ] && echo "${MSG_ERROR}"

exit 1
```

--- END ---

and I ran the following to get the extra binaries i needed

```
cp /bin/ls /var/vpopmail/bin/custom.ls

chown root:root /var/vpopmail/bin/custom.ls

chmod 755 /var/vpopmail/bin/custom.ls

chmod u+s /var/vpopmail/bin/custom.ls

cp /usr/bin/cut /var/vpopmail/bin/vcut

chown root:root /var/vpopmail/bin/vcut

chmod 755 /var/vpopmail/bin/vcut

cp /usr/bin/echo /var/vpopmail/bin/vecho

chown root:root /var/vpopmail/bin/vecho

chmod 755 /var/vpopmail/bin/vecho

cp /bin/grep /var/vpopmail/bin/vgrep

chown root:root /var/vpopmail/bin/vgrep

chmod 755 /var/vpopmail/bin/vgrep
```

I guess i could have just used the $VCUT and $VECHO and pointed them /usr/bin/cut and /usr/bin/echo but at the end of the day i wanted to get this bugger working - i will tidy up later

If you are editing your script and not just copying this wholesale - make sure you add the \= to the # check if the box name contains invalid characters section of the script (not sure if it needed to be escaped - but doesnt harm)

Hope this is of use to people - and huge thanks to danman who basically did everything other than add the equals   :Embarassed: 

Den

EDIT : updated script to include + as a valid character - so i can subscribe to things !! and included updates from December 07

----------

## oliwel

Hi Den

I use a similar script and did the trick another way round - I use the idea already used with qmail-scanner-queue and provide a small binary that is setuid to the vpopmailuser and call the chkusr Plugin through this. So, all vpopmail checks are running on the vpopmail user and you do not need to make any system binaries suid ( I guess this cat will kill you once doing an upgrade on system libs...)

Oliver

----------

## danman

Hi Dennis!

Glad to hear all this! I added the \= in my script, thx!

And many thanks in the name of all who will use this step-by-step tutorial you gave us!

BTW I checked chkuser and it requires patching. Maybe it's a nice program, but I prefer vpopmail_check_recipients.sh until chkuser is included in the official ebuild (with use flag or something). But maybe even then I will stick with this custom made script :-) We have worked with it too much, to just trash it :-) (and it works perfectly)

Bye,

DanMan

----------

## DennisBagley

well - for whatever reason it is a year on and i am back to this post - firstly to work out how we did this last time - and now with a new bug - its not recognising and alias (forward) address that is being used though an alias domain

that is...

user1@domain1.com is a real mail account (well - vpopmail account)

domain2.com is aliased to domain1.com

within domain1... 

user2 is aliased to user1

so - the expected effect - as far as mail delivery is concerned, is that any combination of user1 / user2 with domain1.com / domain2.com would get to the mailbox - and it does...

however because of the way that the domain alias is done (added using vqadmin) user2@domain2.com fails the vpopmail_check_recipient script as it is not recognised by valias...

i imagine the thing to do is to apply the domain alias at the start of the script, but it seems strange that vuserinfo can handle the domain alias, but valias cant...

as ever will post the fix as / when its working

den

----------

## danman

Hi Dennis!

Domain alias works ok by me.

I don't have an overlook on the full script at the moment, but maybe this part is important:

--------------------------------------------------------------------------------------

VDOMAININFO=${VPOPMAIL_BINDIR}/custom.vdominfo

VALIAS=${VPOPMAIL_BINDIR}/custom.valias

VECHO=${VPOPMAIL_BINDIR}/custom.echo

VCUT=${VPOPMAIL_BINDIR}/custom.cut

VGREP=${VPOPMAIL_BINDIR}/custom.grep

VUSERINFO="${VPOPMAIL_BINDIR}/custom.vuserinfo -n"

--------------------------------------------------------------------------------------

And here is another block I think I have modified, and this will be the key I guess:

--------------------------------------------------------------------------------------

# check if the domain exists. If the domain is not on this host, this is

# an relay-attempt

if [ "`${VDOMAININFO} ${DOMAIN} > /dev/null; echo $?`" != "0" ]; then

  # if RELAYCLIENT is set, then the user has authenticated before

  # relaying is allowed

  if [ "`set | /bin/grep RELAYCLIENT > /dev/null; echo $?`" == "0" -o ! -z "${SMTPAUTHUSER}" ]; then

    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}relaying email to: ${RECIPIENT}"  1>&2

    [ "${SPP}" == "1" ] && echo "${MSG_OK}"

    exit 0

  else

    [ "${LOG_USE}" == "1" ] && echo "${LOG_PREFIX}no such domain: ${DOMAIN}"  1>&2

    [ "${SPP}" == "1" ] && echo "${MSG_ERROR}"

    exit 1

  fi

else

  # domain found. but is it the correct domain or is it an alias domain?

  DOM=`${VDOMAININFO} ${DOMAIN} | $VGREP -e "^domain: " | cut -f 2 -d " "`

  if [ "$DOM" != "$DOMAIN" ]

    then

    DOMAIN=$DOM

    RECIPIENT=$BOX@$DOM

  fi

fi

--------------------------------------------------------------------------------------

Hope the above helps. Give me some feedback! :-) If not, we will sort it out someway, like a year ago :-)

Merry Christmas!

DanMan

----------

## DennisBagley

Thanks danman - once again that's done the job

```

else

# domain found. but is it the correct domain or is it an alias domain?

DOM=`${VDOMAININFO} ${DOMAIN} | $VGREP -e "^domain: " | cut -f 2 -d " "`

if [ "$DOM" != "$DOMAIN" ]

then

DOMAIN=$DOM

RECIPIENT=$BOX@$DOM

fi

 
```

and the VGREP  definition did the trick

will drop the full script and commands later - but its all working on the server

----------

