2003-05-16 Jørgen Thomsen, jth@jth.net
Valid XHTML 1.0!

Virtual domains using GNU pop3d and Postfix 

GNU pop3d 0.9.9

The GNU pop3d 0.9.9 is ready, but also needs some better documentation on this page. You may download it here GNU pop3d 0.9.9-4


CHANGES / HISTORY
18/Jan/2003 0.9.9-4 Jørgen Thomsen jth@jth.net, http://jth.net
        Support for Postfix X-Original-To: header line for Message Disposition Notification.
        UIDL computation will no longer include X- headerlines, as they may be added by some mailreaders.
        '%' is allowed as delimiter instead of @ in a virtual username (email address)
        Minor internal changes.
        Additional support for the virtdomain.pl by the author (how to find the mailbox)
18/Oct/2002 0.9.9-3 Jørgen Thomsen jth@jth.net, http://jth.net/
	Corrected an error when a bad mailbox did not contain 'From ' as first line.
05/Sep/2002 0.9.9-2 Jørgen Thomsen jth@jth.net, http://jth.net/
        The fix for disk full prevented the changed mailbox to be written to the .new file. It was retained unchanged
04/Sep/2002 0.9.9-1 Jørgen Thomsen jth@jth.net, http://jth.net/
        If the mailbox did not terminate by a line feed (if crash while writing a message into it)
        an infinite loop was occurring. If the mailbox is modified by GNU pop3d, it will be fixed.
        When the disk became full when writing the new mailbox it was not detected and the new mailbox was truncated
19/Aug/2002 0.9.9 Jørgen Thomsen jth@jth.net, http://jth.net/
        Compatibility with vm-pop3d passwd files introduced (not fully tested)
        Added graceful stop by catching the signals (SIGHUP and SIGTERM).
        The final touches and version number changed to 0.9.9
