481 CREATE OR REPLACE FUNCTION postfix_virtual_alias_map( |
481 CREATE OR REPLACE FUNCTION postfix_virtual_alias_map( |
482 IN localpart varchar, IN the_domain varchar) |
482 IN localpart varchar, IN the_domain varchar) |
483 RETURNS SETOF recipient_destination |
483 RETURNS SETOF recipient_destination |
484 AS $$ |
484 AS $$ |
485 DECLARE |
485 DECLARE |
|
486 recordc recipient_destination; |
486 record recipient_destination; |
487 record recipient_destination; |
|
488 catchall_cursor refcursor; |
487 recipient varchar(320) := localpart || '@' || the_domain; |
489 recipient varchar(320) := localpart || '@' || the_domain; |
488 did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain); |
490 did bigint := (SELECT gid FROM domain_name WHERE domainname=the_domain); |
489 BEGIN |
491 BEGIN |
490 FOR record IN |
492 FOR record IN |
491 SELECT recipient, destination |
493 SELECT recipient, destination |
493 WHERE gid = did |
495 WHERE gid = did |
494 AND address = localpart |
496 AND address = localpart |
495 LOOP |
497 LOOP |
496 RETURN NEXT record; |
498 RETURN NEXT record; |
497 END LOOP; |
499 END LOOP; |
|
500 |
498 IF NOT FOUND THEN |
501 IF NOT FOUND THEN |
499 -- First, we have to check existing mailboxes and |
502 -- There is no matching virtual_alias. If there are no catchall |
500 -- return identity if one exists |
503 -- records for this domain, we can just return NULL since Postfix |
501 FOR record IN |
504 -- will then later consult mailboxes/relocated itself. But if |
502 SELECT recipient, recipient as destination |
505 -- there is a catchall destination, then it would take precedence |
503 FROM users |
506 -- over mailboxes/relocated, which is not what we want. Therefore, |
504 WHERE gid = did |
507 -- we must first find out if the query is for an existing mailbox |
505 AND local_part = localpart |
508 -- or relocated entry and return the identity mapping if that is |
506 UNION SELECT recipient, recipient as destination |
509 -- the case |
507 FROM relocated |
510 OPEN catchall_cursor FOR |
508 WHERE gid = did |
511 SELECT recipient, destination |
509 AND address = localpart |
512 FROM catchall |
510 LOOP |
513 WHERE gid = did; |
511 RETURN NEXT record; |
514 FETCH NEXT FROM catchall_cursor INTO recordc; |
512 END LOOP; |
515 |
513 -- Only now can we think about catchalls... |
516 IF recordc IS NOT NULL THEN |
514 IF NOT FOUND THEN |
517 -- Since there are catchall records for this domain |
|
518 -- check the mailbox and relocated records and return identity |
|
519 -- if a matching record exists. |
515 FOR record IN |
520 FOR record IN |
516 SELECT recipient, destination |
521 SELECT recipient, recipient as destination |
517 FROM catchall |
522 FROM users |
518 WHERE gid = did |
523 WHERE gid = did |
|
524 AND local_part = localpart |
|
525 UNION SELECT recipient, recipient as destination |
|
526 FROM relocated |
|
527 WHERE gid = did |
|
528 AND address = localpart |
519 LOOP |
529 LOOP |
520 RETURN NEXT record; |
530 RETURN NEXT record; |
521 END LOOP; |
531 END LOOP; |
|
532 |
|
533 IF NOT FOUND THEN |
|
534 -- There were no records found for mailboxes/relocated, |
|
535 -- so now we can actually iterate the cursor and populate |
|
536 -- the return set |
|
537 LOOP |
|
538 RETURN NEXT recordc; |
|
539 FETCH NEXT FROM catchall_cursor INTO recordc; |
|
540 EXIT WHEN recordc IS NULL; |
|
541 END LOOP; |
|
542 END IF; |
522 END IF; |
543 END IF; |
|
544 CLOSE catchall_cursor; |
523 END IF; |
545 END IF; |
524 RETURN; |
546 RETURN; |
525 END; |
547 END; |
526 $$ LANGUAGE plpgsql STABLE |
548 $$ LANGUAGE plpgsql STABLE |
527 RETURNS NULL ON NULL INPUT |
549 RETURNS NULL ON NULL INPUT |