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