sendmail+procmail+cyrus, return-path, sieve

Oleg Derevenetz oleg at vsi.ru
Mon Dec 16 12:23:05 EST 2002


Will Partain wrote:

> This scenario, and ones like it, has been discussed here
> before.  I've got something working, so am posting details
> {in case it's useful, so you can tell me I'm an idiot:-)}.
> 
> The 'vacation' bit of sieve wasn't working, because it kept
> seeing a useless 'deliver'-created Return-Path: header.

I wrote a small patch, and it works for me. Code is self-explanatory :-) 
Also I slightly modified deliver.c to realize some sort of DSN and to 
prevent losing of mail messages due to errors.
-------------- next part --------------
*** lmtpengine.c.orig	Sun Nov  3 17:20:10 2002
--- lmtpengine.c	Fri Dec  6 21:53:49 2002
***************
*** 1059,1067 ****
  	m->id = NULL;		/* no message-id */
      }
  
!     if (!m->return_path &&
  	(body = msg_getheader(m, "return-path"))) {
  	/* let's grab return_path */
  	m->return_path = xstrdup(body[0]);
  	clean822space(m->return_path);
  	clean_retpath(m->return_path);
--- 1059,1070 ----
  	m->id = NULL;		/* no message-id */
      }
  
!     if (!(func->addretpath) &&
  	(body = msg_getheader(m, "return-path"))) {
  	/* let's grab return_path */
+ 	if (m->return_path) {
+ 	    free(m->return_path);
+ 	}
  	m->return_path = xstrdup(body[0]);
  	clean822space(m->return_path);
  	clean_retpath(m->return_path);
-------------- next part --------------
*** deliver.c.orig	Fri Aug  2 20:54:48 2002
--- deliver.c	Thu Dec  5 15:05:45 2002
***************
*** 58,63 ****
--- 58,64 ----
  #include <syslog.h>
  #include <com_err.h>
  #include <errno.h>
+ #include <sysexits.h>
  #include <pwd.h>
  #include <sys/types.h>
  
***************
*** 101,109 ****
  	    "421-4.3.0 usage: deliver [-C <alt_config> ] [-m mailbox]"
  	    " [-a auth] [-r return_path] [-l] [-D]\r\n");
      fprintf(stderr, "421 4.3.0 %s\n", CYRUS_VERSION);
!     exit(EC_USAGE);
  }
  
  void fatal(const char* s, int code)
  {
      prot_printf(deliver_out,"421 4.3.0 deliver: %s\r\n", s);
--- 102,183 ----
  	    "421-4.3.0 usage: deliver [-C <alt_config> ] [-m mailbox]"
  	    " [-a auth] [-r return_path] [-l] [-D]\r\n");
      fprintf(stderr, "421 4.3.0 %s\n", CYRUS_VERSION);
!     exit(EX_TEMPFAIL);
  }
  
