Ok, here is it.  I tried to make a very complete description here; hope you
like it.

-- 
Robert Millan
diff -Nur qpsmtpd-0.32.old/config.sample/plugins 
qpsmtpd-0.32/config.sample/plugins
--- qpsmtpd-0.32.old/config.sample/plugins      2006-02-26 13:22:16.000000000 
+0100
+++ qpsmtpd-0.32/config.sample/plugins  2006-06-19 19:41:30.737265480 +0200
@@ -26,6 +26,8 @@
 check_badrcptto
 check_spamhelo
 
+# redirect_local
+
 # sender_permitted_from
 
 # this plugin needs to run after all other "rcpt" plugins
diff -Nur qpsmtpd-0.32.old/lib/Qpsmtpd/Constants.pm 
qpsmtpd-0.32/lib/Qpsmtpd/Constants.pm
--- qpsmtpd-0.32.old/lib/Qpsmtpd/Constants.pm   2006-02-26 13:22:16.000000000 
+0100
+++ qpsmtpd-0.32/lib/Qpsmtpd/Constants.pm       2006-06-19 19:24:13.873892672 
+0200
@@ -23,6 +23,7 @@
        DENYHARD => 903,   # 550 + disconnect  (deprecated in 0.29)
        DENY_DISCONNECT     => 903, # 550 + disconnect
        DENYSOFT_DISCONNECT => 904, # 450 + disconnect
+       REDIRECT => 905, # 551
        DECLINED => 909,
        DONE     => 910,
 );
diff -Nur qpsmtpd-0.32.old/lib/Qpsmtpd/DSN.pm qpsmtpd-0.32/lib/Qpsmtpd/DSN.pm
--- qpsmtpd-0.32.old/lib/Qpsmtpd/DSN.pm 2006-02-26 13:22:16.000000000 +0100
+++ qpsmtpd-0.32/lib/Qpsmtpd/DSN.pm     2006-06-19 19:24:13.873892672 +0200
@@ -172,7 +172,7 @@
 
 sub addr_unspecified { shift->_dsn(shift,shift,DENYSOFT,1,0); }
 
-=item no_such_user, addr_bad_dest_mbox
+=item no_such_user, addr_bad_dest_mbox, user_not_local
 
 X.1.1
 default: DENY
@@ -181,6 +181,7 @@
 
 sub no_such_user         { shift->_dsn(shift,(shift||"No such 
user"),DENY,1,1); }
 sub addr_bad_dest_mbox   { shift->_dsn(shift,shift,DENY,1,1); }
+sub user_not_local       { shift->_dsn(shift,shift,REDIRECT,1,1); }
 
 =item addr_bad_dest_system 
 
diff -Nur qpsmtpd-0.32.old/lib/Qpsmtpd/SMTP.pm qpsmtpd-0.32/lib/Qpsmtpd/SMTP.pm
--- qpsmtpd-0.32.old/lib/Qpsmtpd/SMTP.pm        2006-02-26 13:22:16.000000000 
+0100
+++ qpsmtpd-0.32/lib/Qpsmtpd/SMTP.pm    2006-06-19 19:24:13.874892520 +0200
@@ -355,6 +355,9 @@
     $self->respond(421, $msg);
     $self->disconnect;
   }
+  elsif ($rc == REDIRECT) {
+    $self->respond(551, $msg);
+  }
   elsif ($rc == OK) {
     $self->respond(250, $rcpt->format . ", recipient ok");
     return $self->transaction->add_recipient($rcpt);
diff -Nur qpsmtpd-0.32.old/plugins/redirect_local 
qpsmtpd-0.32/plugins/redirect_local
--- qpsmtpd-0.32.old/plugins/redirect_local     1970-01-01 01:00:00.000000000 
+0100
+++ qpsmtpd-0.32/plugins/redirect_local 2006-06-19 19:40:02.984605912 +0200
@@ -0,0 +1,41 @@
+# This plugin checks for ~/.redirect.  If it exists, it uses the recipient
+# address contained there to inform the sender that this user is actualy
+# somewhere else.  This is specialy useful as an alternative for traditional
+# forwarding because:
+#
+# - It doesn't break when the sender has published SPF records.
+# - It gives the final recipient's MTA a chance to perform its own 
delivery-time
+#   anti-spam checks (greylisting, spf, etc), in addition to whatever checks we
+#   have (or have not) performed on our side.
+#
+# Note that ATTOW most senders will not automaticaly redirect their mail to the
+# final recipient.  In that case, a sane MTA would generate an MDN, informing
+# the user of the new recipient address.  RFC 2821 says that you must not 
assume
+# this will actualy happen, though, so you do it on your own responsability.
+#
+# From RFC 2821, section 3.4:
+#
+#   *  Servers MAY reject or bounce messages when they are not
+#      deliverable when addressed.  When they do so, they MAY either
+#      provide address-updating information with a 551 code, or may
+#      reject the message as undeliverable with a 550 code and no
+#      address-specific information.  But, if a 551 code is used, they
+#      MUST NOT assume that the client will actually update address
+#      information or even return that information to the user.
+
+use Qpsmtpd::DSN;
+use File::HomeDir;
+
+sub hook_rcpt {
+  my ($self, $transaction, $recipient) = @_;
+
+  # Check for ~/.redirect
+  if (open (REDIR, home(lc($recipient->user)) . "/.redirect")) {
+    my ($redir) = <REDIR>;
+    close(REDIR);
+    chomp ($redir);
+    return Qpsmtpd::DSN->user_not_local("User not local; please try <$redir>");
+  }
+
+  return (OK);
+}

Reply via email to