19/Oct/2001 Jørgen Thomsen jth@jth.net, http://jth.net/
        Added Message Disposition Notification (return receipt, RFC 2298)
        Added configure options to avoid editing config.h in most cases
        Changed the update of the mailbox from copying inside the file to creating a new file (mailbox.new)
        if needed and improved the copying inside the file. This improves the speed greatly especially for webmail programs.
        Introduced support for the classical Status: header line RFC 2076 (supported by e.q. Null Webmail
        http://nullwebmail.sourceforge.net/)

17/Oct/2001 Jørgen Thomsen jth@jth.net, http://jth.net/
        Added an old patch for better handling of children processes creation and death.
        Now child processes are created as needed and only the parent process is permanent.

   

VirtDomain 1.03

The web GUI interface is functional for both standard Postfix virtual domains and my flavour: jth virtual domains. It comes as a single Perl program, whcih is called from the commandline to create a virtual domain and from the webserver to administer it. Requires a recent release of Postfix VirtDomain 1.03

#!/usr/bin/perl -w
#**********************************************************************
#
# Utility to administer virtual domains in postfix (both the standard
# ones and those defined in http://jth.net/virtual.html)
#
# This program should reside in /var/www/cgi-bin/virtdomain.pl with global
# read and execute rights (chmod o+rx /var/www/cgi-bin/virtdomain.pl).
#
# Remember to define $main::postfixadmin below !
#
# The first argument to the program determines its function:

# CREATE:  call from commandline as root: create virtual domain by updating
#          /etc/postfix/virtual and virtual_regexp
#          and creating /etc/virtual/domain/passwd and /var/spool/virtual/domain
#          CREATE <domain name> <real user administering the domain>
#                               <passwd> [postfix]

# DELETE:  call from commandline as root: delete virtual domain by updating
#          /etc/postfix/virtual and virtual_regexp
#          and deleting /etc/virtual/domain/passwd and /var/spool/virtual/domain as
#          well as .forward files in the administrators homedir
#          DELETE <domain name> <real user administering the domain> <passwd>

# <blank>
# MAILBOUNCE
#          if called from postfix as mail to user@domain the email on STDIN will be processed
#          according to the setup of the user in /etc/virtual/domain/passwd.
#          MAILBOUNCE: bounce email to unknown users otherwise store in postmaster mailbox

# <blank>  if called from postfix as mail to postmaster@domain or <postfixadmin+postmaster>
#          with the subject "*** Virtual domain update ***" and line 1 is trans=UPDATE....
#          a user will be created/updated/deleted
#          otherwise process email normally as above

# <blank>: if called from a web server displays webpages to update the user
#          base in a virtual domain e,g, http://jth.net/cgi-bin/virtdomain.pl

#
# As a basis the user postmaster must be defined for the domain.
# in the /etc/virtual/domain/passwd file. The user and group ids as
# well as homedir from this user is used for the virtual domain.
# For each virtual user the file homedir/.forward+user--domain is created.
# The web server should have read access to these files as well as
# the /etc/virtual/domain/passwd file.
# The GNU pop3d deamon as maintained by me is supporting this
# virtual domain implementation.
#
# Using this program to deliver the mail for jth style domains is not suitable for
# a high volume system, as loading the Perl interpreter
# has a fairly high initial CPU usage compared to this program (90% of total run time).
# However, using the provision for hooking in another program to deliver the mail
# may be useful. An awk utility may be used instead virtual.awk
#
# ©2002 Jørgen Thomsen jth@jth.net, http://jth.net/virtual.html
# 1.01  2002-08-22 Official release
# 1.02  2003-01-24 Support for new virtual_alias_map parameter and relay_domains behaviour
# 1.03  2003-04-26 Better language support and fix webmail URL in info
#
#**********************************************************************
   

Changes to GNU pop3d 0.9.8 
(including some changes not related to virtual domains e.g. POP-before-SMTP)

Based on my own needs I have made a patch for GNU-pop3d vers. 0.9.8
I also listened to some of the requests on the GNU pop3d mailing list.
The patch may be applied also if you don't need the virtual domain stuff. 

Basicallly I took the virtual-patch by Jeremy Reed, made it more general and added my own GNU pop3d changes:

The search for a users mailbox is performed as

  1. search MAILSPOOLHOME (e.g. /home/user/Mail/mailbox)
  2. search _MAILDIR (e.g. /var/mail/user)
  3. search VIRTUAL_MAILDIR (e.g. /var/spool/virtual/domain/user)
  4. give up and use /dev/null

Patching GNU pop3d

In stead of everybody applying the patches I have done it.

  1. Download the patched source gnu-pop3d-0.9.8.10j8.tar.gz
  2. Create the config.h file by
    ./configure --enable-virtual-domains
    or./configure --enable-ip-based-virtual
  3. If needed/wanted define MAILSPOOLHOME (e.g. "/Mail/mailbox") and/or DEFAULT_DOMAIN in config.h
  4. Compile by executing make

The technical changes 

Implementing virtual domains in Postfix and GNU pop3d

The reason for not using the standard Postfix virtual domains are twofold:
1) this implementation focuses on virtual domains with each its own administrator
2) the following limitations (quote from the Postfix documentation (my emphasis)):
This agent was originally based on the Postfix local delivery agent. Modifications mainly consisted of removing code that either was not applicable or that was not safe in this context: aliases, ~user/.forward files, delivery to "|command" or to /file/name

The following shows one way of implementing a virtual domain, kvt.dk, in Postfix and GNU pop3d.
A real user kvt_dk has been defined on the system. The home directory of this user contains some data for the virtual domain kvt.dk.
Two users are defined at kvt.dk: abc@kvt.dk (virtual user only) and kvt@kvt.dk (real user kvt_dk at the mail server)
The implementation is based upon Redhat Linux 7.0
 

GNU pop3d

Jeremy Reeds original description of the virtual patch

The virtual patch assumes the following file structures:
/etc/virtual/<domain>/passwd
 for the definition of users, passwords and mailbox directory

In this example create the directory /etc/virtual/kvt.dk

The default mailbox for a virtual user is
/var/spool/virtual/<domain>/<user>

In this example create the directory /var/spool/virtual/kvt.dk

At my server the mail is stored in the user's homedir /home/<usr>/Mail/mailbox requiring the definition of MAILSPOOLHOME in config.h.
I also have only one IP-address and want my main domain "jth.net" to be automatically stripped from mail requests to GNU pop3d.

I generated the config.h file by the command

