From fb1e6a8b4126365c72d70c92f954755a2f4fbf87 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sat, 27 Jun 2009 09:36:22 +0100 Subject: Force mail to be delivered by the MDA. SF patch 2489938. --- NEWS | 2 ++ esmtprc.5 | 15 +++++++++++ lexer.l | 1 + local.c | 88 ++++++++++++++++++++++++++++++++++++++++++--------------------- local.h | 1 + main.c | 9 ++++--- parser.y | 3 ++- 7 files changed, 86 insertions(+), 33 deletions(-) diff --git a/NEWS b/NEWS index a5dd2b6..ac99852 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ News * Development: + * Option to force local only MDA (Robert A.M. Diamond). + * Use locking in esmtp-wrapper (Phil Sutter). * Update mutt option name in the user manual (Wu Fengguang). diff --git a/esmtprc.5 b/esmtprc.5 index b0bcbd9..415ce0e 100644 --- a/esmtprc.5 +++ b/esmtprc.5 @@ -149,6 +149,21 @@ place an %F. Some common MDAs are "/usr/bin/procmail -d %T", "/usr/bin/deliver" and "/usr/lib/mail.local %T". +.TP +\fBforce_mda\fR +Force mail to be delivered by the MDA. + +When set, any mail from anywhere to anywhere will instead be delivered to the +value of force_mda. It will also only be delivered locally, via the mda. This +will let you have a very minimal mail set-up, which can ONLY handle local mail. + +For example: + +.nf + mda = "procmail -d %T" + force_mda = "\fIsomeuser\fR" +.fi + .SH SEE ALSO esmtp(1) diff --git a/lexer.l b/lexer.l index 668837f..6996a3a 100644 --- a/lexer.l +++ b/lexer.l @@ -69,6 +69,7 @@ reverse_path { return REVERSE_PATH; } sender { return SENDER; } message_id { return MSGID; } mda { return MDA; } +force_mda { return FORCE_MDA; } = { return MAP; } diff --git a/local.c b/local.c index 494d163..e4afa29 100644 --- a/local.c +++ b/local.c @@ -17,13 +17,26 @@ char *mda = NULL; +char *force_mda = NULL; FILE *mda_fp = NULL; int local_address(const char *address) { - return !strchr(address, '@'); + if (!force_mda) + { + /* TODO: + * + * A litle more searching + * Does the regex"[^@]*\@(.*)" resolve to 127.0.0.1 or a local ip? + * + * Maybe it should be delivered locally? + */ + return !strchr(address, '@'); + } + + return 1; } /** replace ' by _ */ @@ -58,40 +71,54 @@ void local_init(message_t *message) /* get user addresses for %T */ if (strstr(before, "%T")) { - struct list_head *ptr; - char *p; - - /* - * We go through this in order to be able to handle very - * long lists of users and (re)implement %s. - */ - nameslen = 0; - list_for_each(ptr, &message->local_recipients) + if (!force_mda) { - recipient_t *recipient = list_entry(ptr, recipient_t, list); - - assert(recipient->address); - - nameslen += (strlen(recipient->address) + 3); /* string + quotes + ' ' */ - } - - names = (char *)xmalloc(nameslen + 1); /* account for '\0' */ - p = names; - list_for_each(ptr, &message->local_recipients) - { - recipient_t *recipient = list_entry(ptr, recipient_t, list); - int written; - - sanitize(recipient->address); - written = sprintf(p, "'%s' ", recipient->address); - if (written < 0) + struct list_head *ptr; + char *p; + + /* + * We go through this in order to be able to handle very + * long lists of users and (re)implement %s. + */ + nameslen = 0; + list_for_each(ptr, &message->local_recipients) + { + recipient_t *recipient = list_entry(ptr, recipient_t, list); + + assert(recipient->address); + + nameslen += (strlen(recipient->address) + 3); /* string + quotes + ' ' */ + } + + names = (char *)xmalloc(nameslen + 1); /* account for '\0' */ + p = names; + list_for_each(ptr, &message->local_recipients) + { + recipient_t *recipient = list_entry(ptr, recipient_t, list); + int written; + + sanitize(recipient->address); + written = sprintf(p, "'%s' ", recipient->address); + if (written < 0) + { + perror(NULL); + exit(EX_OSERR); + } + p += written; + } + names[--nameslen] = '\0'; /* chop trailing space */ + } else { + nameslen = (strlen(force_mda) + 3); // 'force_mda' + names = (char *)xmalloc(nameslen + 1); // 'force_mda'\0 + + // Let's skip sanitization? + // Hope the config isn't evil to us 0.o + if (sprintf(names, "'%s' ", force_mda) < 0) { perror(NULL); exit(EX_OSERR); } - p += written; } - names[--nameslen] = '\0'; /* chop trailing space */ } /* get From address for %F */ @@ -216,4 +243,7 @@ void local_cleanup(void) if(mda) free(mda); + + if(force_mda) + free(force_mda); } diff --git a/local.h b/local.h index 726364a..f2cd0f1 100644 --- a/local.h +++ b/local.h @@ -12,6 +12,7 @@ extern char *mda; +extern char *force_mda; extern FILE *mda_fp; diff --git a/main.c b/main.c index 3023673..87d16ad 100644 --- a/main.c +++ b/main.c @@ -371,15 +371,18 @@ int main (int argc, char **argv) exit (EX_USAGE); } + /* Parse the rc file. + * + * Do this before message_add_recipient; to enable the force_mda recipient + */ + rcfile_parse(rcfile); + /* Add remaining program arguments as message recipients. */ while (optind < argc) message_add_recipient(message, argv[optind++]); identities_init(); - /* Parse the rc file. */ - rcfile_parse(rcfile); - drop_sgids(); message_send(message); diff --git a/parser.y b/parser.y index bc01fb7..b2c7a8f 100644 --- a/parser.y +++ b/parser.y @@ -64,7 +64,7 @@ void yyerror (const char *s); char *sval; } -%token IDENTITY DEFAULT HOSTNAME USERNAME PASSWORD STARTTLS CERTIFICATE_PASSPHRASE PRECONNECT POSTCONNECT MDA QUALIFYDOMAIN HELO FORCE SENDER MSGID REVERSE_PATH +%token IDENTITY DEFAULT HOSTNAME USERNAME PASSWORD STARTTLS CERTIFICATE_PASSPHRASE PRECONNECT POSTCONNECT MDA QUALIFYDOMAIN HELO FORCE SENDER MSGID REVERSE_PATH FORCE_MDA %token MAP @@ -119,6 +119,7 @@ statement : HOSTNAME map STRING { identity->host = xstrdup($3); SET_DEFAULT_IDEN | MSGID map DISABLED { identity->prohibit_msgid = 1; SET_DEFAULT_IDENTITY; } | MSGID map ENABLED { identity->prohibit_msgid = 0; SET_DEFAULT_IDENTITY; } | MDA map STRING { mda = xstrdup($3); } + | FORCE_MDA map STRING { force_mda = xstrdup($3); } | DEFAULT { default_identity = identity; } ; -- cgit v1.2.3-54-g00ecf