+ char *convert_lmtp(int r)
+ {
+     switch (r) {
+     case 0:
+ 	return "250 2.1.5 Ok";
+ 	
+     case IMAP_IOERROR:
+ 	return "451 4.3.0 System I/O error";
+ 
+     case IMAP_SERVER_UNAVAILABLE:
+ 	return "451 4.4.0 Remote server unavailable";
+ 
+     case IMAP_NOSPACE:
+ 	return "451 4.3.1 cannot create file: out of space";
+ 
+     case IMAP_AGAIN:
+ 	return "451 4.3.0 transient system error";
+ 		
+     case IMAP_PERMISSION_DENIED:
+ 	return "550 5.7.1 Permission denied";
+ 
+     case IMAP_QUOTA_EXCEEDED:
+ 	return "552 5.2.2 Over quota";
+ 
+     case IMAP_MAILBOX_BADFORMAT:
+     case IMAP_MAILBOX_NOTSUPPORTED:
+ 	return "451 4.2.0 Mailbox has an invalid format";
+ 
+     case IMAP_MESSAGE_CONTAINSNULL:
+ 	return "554 5.6.0 Message contains NUL characters";
+ 	
+     case IMAP_MESSAGE_CONTAINSNL:
+ 	return "554 5.6.0 Message contains bare newlines";
+ 
+     case IMAP_MESSAGE_CONTAINS8BIT:
+ 	return "554 5.6.0 Message contains non-ASCII characters in headers";
+ 
+     case IMAP_MESSAGE_BADHEADER:
+ 	return "554 5.6.0 Message contains invalid header";
+ 
+     case IMAP_MESSAGE_NOBLANKLINE:
+ 	return "554 5.6.0 Message has no header/body separator";
+ 
+     case IMAP_MAILBOX_NONEXISTENT:
+ 	/* XXX Might have been moved to other server */
+ 	return "550 5.1.1 User unknown";
+     }
+ 
+     /* Some error we're not expecting. */
+     return "554 5.0.0 Unexpected internal error";
+ }
+ 
+ /* This will always return fatal error codes due to call in RCPT_PERMFAIL state */
+ static int convert_sysexit_fatal (int r)
+ {
+     switch (r) {
+ 	case IMAP_MESSAGE_CONTAINSNULL:
+ 	case IMAP_MESSAGE_CONTAINSNL:
+ 	case IMAP_MESSAGE_CONTAINS8BIT:
+ 	case IMAP_MESSAGE_BADHEADER:
+ 	case IMAP_MESSAGE_NOBLANKLINE:
+ 	    return EX_DATAERR;
+ 	    
+ 	case IMAP_QUOTA_EXCEEDED:
+ 	    return EX_UNAVAILABLE;
+ 	
+ 	case IMAP_MAILBOX_NONEXISTENT:
+ 	    return EX_NOUSER;
+     }
+     
+     return EX_UNAVAILABLE;
+ }
+ 
  void fatal(const char* s, int code)
  {
      prot_printf(deliver_out,"421 4.3.0 deliver: %s\r\n", s);
***************
*** 120,126 ****
  
      len = read(in, buf, sizeof(buf)-1);
      if (len == -1) {
! 	exit(EC_IOERR);
      }
      if (len == 0) {
  	exit(0);
--- 194,200 ----
  
      len = read(in, buf, sizeof(buf)-1);
      if (len == -1) {
! 	exit(EX_TEMPFAIL);
      }
      if (len == 0) {
  	exit(0);
***************
*** 130,136 ****
         xxx can cause deadlock??? */
      do {
  	cnt = write(out, buf+amnt,len-amnt);
!     	if (cnt == -1) exit(EC_IOERR);
  	amnt += cnt;
      } while (amnt<len);
  
--- 204,210 ----
         xxx can cause deadlock??? */
      do {
  	cnt = write(out, buf+amnt,len-amnt);
!     	if (cnt == -1) exit(EX_TEMPFAIL);
  	amnt += cnt;
      } while (amnt<len);
  
***************
*** 166,172 ****
  	nfound = select(highest, &rset, &wset, NULL, NULL);
  	if (nfound < 0) {
  	    if (errno == EINTR) continue;
! 	    exit(EC_IOERR);
  	}
  
  	if ((FD_ISSET(lmtp_in,&rset))  && (FD_ISSET(local_out,&wset))) {
--- 240,246 ----
  	nfound = select(highest, &rset, &wset, NULL, NULL);
  	if (nfound < 0) {
  	    if (errno == EINTR) continue;
! 	    exit(EX_TEMPFAIL);
  	}
  
  	if ((FD_ISSET(lmtp_in,&rset))  && (FD_ISSET(local_out,&wset))) {
***************
*** 289,295 ****
  {
      com_err(msg, 0, error_message(errno));
  
!     fatal(msg, EC_CONFIG);
  }
  
  /* initialize the network 
--- 363,369 ----
  {
      com_err(msg, 0, error_message(errno));
  
!     fatal(msg, EX_TEMPFAIL);
  }
  
  /* initialize the network 
***************
*** 369,375 ****
      lmtp_disconnect(conn);
  
      /* examine txn for error state */
!     r = 0;
      for (j = 0; j < txn->rcpt_num; j++) {
  	switch (txn->rcpt[j].result) {
  	case RCPT_GOOD:
--- 443,449 ----
      lmtp_disconnect(conn);
  
      /* examine txn for error state */
!     r = EX_OK;
      for (j = 0; j < txn->rcpt_num; j++) {
  	switch (txn->rcpt[j].result) {
  	case RCPT_GOOD:
***************
*** 376,391 ****
  	    break;
  
  	case RCPT_TEMPFAIL:
! 	    r = EC_TEMPFAIL;
  	    break;
  
  	case RCPT_PERMFAIL:
! 	    /* we just need any permanent failure, though we should
! 	       probably return data from the client-side LMTP info */
! 	    printf("%s: %s\n", 
! 		   txn->rcpt[j].addr, error_message(txn->rcpt[j].r));
! 	    if (r != EC_TEMPFAIL) {
! 		r = EC_DATAERR;
  	    }
  	    break;
  	}
--- 450,465 ----
  	    break;
  
  	case RCPT_TEMPFAIL:
! 	    printf(">>> RCPT TO: %s\n", txn->rcpt[j].addr);
! 	    printf("<<< %s\n", convert_lmtp(txn->rcpt[j].r));
! 	    r = EX_TEMPFAIL;
  	    break;
  
  	case RCPT_PERMFAIL:
! 	    printf(">>> RCPT TO: %s\n", txn->rcpt[j].addr);
! 	    printf("<<< %s\n", convert_lmtp(txn->rcpt[j].r));
! 	    if (r != EX_TEMPFAIL) {
! 		r = convert_sysexit_fatal(txn->rcpt[j].r);
  	    }
  	    break;
  	}


More information about the Info-cyrus mailing list