./configure --enable-virtual-domains --enable-maildir --enable-language=DA --enable-default-domain=jth.net

Before compiling GNU pop3d I made sure the following constants were defined in config.h:

#define MAILSPOOLHOME "/Mail/mailbox"
#define USE_VIRTUAL 1
#define DEFAULT_DOMAIN "jth.net"

/etc/virtual/kvt.dk/passwd

Create this file with the following contents
kvt:kvtpasswd:601:100:kvtname:/home/kvt_dk/:
abc:abcpasswd:601:100:abcname:.:

601 is the userid of the kvt_dk user. 100 is the groupid (group mail at my server). The '.' homedir for abc is just to make pwck happy.
Mail for kvt@kvt.dk is delivered to /home/kvt_dk/Mail/mailbox (see below).
Mail for abc@kvt.dk is delivered to /var/spool/virtual/kvt.dk/abc

If you trust the kvt_dk user, then create the passwd file in the home directory of the user kvt_dk. and link it into the /etc/virtual/kvt.dk directory
ln -s /home/kvt_dk/passwd /etc/virtual/kvt.dk/passwd

Note, that there might be a security risk here, because GNU pop3d will execute with any userid specified in the passwd file. Whether this is a real threat remains to be analyzed.

The owner and permissions on the files and directories should be kvt_dk.mail and 700 e.g
chmod 700 /etc/virtual/kvt.dk /etc/virtual/kvt.dk/passwd /var/spool/virtual/kvt.dk
chown kvt_dk.100 /etc/virtual/kvt.dk /etc/virtual/kvt.dk/passwd /var/spool/virtual/kvt.dk

Postfix

This implementation may be more complex than other ones, but it allows different administrators of each virtual domain keeping everything in the home directory of the domain administrator.

/etc/postfix/main.cf

recipient_delimiter = +
home_mailbox = Mail/mailbox
allow_mail_to_commands = forward
allow_mail_to_files = forward

/home/kvt_dk

-rw-r--r--    1 kvt_dk   mail    12 Dec 10 02:52 .forward
-rw-r--r--    1 kvt_dk   mail    25 Dec 10 01:55 .forward+abc--kvt.dk
-rw-r--r--    1 kvt_dk   mail    20 Dec 10 02:53 .forward+kvt--kvt.dk

/home/kvt_dk/.forward

|"exit 67"

Bounce any message not for abc@kvt.dk or kvt@kvt.dk

/home/kvt_dk/.forward+abc--kvt.dk

|/usr/local/bin/virtual

Deliver all mail for abc@kvt.dk to the virtual domain mailbox for abc changing the Delivered-To: header line to the correct one.

/home/kvt_dk/.forward+kvt--kvt.dk

/home/kvt_dk/Mail/mailbox

Deliver all mail for kvt@kvt.dk to the mailbox of kvt_dk

/etc/postfix/virtual

kvt.dk                    anything
postmaster@kvt.dk         postmaster
webmaster@kvt.dk          jth

The real users: postmaster and jth must receive all mail for the postmaster and webmaster of the virtual domain

/etc/postfix/virtual_regexp

/^(.+)@(.+\.)?(kvt\.dk)$/ kvt_dk+$1--$2$3

This expression will cause postfix to deliver any mail with adresses x@kvt.dk and y@z.kvt.dk to the real user kvt_dk keeping the original envelope recipient as an extension to the new recipient address.

/usr/local/bin/virtual

awk  -F: -f /usr/local/bin/virtual.awk

/usr/local/bin/virtual.awk NEW 2002-04-11

# J. Thomsen 2002-04-11 Postfix utility
# /usr/local/bin/virtual.awk
#
# Used by Postfix for delivering mail to a GNU-pop3d virtual domain
# mailbox.
#
# Postfix will use this utility for delivering a message to the local
# mailbox rewriting the Delivered-To header line to the original recipient
# address.
# 2002-04-11 Fix 'From ' lines in msg body and add empty line to msgs to ensure the separation of messages
#

Deliver  to virtual domain mailbox e.g. abc@def.kvt.dk to /var/spool/virtual/kvt.dk/abc.
The Delivered-To: header is modified to contain the original envelope recipient address (after possible modification by aliases).