HaveFun.cz

HaveMail


HaveMail is a web administration for virtual mailboxes in Postfix and Dovecot.

Screenshots

Features

Configuration

This configuration should work in RHEL6. These examples show only how to connect Postfix and Dovecot with HaveMail, this is not a complete mail server setup.

Create tables in database:

CREATE TABLE IF NOT EXISTS `mail_alias` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`domain_id` int(11) NOT NULL,
`user` varchar(100) COLLATE utf8_czech_ci NOT NULL,
`target` varchar(100) COLLATE utf8_czech_ci NOT NULL,
`save_copy` tinyint(1) NOT NULL DEFAULT '1',
`enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `alias_ibfk_1` (`domain_id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `mail_domain` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_czech_ci NOT NULL,
`enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `mail_mailbox` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`domain_id` int(11) NOT NULL,
`user` varchar(100) COLLATE utf8_czech_ci NOT NULL,
`password` varchar(100) COLLATE utf8_czech_ci NOT NULL,
`quota` bigint(11) NOT NULL DEFAULT '10240',
`messages` bigint NOT NULL,
`smtp_allowed` tinyint(1) NOT NULL DEFAULT '1',
`imap_allowed` tinyint(1) NOT NULL DEFAULT '1',
`pop3_allowed` tinyint(1) NOT NULL DEFAULT '1',
`sieve_allowed` tinyint(1) NOT NULL DEFAULT '1',
`enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `domain_id` (`domain_id`,`user`)
) ENGINE=InnoDB;

ALTER TABLE `mail_alias`
ADD CONSTRAINT `alias_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `mail_domain` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `mail_mailbox`
ADD CONSTRAINT `mailbox_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `mail_domain` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

Create users for Postfix, Dovecot and HaveMail:

GRANT SELECT ON mail_domain TO 'postfix'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT (id, domain_id, user, enabled) ON mail_mailbox TO 'postfix'@'localhost';
GRANT SELECT (id, domain_id, user, target, save_copy, enabled) ON mail_alias TO 'postfix'@'localhost';

GRANT SELECT ON mail_domain TO 'dovecot'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT (id, domain_id, user, password, quota, messages, smtp_allowed, imap_allowed, pop3_allowed, sieve_allowed, enabled) ON mail_mailbox TO 'dovecot'@'localhost';

GRANT USAGE ON *.* TO 'havemail'@'localhost' IDENTIFIED BY  'password';
GRANT ALL PRIVILEGES ON  `mail`.* TO  'havemail'@'localhost';

Postfix

Edit /etc/postfix/main.cf and set:

virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql/vdomains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql/vmailbox.cf
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql/virtual.cf

Now create those files:

mkdir /etc/postfix/mysql

/etc/postfix/mysql/domains.cf:

hosts = unix:/var/lib/mysql/mysql.sock 
user = postfix
password = password
dbname = mail

query = SELECT 1 FROM mail_domain WHERE name='%s' AND enabled=1

/etc/postfix/mysql/vmailbox.cf:

hosts = unix:/var/lib/mysql/mysql.sock
user = postfix
password = password
dbname = mail

query = SELECT CONCAT(d.name, '/', mb.user, '/')
  FROM mail_mailbox mb INNER JOIN mail_domain d ON mb.domain_id = d.id
  WHERE mb.enabled=1 AND d.enabled=1 AND mb.user='%u' AND d.name='%d'

/etc/postfix/mysql/virtual.cf:

hosts = unix:/var/lib/mysql/mysql.sock
user = postfix
password = password
dbname = mail

query = SELECT a.target FROM mail_alias a INNER JOIN mail_domain d ON a.domain_id = d.id
  WHERE a.enabled=1 AND d.enabled=1 AND a.user='%u' AND d.name='%d'
  UNION
  SELECT CONCAT(a.user, '@', d.name) AS target FROM mail_alias a INNER JOIN mail_domain d ON a.domain_id = d.id
  WHERE a.enabled=1 AND d.enabled=1 AND a.user='%u' AND d.name='%d' AND save_copy=1

Dovecot

/etc/dovecot/conf.d/acl-dict-sql.conf.ext:

connect = host=/var/lib/mysql/mysql.sock dbname=mail user=dovecot password=password

map {
  table = acls
  pattern = shared/shared-boxes/user/$to/$from
  value_field = valid
  fields {
    mbfrom = $from
    mbto = $to
  }
}

map {
  pattern = shared/shared-boxes/anyone/$from
  table = anyone_shares
  value_field = valid

  fields {
    mbfrom = $from
  }
}

/etc/dovecot/conf.d/auth-sql.conf.ext:

connect = host=/var/lib/mysql/mysql.sock dbname=mail user=dovecot password=password

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = prefetch
}

# This is for LDA, since prefetch itself is not enough
userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

/etc/dovecot/dovecot-sql.conf.ext:

default_pass_scheme = PLAIN
driver = mysql
connect = host=/var/lib/mysql/mysql.sock dbname=mail user=dovecot password=password

password_query = SELECT mb.password AS password, '%u' AS user, \
  200 AS userdb_uid, 200 AS userdb_gid, '/var/mail/virtual/%d/%n' AS userdb_home, \
  CONCAT('*:storage=', quota, 'k') AS userdb_quota_rule, \
  CONCAT('*:messages=', messages) AS userdb_quota_rule2 \
  FROM mail_mailbox mb INNER JOIN mail_domain d ON mb.domain_id = d.id \
  WHERE mb.enabled = 1 AND %s_allowed = 1 \
  AND d.enabled = 1 AND mb.user = '%n' AND d.name = '%d'

user_query = SELECT 200 AS uid, 200 AS gid, '/var/mail/virtual/%d/%n' AS home, \
  CONCAT('*:storage=', quota, 'k') AS quota_rule, \
  CONCAT('*:messages=', messages) AS quota_rule2 \
  FROM mail_mailbox mb INNER JOIN mail_domain d ON mb.domain_id = d.id \
  WHERE mb.enabled = 1 AND d.enabled = 1 AND mb.user = '%n' AND d.name = '%d' AND d.name = '%d'

HaveMail

Edit settings.py – configure database, TEMPLATE_DIRS, MAIL_PROTOCOLS and JABBER_DOMAINS. Databases for ejabberd needs to be created manually.

License

HaveMail is released under GNU/GPL.

Used technologies

Written in Python with Django framework, MySQL.

Download

https://secure.havefun.cz/~aither/pub/releases/havemail.tar.gz