584 CREATE OR REPLACE FUNCTION postfix_virtual_alias_map( |
584 CREATE OR REPLACE FUNCTION postfix_virtual_alias_map( |
585 IN localpart varchar, IN the_domain varchar) |
585 IN localpart varchar, IN the_domain varchar) |
586 RETURNS SETOF recipient_destination |
586 RETURNS SETOF recipient_destination |
587 AS $$ |
587 AS $$ |
588 DECLARE |
588 DECLARE |
|
589 recordc recipient_destination; |
589 record recipient_destination; |
590 record recipient_destination; |
|
591 catchall_cursor refcursor; |
590 recipient varchar(320) := localpart || '@' || the_domain; |
592 recipient varchar(320) := localpart || '@' || the_domain; |
591 did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain); |
593 did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain); |
592 BEGIN |
594 BEGIN |
593 FOR record IN |
595 FOR record IN |
594 SELECT recipient, destination |
596 SELECT recipient, destination |
596 WHERE gid = did |
598 WHERE gid = did |
597 AND address = localpart |
599 AND address = localpart |
598 LOOP |
600 LOOP |
599 RETURN NEXT record; |
601 RETURN NEXT record; |
600 END LOOP; |
602 END LOOP; |
|
603 |
601 IF NOT FOUND THEN |
604 IF NOT FOUND THEN |
602 -- First, we have to check existing mailboxes and |
605 -- There is no matching virtual_alias. If there are no catchall |
603 -- return identity if one exists |
606 -- records for this domain, we can just return NULL since Postfix |
604 FOR record IN |
607 -- will then later consult mailboxes/relocated itself. But if |
605 SELECT recipient, recipient as destination |
608 -- there is a catchall destination, then it would take precedence |
606 FROM users |
609 -- over mailboxes/relocated, which is not what we want. Therefore, |
607 WHERE gid = did |
610 -- we must first find out if the query is for an existing mailbox |
608 AND local_part = localpart |
611 -- or relocated entry and return the identity mapping if that is |
609 UNION SELECT recipient, recipient as destination |
612 -- the case |
610 FROM relocated |
613 OPEN catchall_cursor FOR |
611 WHERE gid = did |
614 SELECT recipient, destination |
612 AND address = localpart |
615 FROM catchall |
613 LOOP |
616 WHERE gid = did; |
614 RETURN NEXT record; |
617 FETCH NEXT FROM catchall_cursor INTO recordc; |
615 END LOOP; |
618 |
616 -- Only now can we think about catchalls... |
619 IF recordc IS NOT NULL THEN |
617 IF NOT FOUND THEN |
620 -- Since there are catchall records for this domain |
|
621 -- check the mailbox and relocated records and return identity |
|
622 -- if a matching record exists. |
618 FOR record IN |
623 FOR record IN |
619 SELECT recipient, destination |
624 SELECT recipient, recipient as destination |
620 FROM catchall |
625 FROM users |
621 WHERE gid = did |
626 WHERE gid = did |
|
627 AND local_part = localpart |
|
628 UNION SELECT recipient, recipient as destination |
|
629 FROM relocated |
|
630 WHERE gid = did |
|
631 AND address = localpart |
622 LOOP |
632 LOOP |
623 RETURN NEXT record; |
633 RETURN NEXT record; |
624 END LOOP; |
634 END LOOP; |
|
635 |
|
636 IF NOT FOUND THEN |
|
637 -- There were no records found for mailboxes/relocated, |
|
638 -- so now we can actually iterate the cursor and populate |
|
639 -- the return set |
|
640 LOOP |
|
641 RETURN NEXT recordc; |
|
642 FETCH NEXT FROM catchall_cursor INTO recordc; |
|
643 EXIT WHEN recordc IS NULL; |
|
644 END LOOP; |
|
645 END IF; |
625 END IF; |
646 END IF; |
|
647 CLOSE catchall_cursor; |
626 END IF; |
648 END IF; |
627 RETURN; |
649 RETURN; |
628 END; |
650 END; |
629 $$ LANGUAGE plpgsql STABLE |
651 $$ LANGUAGE plpgsql STABLE |
630 RETURNS NULL ON NULL INPUT |
652 RETURNS NULL ON NULL INPUT |