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