Enable interpolation of alias destinations
This patch modifies the virtual_alias_maps function so that the destination
address is parsed for the place holders %n, %d and %=, which are replaced with
the localpart, the domain or the full address with '@' replaced by '=' of the
queried key.
In combination with alias domains, this allows for domain-specific recipients.
E.g. given example.org and its alias domain example.com, defining an alias
postmaster@example.org → postmaster+%d@example.org
will cause mail to postmaster@example.*com* to go to
postmaster+example.*com*@example.org.
--- a/README Wed Apr 11 09:08:19 2012 +0200
+++ b/README Wed Apr 11 16:23:27 2012 +0200
@@ -61,6 +61,13 @@
‣ supports multiple destinations per e-mail alias
‣ destinations can be deleted separately
+ ‣ destinations can be interpolated using the original address' localpart
+ and domain, allowing aliases to have different meaning in aliasdomains,
+ e.g. with the following defined in example.org:
+ postmaster@example.org → postmaster+%d@admin.example.org
+ If example.com is an aliasdomain of example.org, the alias will become
+ postmaster@example.org → postmaster+example.org@admin.example.org
+ postmaster@example.com → postmaster+example.com@admin.example.org
Installation Prerequisites
==========================
--- a/man/de/man1/vmm.1 Wed Apr 11 09:08:19 2012 +0200
+++ b/man/de/man1/vmm.1 Wed Apr 11 16:23:27 2012 +0200
@@ -780,11 +780,21 @@
.IR destination (en),
erstellt.
.PP
+Innerhalb der Zieladresse werden die Zeichenketten
+.IR %n ,
+.IR %d
+und
+.IR %=
+durch den ursprünglichen lokalen Teil, die Domain bzw. die Emailadresse mit
+'=' anstelle von '@' ersetzt. Dies ermöglicht z.B. in Verbindung mit
+Alias-Domains domain-spezifische Empfänger.
+.PP
Beispiele:
.PP
.nf
.B vmm aliasadd john.doe@example.com d.user@example.com
.B vmm aa support@example.com d.user@example.com e.user@example.com
+.B vmm aa postmaster@example.com postmaster+%d@example.org
.fi
.\" ------------------------------------
.SS aliasdelete (ad)
--- a/man/man1/vmm.1 Wed Apr 11 09:08:19 2012 +0200
+++ b/man/man1/vmm.1 Wed Apr 11 16:23:27 2012 +0200
@@ -746,11 +746,21 @@
.I destination
addresses.
.PP
+Within the destination address, the placeholders
+.IR %n ,
+.IR %d ,
+and
+.IR %=
+will be replaced by the local part, the domain, or the email address with '@'
+replaced by '=' respectively. In combination with alias domains, this enables
+domain-specific destinations.
+.PP
Examples:
.PP
.nf
.B vmm aliasadd john.doe@example.com d.user@example.com
.B vmm aa support@example.com d.user@example.com e.user@example.com
+.B vmm aa postmaster@example.com postmaster+%d@example.org
.fi
.\" ------------------------------------
.SS aliasdelete (ad)
--- a/pgsql/create_tables-dovecot-1.2.x.pgsql Wed Apr 11 09:08:19 2012 +0200
+++ b/pgsql/create_tables-dovecot-1.2.x.pgsql Wed Apr 11 16:23:27 2012 +0200
@@ -584,6 +584,25 @@
--
-- For more details see postconf(5) section virtual_alias_maps and virtual(5)
-- ---
+CREATE OR REPLACE FUNCTION _interpolate_destination(
+ IN destination varchar, localpart varchar, IN the_domain varchar)
+ RETURNS varchar
+AS $$
+ DECLARE
+ result varchar(320);
+ BEGIN
+ IF position('%' in destination) = 0 THEN
+ RETURN destination;
+ END IF;
+ result := replace(destination, '%n', localpart);
+ result := replace(result, '%d', the_domain);
+ result := replace(result, '%=', localpart || '=' || the_domain);
+ RETURN result;
+ END;
+$$ LANGUAGE plpgsql STABLE
+RETURNS NULL ON NULL INPUT
+EXTERNAL SECURITY INVOKER;
+
CREATE OR REPLACE FUNCTION postfix_virtual_alias_map(
IN localpart varchar, IN the_domain varchar)
RETURNS SETOF recipient_destination
@@ -596,7 +615,8 @@
did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain);
BEGIN
FOR record IN
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM alias
WHERE gid = did
AND address = localpart
@@ -614,7 +634,8 @@
-- or relocated entry and return the identity mapping if that is
-- the case
OPEN catchall_cursor FOR
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM catchall
WHERE gid = did;
FETCH NEXT FROM catchall_cursor INTO recordc;
--- a/pgsql/create_tables.pgsql Wed Apr 11 09:08:19 2012 +0200
+++ b/pgsql/create_tables.pgsql Wed Apr 11 16:23:27 2012 +0200
@@ -561,6 +561,25 @@
--
-- For more details see postconf(5) section virtual_alias_maps and virtual(5)
-- ---
+CREATE OR REPLACE FUNCTION _interpolate_destination(
+ IN destination varchar, localpart varchar, IN the_domain varchar)
+ RETURNS varchar
+AS $$
+ DECLARE
+ result varchar(320);
+ BEGIN
+ IF position('%' in destination) = 0 THEN
+ RETURN destination;
+ END IF;
+ result := replace(destination, '%n', localpart);
+ result := replace(result, '%d', the_domain);
+ result := replace(result, '%=', localpart || '=' || the_domain);
+ RETURN result;
+ END;
+$$ LANGUAGE plpgsql STABLE
+RETURNS NULL ON NULL INPUT
+EXTERNAL SECURITY INVOKER;
+
CREATE OR REPLACE FUNCTION postfix_virtual_alias_map(
IN localpart varchar, IN the_domain varchar)
RETURNS SETOF recipient_destination
@@ -573,7 +592,8 @@
did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain);
BEGIN
FOR record IN
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM alias
WHERE gid = did
AND address = localpart
@@ -591,7 +611,8 @@
-- or relocated entry and return the identity mapping if that is
-- the case
OPEN catchall_cursor FOR
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM catchall
WHERE gid = did;
FETCH NEXT FROM catchall_cursor INTO recordc;
--- a/pgsql/update_tables_0.5.x-0.6-dovecot-1.2.x.pgsql Wed Apr 11 09:08:19 2012 +0200
+++ b/pgsql/update_tables_0.5.x-0.6-dovecot-1.2.x.pgsql Wed Apr 11 16:23:27 2012 +0200
@@ -481,6 +481,25 @@
-- varchar the_domain
-- Returns: recipient_destination records
-- ---
+CREATE OR REPLACE FUNCTION _interpolate_destination(
+ IN destination varchar, localpart varchar, IN the_domain varchar)
+ RETURNS varchar
+AS $$
+ DECLARE
+ result varchar(320);
+ BEGIN
+ IF position('%' in destination) = 0 THEN
+ RETURN destination;
+ END IF;
+ result := replace(destination, '%n', localpart);
+ result := replace(result, '%d', the_domain);
+ result := replace(result, '%=', localpart || '=' || the_domain);
+ RETURN result;
+ END;
+$$ LANGUAGE plpgsql STABLE
+RETURNS NULL ON NULL INPUT
+EXTERNAL SECURITY INVOKER;
+
CREATE OR REPLACE FUNCTION postfix_virtual_alias_map(
IN localpart varchar, IN the_domain varchar)
RETURNS SETOF recipient_destination
@@ -493,7 +512,8 @@
did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain);
BEGIN
FOR record IN
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM alias
WHERE gid = did
AND address = localpart
@@ -511,7 +531,8 @@
-- or relocated entry and return the identity mapping if that is
-- the case
OPEN catchall_cursor FOR
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM catchall
WHERE gid = did;
FETCH NEXT FROM catchall_cursor INTO recordc;
--- a/pgsql/update_tables_0.5.x-0.6.pgsql Wed Apr 11 09:08:19 2012 +0200
+++ b/pgsql/update_tables_0.5.x-0.6.pgsql Wed Apr 11 16:23:27 2012 +0200
@@ -459,6 +459,25 @@
-- varchar the_domain
-- Returns: recipient_destination records
-- ---
+CREATE OR REPLACE FUNCTION _interpolate_destination(
+ IN destination varchar, localpart varchar, IN the_domain varchar)
+ RETURNS varchar
+AS $$
+ DECLARE
+ result varchar(320);
+ BEGIN
+ IF position('%' in destination) = 0 THEN
+ RETURN destination;
+ END IF;
+ result := replace(destination, '%n', localpart);
+ result := replace(result, '%d', the_domain);
+ result := replace(result, '%=', localpart || '=' || the_domain);
+ RETURN result;
+ END;
+$$ LANGUAGE plpgsql STABLE
+RETURNS NULL ON NULL INPUT
+EXTERNAL SECURITY INVOKER;
+
CREATE OR REPLACE FUNCTION postfix_virtual_alias_map(
IN localpart varchar, IN the_domain varchar)
RETURNS SETOF recipient_destination
@@ -471,7 +490,8 @@
did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain);
BEGIN
FOR record IN
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM alias
WHERE gid = did
AND address = localpart
@@ -489,7 +509,8 @@
-- or relocated entry and return the identity mapping if that is
-- the case
OPEN catchall_cursor FOR
- SELECT recipient, destination
+ SELECT recipient,
+ _interpolate_destination(destination, localpart, the_domain)
FROM catchall
WHERE gid = did;
FETCH NEXT FROM catchall_cursor INTO recordc;