summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Fonseca <jrfonseca@users.sourceforge.net>2003-02-11 00:09:16 +0000
committerJosé Fonseca <jrfonseca@users.sourceforge.net>2003-02-11 00:09:16 +0000
commitfb836eb1e24d9d1f2e39aea9909fc5e0a7e595d3 (patch)
tree573a30710b9f66eb90b2a1e95b14e09774a0ab82
parente70f6ebca12dd63941d02c73797dfb68deb65f20 (diff)
Support for identities and custom configuration files based on patch by Jerome
<freejazz@gmx.fr>. Respective documentation updates. The use of '=' in the configuration file was made optional.
-rw-r--r--NEWS17
-rw-r--r--TODO1
-rw-r--r--esmtp.14
-rw-r--r--esmtp.h30
-rw-r--r--lexer.l1
-rw-r--r--main.c64
-rw-r--r--parser.y83
-rw-r--r--sample.esmtprc46
8 files changed, 194 insertions, 52 deletions
diff --git a/NEWS b/NEWS
index e69de29..b77d803 100644
--- a/NEWS
+++ b/NEWS
@@ -0,0 +1,17 @@
+Version 0.3
+
+ * Capability to generate log files.
+ * Better verbose output.
+ * Minor bug fixes and documentation enhancements.
+ * Multiple identities.
+
+Version 0.2:
+
+ * Packaging corrections.
+ * Minor bug fixes and documentation enhancements.
+ * Use sendmail exit codes.
+
+
+Version 0.1:
+
+ * Initial release
diff --git a/TODO b/TODO
index d2cfa56..0b74cb8 100644
--- a/TODO
+++ b/TODO
@@ -1 +1,2 @@
- handle the '-t' option
+- safer memory allocation
diff --git a/esmtp.1 b/esmtp.1
index 2fd7e6d..4d46ea5 100644
--- a/esmtp.1
+++ b/esmtp.1
@@ -137,7 +137,6 @@ Verify names only \- do not try to collect or deliver a message.
.TP
.BI \-C file
-(ignored)
Use alternate configuration file.
.TP
@@ -160,6 +159,9 @@ if that header is missing during initial submission.
The envelope sender address is used as the recipient
for delivery status notifications
and may also appear in a Return-Path: header.
+.PP
+This address is also used to select from different identities in the
+configuration file.
.TP
.BI \-G
diff --git a/esmtp.h b/esmtp.h
new file mode 100644
index 0000000..7c61e9a
--- /dev/null
+++ b/esmtp.h
@@ -0,0 +1,30 @@
+/*
+ * esmtp.h - global declarations
+ */
+
+typedef struct {
+ char *identity;
+ char *host;
+ char *user;
+ char *pass;
+ enum starttls_option starttls; /* it should default to Starttls_DISABLED */
+ char *certificate_passphrase;
+} identity_t;
+
+extern identity_t default_identity;
+
+typedef struct identity_list_rec identity_list_t;
+
+struct identity_list_rec {
+ identity_list_t *next;
+ identity_t identity;
+} ;
+
+extern identity_list_t *identities_head, **identities_tail;
+
+
+extern char *rcfile;
+
+
+extern void parse_rcfile(void);
+
diff --git a/lexer.l b/lexer.l
index ef550e7..530e622 100644
--- a/lexer.l
+++ b/lexer.l
@@ -54,6 +54,7 @@ void escapes(const char *tp, char *cp);
+identity { BEGIN(NAME); return IDENTITY; }
host(name)? { BEGIN(NAME); return HOSTNAME; }
user(name)? { BEGIN(NAME); return USERNAME; }
pass(word)? { BEGIN(NAME); return PASSWORD; }
diff --git a/main.c b/main.c
index a8a1c65..f34a852 100644
--- a/main.c
+++ b/main.c
@@ -37,14 +37,19 @@
#include <auth-client.h>
#include <libesmtp.h>
-char *from = NULL;
-char *host = NULL;
-char *user = NULL;
-char *pass = NULL;
-enum starttls_option starttls = Starttls_DISABLED;
-char *certificate_passphrase = NULL;
+#include "esmtp.h"
-extern void parse_rcfile(void);
+/* Identity management */
+identity_t default_identity = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ Starttls_DISABLED,
+ NULL
+};
+
+identity_list_t *identities_head = NULL, **identities_tail = &identities_head;
/* Callback function to read the message from a file. Since libESMTP does not
* provide callbacks which translate line endings, one must be provided by the
@@ -197,14 +202,18 @@ void version (void)
int authinteract (auth_client_request_t request, char **result, int fields,
void *arg)
{
+ identity_t *identity = (identity_t *)arg;
int i;
+ if(!identity)
+ return 0;
+
for (i = 0; i < fields; i++)
{
- if (request[i].flags & AUTH_USER && user)
- result[i] = user;
- else if (request[i].flags & AUTH_PASS && pass)
- result[i] = pass;
+ if (request[i].flags & AUTH_USER && identity->user)
+ result[i] = identity->user;
+ else if (request[i].flags & AUTH_PASS && identity->pass)
+ result[i] = identity->pass;
else
return 0;
}
@@ -213,12 +222,16 @@ int authinteract (auth_client_request_t request, char **result, int fields,
int tlsinteract (char *buf, int buflen, int rwflag, void *arg)
{
+ identity_t *identity = (identity_t *)arg;
char *pw;
int len;
- if (certificate_passphrase)
+ if(!identity)
+ return 0;
+
+ if (identity->certificate_passphrase)
{
- pw = certificate_passphrase;
+ pw = identity->certificate_passphrase;
len = strlen (pw);
if (len + 1 > buflen)
return 0;
@@ -251,13 +264,17 @@ int main (int argc, char **argv)
int ret;
enum notify_flags notify = Notify_NOTSET;
FILE *fp = NULL;
+ identity_t *identity = &default_identity;
+ char *from = NULL;
+ identity_list_t *p;
/* Parse the rc file. */
parse_rcfile();
/* This program sends only one message at a time. Create an SMTP session.
*/
- auth_client_init (); session = smtp_create_session ();
+ auth_client_init ();
+ session = smtp_create_session ();
while ((c = getopt (argc, argv,
"A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:")) != EOF)
@@ -273,6 +290,7 @@ int main (int argc, char **argv)
case 'C':
/* Select configuration file */
+ rcfile = optarg;
break;
case 'F':
@@ -394,6 +412,16 @@ int main (int argc, char **argv)
case 'r':
/* Obsolete -f flag */
from = optarg;
+ p = identities_head;
+ while(p)
+ {
+ if(!strcmp(p->identity.identity, from))
+ {
+ identity = &p->identity;
+ break;
+ }
+ p = p->next;
+ }
break;
case 'h':
@@ -502,20 +530,20 @@ int main (int argc, char **argv)
* number of 587, however this is not widely deployed so the port is
* specified as 25 along with the default MTA host.
*/
- smtp_set_server (session, host ? host : "localhost:25");
+ smtp_set_server (session, identity->host ? identity->host : "localhost:25");
/* Set the SMTP Starttls extension. */
- smtp_starttls_enable (session, starttls);
+ smtp_starttls_enable (session, identity->starttls);
/* Do what's needed at application level to use authentication. */
authctx = auth_create_context ();
auth_set_mechanism_flags (authctx, AUTH_PLUGIN_PLAIN, 0);
- auth_set_interact_cb (authctx, authinteract, NULL);
+ auth_set_interact_cb (authctx, authinteract, identity);
/* Use our callback for X.509 certificate passwords. If STARTTLS is not in
* use or disabled in configure, the following is harmless.
*/
- smtp_starttls_set_password_cb (tlsinteract, NULL);
+ smtp_starttls_set_password_cb (tlsinteract, identity);
/* Now tell libESMTP it can use the SMTP AUTH extension. */
smtp_auth_set_context (session, authctx);
diff --git a/parser.y b/parser.y
index 5694948..aebdd75 100644
--- a/parser.y
+++ b/parser.y
@@ -14,17 +14,15 @@
#include <libesmtp.h>
+#include "esmtp.h"
+
/* parser reads these */
char *rcfile = NULL; /* path name of dot file */
/* parser sets these */
int yydebug; /* in case we didn't generate with -- debug */
-extern char *host;
-extern char *user;
-extern char *pass;
-extern enum starttls_option starttls;
-extern char *certificate_passphrase;
+static identity_t *identity = &default_identity;
/* using Bison, this arranges that yydebug messages will show actual tokens */
extern char * yytext;
@@ -38,7 +36,7 @@ void yyerror (const char *s);
char *sval;
}
-%token HOSTNAME USERNAME PASSWORD STARTTLS CERTIFICATE_PASSPHRASE
+%token IDENTITY HOSTNAME USERNAME PASSWORD STARTTLS CERTIFICATE_PASSPHRASE
%token MAP
@@ -50,6 +48,34 @@ void yyerror (const char *s);
rcfile : /* empty */
| statement_list
+ | statement_list identity_list
+ | identity_list
+ ;
+
+identity_list : identity
+ | identity statement_list
+ | identity_list identity statement_list
+ ;
+
+
+map : /* empty */
+ | MAP
+ ;
+
+identity : IDENTITY map STRING
+ {
+ identity_list_t *item;
+
+ item = malloc(sizeof(identity_list_t));
+ memset(item, 0, sizeof(identity_list_t));
+
+ *identities_tail = item;
+ identities_tail = &item->next;
+ identity = &item->identity;
+
+ identity->identity = strdup($3);
+ identity->starttls = Starttls_DISABLED;
+ }
;
statement_list : statement
@@ -57,19 +83,18 @@ statement_list : statement
;
/* future global options should also have the form SET <name> optmap <value> */
-statement : HOSTNAME MAP STRING { host = strdup($3); }
- | USERNAME MAP STRING { user = strdup($3); }
- | PASSWORD MAP STRING { pass = strdup($3); }
- | STARTTLS MAP DISABLED { starttls = Starttls_DISABLED; }
- | STARTTLS MAP ENABLED { starttls = Starttls_ENABLED; }
- | STARTTLS MAP REQUIRED { starttls = Starttls_REQUIRED; }
- | CERTIFICATE_PASSPHRASE MAP STRING { certificate_passphrase = strdup($3); }
+statement : HOSTNAME map STRING { identity->host = strdup($3); }
+ | USERNAME map STRING { identity->user = strdup($3); }
+ | PASSWORD map STRING { identity->pass = strdup($3); }
+ | STARTTLS map DISABLED { identity->starttls = Starttls_DISABLED; }
+ | STARTTLS map ENABLED { identity->starttls = Starttls_ENABLED; }
+ | STARTTLS map REQUIRED { identity->starttls = Starttls_REQUIRED; }
+ | CERTIFICATE_PASSPHRASE map STRING { identity->certificate_passphrase = strdup($3); }
;
%%
/* lexer interface */
-extern char *rcfile;
extern int lineno;
extern char *yytext;
extern FILE *yyin;
@@ -82,21 +107,25 @@ void yyerror (const char *s)
}
#define RCFILE ".esmtprc"
+
void parse_rcfile (void)
{
- char *home;
-
- /* Setup the rcfile name. */
- if (!(home = getenv("HOME")))
- return;
-
- if (!(rcfile = malloc(strlen(home) + sizeof(RCFILE) + 2)))
- return;
-
- strcpy(rcfile, home);
- if (rcfile[strlen(rcfile) - 1] != '/')
- strcat(rcfile, "/");
- strcat(rcfile, RCFILE);
+ if(!rcfile)
+ {
+ char *home;
+
+ /* Setup the rcfile name. */
+ if (!(home = getenv("HOME")))
+ return;
+
+ if (!(rcfile = malloc(strlen(home) + strlen(RCFILE) + 2)))
+ return;
+
+ strcpy(rcfile, home);
+ if (rcfile[strlen(rcfile) - 1] != '/')
+ strcat(rcfile, "/");
+ strcat(rcfile, RCFILE);
+ }
/* Open the configuration file and feed it to the lexer. */
if (!(yyin = fopen(rcfile, "r")))
diff --git a/sample.esmtprc b/sample.esmtprc
index a5343f2..1a11e4e 100644
--- a/sample.esmtprc
+++ b/sample.esmtprc
@@ -1,15 +1,49 @@
-#set SMTP host and service (port)
+# Sample configuration file for ESMTP.
+#
+# José Fonseca
+
+# Set SMTP host and service (port)
+#
hostname = localhost:25
+#
+# This is specified in the format host.example.org[:service] with no whitespace
+# surrounding the colon if service is specified. service may be a name from
+# /etc/services or a decimal port number. If not specified the port defaults to
+# 587.
+#
+# NOTE (from libESMTP documentation): The default port number is set to 587
+# since this is the port that should be used for mail submission, see RFC 2476.
+# By choosing this default now, the API does not change behaviour unexpectedly
+# in the future as use of the new standard becomes commonplace. The hostport
+# nototion simplifies things for the application, the user can type
+# localhost:smtp or localhost:25 where the application expects a host name.
-# set the user name
+# Set the user name
+#
username = "USERNAME"
+#
+# Note that the equal and quotes are optional but can be helpful in certain
+# circumstances.
-# set the password
+# Set the password
password = "PASSWORD"
-# use the Starttls
-#starttls = { enabled | disabled | required }
+# Use the Starttls
+#
+starttls = disabled
+#
+# It can be one of "enabled", "disabled" or "required". It defaults to
+# disabled.
-# set the certificate passphrase
+# Set the certificate passphrase
+#
#certificate_passphrase = "CERTIFICATE_PASSPHRASE"
+
+# A different identity which can be selected with the '-f' flag. You can have
+# as many you like.
+#
+identity myself@somewhere.com
+ hostname smtp.somewhere.com:25
+ username "myself"
+ password "secret"