Commit 40fffffb 40fffffb6c6b5b10642428408f49bec401668f68 by Sergey Poznyakoff

Finish removing mail.local and mail.remote

1 parent 4d8141cf
......@@ -244,7 +244,7 @@ mailutils-specific configuration options:
The following options enable DBM support in Mailutils. DBM support is
necessary if you wish to use APOP authentication in POP3 daemon or to
use DBM-based mail box quotas with mail.local.
use DBM-based mail box quotas with maildag.
--with-gdbm
......
......@@ -42,8 +42,6 @@
* sieve: (mailutils)sieve. Mail Filtering Utility.
* mimeview: (mailutils)mimeview. View MIME Messages.
* mailutils-config: (mailutils)mailutils-config. List Information about Mailutils.
* mail.local: (mailutils)mail.local. Deliver Mail to UNIX Mailboxes.
* mail.remote: (mailutils)mail.remote. Forward Mail to Remote Machine.
@end direntry
@end ifinfo
......
......@@ -12,8 +12,8 @@ mailbox.
To invoke the script directly by its name, add executable bit to its
permissions.
The same script may be used by mail.local to sieve the incoming mail upon
its arrival, see node "Programs -> mail.local" in the accompanying
The same script may be used by maidag to sieve the incoming mail upon
its arrival, see node "Programs -> maidag" in the accompanying
documentation for more information on this.
To execute the sieve script directly, without saving the produced Scheme
......
Makefile
Makefile.in
mail.local
.deps
.libs
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2002, 2007 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = -I${top_srcdir} @MU_COMMON_INCLUDES@ @GUILE_INCLUDES@
SUBDIRS = testsuite
libexec_PROGRAMS = mail.local
mail_local_SOURCES = main.c mailquota.c script.c mail.local.h
mail_local_LDADD = \
@LIBMU_SCM@ @GUILE_LIBS@\
@LIBMU_SCM_DEPS@\
${MU_APP_LIBRARIES}\
${MU_LIB_SIEVE}\
${MU_LIB_MBOX}\
${MU_LIB_IMAP}\
${MU_LIB_POP}\
${MU_LIB_NNTP}\
${MU_LIB_MH}\
${MU_LIB_MAILDIR}\
${MU_LIB_AUTH}\
${MU_LIB_MAILER}\
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS} \
@MU_COMMON_LIBRARIES@
install-exec-hook:
for i in $(libexec_PROGRAMS); do\
chown root:mail $(DESTDIR)$(libexecdir)/$$i;\
chmod 4755 $(DESTDIR)$(libexecdir)/$$i;\
done
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005,
2007 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include <errno.h>
#include <grp.h>
#include <netdb.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_SYSEXITS_H
# include <sysexits.h>
#else
# define EX_OK 0 /* successful termination */
# define EX__BASE 64 /* base value for error messages */
# define EX_USAGE 64 /* command line usage error */
# define EX_DATAERR 65 /* data format error */
# define EX_NOINPUT 66 /* cannot open input */
# define EX_NOUSER 67 /* addressee unknown */
# define EX_NOHOST 68 /* host name unknown */
# define EX_UNAVAILABLE 69 /* service unavailable */
# define EX_SOFTWARE 70 /* internal software error */
# define EX_OSERR 71 /* system error (e.g., can't fork) */
# define EX_OSFILE 72 /* critical OS file missing */
# define EX_CANTCREAT 73 /* can't create (user) output file */
# define EX_IOERR 74 /* input/output error */
# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
# define EX_PROTOCOL 76 /* remote error in protocol */
# define EX_NOPERM 77 /* permission denied */
# define EX_CONFIG 78 /* configuration error */
# define EX__MAX 78 /* maximum listed value */
#endif
#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBAK 0x7f000001
#endif
#include <mailutils/attribute.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/list.h>
#include <mailutils/locker.h>
#include <mailutils/mailbox.h>
#include <mailutils/message.h>
#include <mailutils/mutil.h>
#include <mailutils/registrar.h>
#include <mailutils/stream.h>
#include <mailutils/url.h>
#include <mailutils/mu_auth.h>
#include <mailutils/sieve.h>
#include <mailutils/nls.h>
#include <mu_dbm.h>
#include <mu_asprintf.h>
#if defined (USE_DBM) || defined (USE_SQL)
# define USE_MAILBOX_QUOTAS 1
#endif
/* Debug */
extern int debug_level;
#define dbg() if (debug_level) debug
/* mailquota settings */
#define MQUOTA_OK 0
#define MQUOTA_EXCEEDED 1
#define MQUOTA_UNLIMITED 2
extern char *quotadbname;
extern char *quota_query;
extern int exit_code;
extern void setgroupquota (char *str);
extern int check_quota (struct mu_auth_data *auth,
mu_off_t size, mu_off_t *rest);
int mda (mu_mailbox_t mbx, char *username);
int switch_user_id (struct mu_auth_data *auth, int user);
void mailer_err (const char *msg, const char *arg, const char *fmt, ...)
MU_PRINTFLIKE(3,4);
#ifdef WITH_GUILE
struct mda_data
{
mu_mailbox_t mbox;
char *progfile;
char *progfile_pattern;
char **argv;
};
int prog_mda (struct mda_data *data);
extern int debug_guile;
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2004,
2005, 2007 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
#include <mail.local.h>
#if defined (USE_MAILBOX_QUOTAS)
#define DEFRETVAL MQUOTA_UNLIMITED
mu_off_t groupquota = 5*1024*1024UL;
static int get_size (char *, mu_off_t *, char **);
int
get_size (char *str, mu_off_t *size, char **endp)
{
mu_off_t s;
s = strtol (str, &str, 0);
switch (*str)
{
case 0:
break;
case 'k':
case 'K':
s *= 1024;
break;
case 'm':
case 'M':
s *= 1024*1024;
break;
default:
*endp = str;
return -1;
}
*size = s;
return 0;
}
#define RETR_OK 0
#define RETR_UNLIMITED -1
#define RETR_FAILURE 1
int
fail_retrieve_quota (char *name, mu_off_t *quota)
{
mu_error (_("No quota retrieving mechanism"));
return RETR_FAILURE;
}
#ifdef USE_DBM
int
dbm_retrieve_quota (char *name, mu_off_t *quota)
{
DBM_FILE db;
DBM_DATUM named, contentd;
char buffer[64];
int unlimited = 0;
int rc;
if (!quotadbname)
return RETR_FAILURE;
if (mu_dbm_open (quotadbname, &db, MU_STREAM_READ, 0600))
{
mu_error (_("Cannot open %s: %s"), quotadbname, mu_strerror (errno));
return RETR_FAILURE;
}
memset (&named, 0, sizeof named);
memset (&contentd, 0, sizeof contentd);
MU_DATUM_PTR (named) = name;
MU_DATUM_SIZE (named) = strlen (name);
rc = mu_dbm_fetch (db, named, &contentd);
if (rc || !MU_DATUM_PTR (contentd))
{
/* User not in database, try default quota */
memset (&named, 0, sizeof named);
MU_DATUM_PTR (named) = "DEFAULT";
MU_DATUM_SIZE (named) = strlen ("DEFAULT");
rc = mu_dbm_fetch (db, named, &contentd);
if (rc)
{
/*mu_error (_("can't fetch data: %s"), strerror (rc));*/
return RETR_FAILURE;
}
if (!MU_DATUM_PTR (contentd))
return RETR_FAILURE;
}
if (strncasecmp("none",
MU_DATUM_PTR (contentd),
MU_DATUM_SIZE (contentd)) == 0)
unlimited = 1;
else if (MU_DATUM_SIZE (contentd) > sizeof(buffer)-1)
{
mu_error (ngettext ("Mailbox quota for `%s' is too big: %d digit",
"Mailbox quota for `%s' is too big: %d digits",
MU_DATUM_SIZE (contentd)),
name, MU_DATUM_SIZE (contentd));
*quota = groupquota;
}
else
{
char *p;
strncpy(buffer, MU_DATUM_PTR (contentd), MU_DATUM_SIZE (contentd));
buffer[MU_DATUM_SIZE (contentd)] = 0;
*quota = strtoul (buffer, &p, 0);
if (get_size (buffer, quota, &p))
{
mu_error (_("Bogus mailbox quota for `%s' (near `%s')"), name, p);
*quota = groupquota;
}
}
mu_dbm_close (db);
return unlimited ? RETR_UNLIMITED : RETR_OK;
}
# define default_retrieve_quota dbm_retrieve_quota
#else
# define default_retrieve_quota fail_retrieve_quota
#endif
#ifdef USE_SQL
#include <mailutils/sql.h>
/* FIXME: defined in libmu_auth/sql.c */
#include <libmu_auth/sql.h>
int
sql_retrieve_quota (char *name, mu_off_t *quota)
{
mu_sql_connection_t conn;
char *query_str;
int rc, status;
char *tmp;
size_t n;
query_str = mu_sql_expand_query (quota_query, name);
if (!query_str)
return RETR_FAILURE;
status = mu_sql_connection_init (&conn,
mu_sql_module_config.interface,
mu_sql_module_config.host,
mu_sql_module_config.port,
mu_sql_module_config.user,
mu_sql_module_config.passwd,
mu_sql_module_config.db);
if (status)
{
mu_error ("%s. SQL error: %s",
mu_strerror (status), mu_sql_strerror (conn));
mu_sql_connection_destroy (&conn);
free (query_str);
return RETR_FAILURE;
}
status = mu_sql_connect (conn);
if (status)
{
mu_error ("%s. SQL error: %s",
mu_strerror (status), mu_sql_strerror (conn));
mu_sql_connection_destroy (&conn);
free (query_str);
return RETR_FAILURE;
}
status = mu_sql_query (conn, query_str);
free (query_str);
if (status)
{
mu_error (_("SQL Query failed: %s"),
(status == MU_ERR_SQL) ? mu_sql_strerror (conn) :
mu_strerror (status));
mu_sql_connection_destroy (&conn);
return RETR_FAILURE;
}
status = mu_sql_store_result (conn);
if (status)
{
mu_error (_("Cannot store SQL result: %s"),
(status == MU_ERR_SQL) ? mu_sql_strerror (conn) :
mu_strerror (status));
mu_sql_connection_destroy (&conn);
return RETR_FAILURE;
}
mu_sql_num_tuples (conn, &n);
if (n == 0)
{
rc = RETR_FAILURE;
}
else
{
rc = RETR_OK;
tmp = NULL;
status = mu_sql_get_column (conn, 0, 0, &tmp);
if (status)
{
mu_error (_("Cannot retrieve mailbox quota from SQL: %s"),
(status == MU_ERR_SQL) ? mu_sql_strerror (conn) :
mu_strerror (status));
rc = RETR_FAILURE;
}
else if (tmp == NULL || tmp[0] == 0 || strcasecmp (tmp, "none") == 0)
rc = RETR_UNLIMITED;
else
{
char *p;
if (get_size (tmp, quota, &p))
{
mu_error (_("Bogus mailbox quota for `%s' (near `%s')"),
name, p);
*quota = groupquota;
}
}
}
mu_sql_release_result (conn);
mu_sql_disconnect (conn);
mu_sql_connection_destroy (&conn);
return rc;
}
#endif
static int
retrieve_quota (struct mu_auth_data *auth, mu_off_t *quota)
{
if (MU_HAS_QUOTA (auth))
{
if (auth->quota == 0)
return RETR_UNLIMITED;
*quota = auth->quota;
return RETR_OK;
}
#ifdef USE_SQL
if (quota_query)
return sql_retrieve_quota (auth->name, quota);
#endif
return default_retrieve_quota (auth->name, quota);
}
int
check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest)
{
mu_off_t quota;
switch (retrieve_quota (auth, &quota))
{
case RETR_FAILURE:
return DEFRETVAL;
case RETR_UNLIMITED:
return MQUOTA_UNLIMITED;
case RETR_OK:
if (quota < size) /* Mailbox full */
return MQUOTA_EXCEEDED;
if (rest)
*rest = quota - size;
}
return MQUOTA_OK;
}
#endif /* USE_MAIL_QUOTA */
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005,
2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
#include <mail.local.h>
#include "mailutils/libargp.h"
int multiple_delivery; /* Don't return errors when delivering to multiple
recipients */
int ex_quota_tempfail; /* Return temporary failure if mailbox quota is
exceeded. If this variable is not set, mail.local
will return "service unavailable" */
int exit_code = EX_OK; /* Exit code to be used */
uid_t uid; /* Current user id */
char *quotadbname = NULL; /* Name of mailbox quota database */
char *quota_query = NULL; /* SQL query to retrieve mailbox quota */
/* Debuggig options */
int debug_level; /* General debugging level */
int debug_flags; /* Mailutils debugging flags */
int sieve_debug_flags; /* Sieve debugging flags */
int sieve_enable_log; /* Enables logging of executed Sieve actions */
char *message_id_header; /* Use the value of this header as message
identifier when logging Sieve actions */
mu_debug_t mudebug; /* Mailutils debugging object */
#define MAXFD 64
#define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE)
void close_fds (void);
int make_tmp (const char *from, mu_mailbox_t *mbx);
void deliver (mu_mailbox_t msg, char *name);
void guess_retval (int ec);
void notify_biff (mu_mailbox_t mbox, char *name, size_t size);
const char *program_version = "mail.local (" PACKAGE_STRING ")";
static char doc[] =
N_("GNU mail.local -- the local MDA")
"\v"
N_("Debug flags are:\n\
g - guimb stack traces\n\
T - mailutils traces (MU_DEBUG_TRACE0-MU_DEBUG_TRACE9)\n\
P - network protocols (MU_DEBUG_PROT)\n\
t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\
i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n\
l - sieve action logs\n\
0-9 - Set mail.local debugging level\n");
static char args_doc[] = N_("recipient [recipient ...]");
#define ARG_MULTIPLE_DELIVERY 1
#define ARG_QUOTA_TEMPFAIL 2
#define ARG_MESSAGE_ID_HEADER 3
#define ARG_QUOTA_QUERY 4
static struct argp_option options[] =
{
{ "ex-multiple-delivery-success", ARG_MULTIPLE_DELIVERY, NULL, 0,
N_("Do not return errors when delivering to multiple recipients"), 0 },
{ "ex-quota-tempfail", ARG_QUOTA_TEMPFAIL, NULL, 0,
N_("Return temporary failure if disk or mailbox quota is exceeded"), 0 },
{ "from", 'f', N_("EMAIL"), 0,
N_("Specify the sender's name") },
{ NULL, 'r', NULL, OPTION_ALIAS, NULL },
#ifdef USE_DBM
{ "quota-db", 'q', N_("FILE"), 0,
N_("Specify path to quota DBM database"), 0 },
#endif
#ifdef USE_SQL
{ "quota-query", ARG_QUOTA_QUERY, N_("STRING"), 0,
N_("SQL query to retrieve mailbox quota"), 0 },
#endif
{ "sieve", 'S', N_("PATTERN"), 0,
N_("Set name pattern for user-defined Sieve mail filters"), 0 },
{ "message-id-header", ARG_MESSAGE_ID_HEADER, N_("STRING"), 0,
N_("Identify messages by the value of this header when logging Sieve actions"), 0 },
#ifdef WITH_GUILE
{ "source", 's', N_("PATTERN"), 0,
N_("Set name pattern for user-defined Scheme mail filters"), 0 },
#endif
{ "debug", 'x', N_("FLAGS"), 0,
N_("Enable debugging"), 0 },
{ NULL, 0, NULL, 0, NULL, 0 }
};
static error_t parse_opt (int key, char *arg, struct argp_state *state);
static struct argp argp = {
options,
parse_opt,
args_doc,
doc,
NULL,
NULL, NULL
};
static const char *argp_capa[] = {
"auth",
"common",
"debug",
"license",
"logging",
"mailbox",
"locking",
"mailer",
NULL
};
char *from = NULL;
char *progfile_pattern = NULL;
char *sieve_pattern = NULL;
char *saved_envelope; /* A hack to spare mu_envelope_ calls */
#define D_DEFAULT "9s"
static void
set_debug_flags (mu_debug_t debug, const char *arg)
{
for (; *arg; arg++)
{
switch (*arg)
{
case 'g':
#ifdef WITH_GUILE
debug_guile = 1;
#endif
break;
case 't':
sieve_debug_flags |= MU_SIEVE_DEBUG_TRACE;
break;
case 'i':
sieve_debug_flags |= MU_SIEVE_DEBUG_INSTR;
break;
case 'l':
sieve_enable_log = 1;
break;
case 'T':
debug_flags |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE7);
break;
case 'P':
debug_flags |= MU_DEBUG_LEVEL_MASK (MU_DEBUG_PROT);
break;
default:
if (isdigit (*arg))
debug_level = *arg - '0';
else if (debug)
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("%c is not a valid debug flag"),
*arg);
else
mu_error (_("%c is not a valid debug flag"), *arg);
break;
}
}
}
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
static struct mu_argp_node_list lst;
switch (key)
{
case ARG_MULTIPLE_DELIVERY:
mu_argp_node_list_new (&lst, "ex-multiple-delivery-success", "yes");
break;
case ARG_QUOTA_TEMPFAIL:
mu_argp_node_list_new (&lst, "ex-quota-tempfail", "yes");
break;
case ARG_MESSAGE_ID_HEADER:
mu_argp_node_list_new (&lst, "message-id-header", arg);
break;
case ARG_QUOTA_QUERY:
mu_argp_node_list_new (&lst, "quota-query", arg);
break;
case 'r':
case 'f':
if (from != NULL)
{
argp_error (state, _("Multiple --from options"));
return EX_USAGE;
}
from = arg;
break;
#ifdef USE_DBM
case 'q':
mu_argp_node_list_new (&lst, "quota-db", arg);
break;
#endif
#ifdef WITH_GUILE
case 's':
mu_argp_node_list_new (&lst, "source", arg);
break;
#endif
case 'S':
mu_argp_node_list_new (&lst, "sieve-filter", arg);
break;
case 'x':
mu_argp_node_list_new (&lst, "debug", arg ? arg : D_DEFAULT);
break;
case ARGP_KEY_INIT:
mu_argp_node_list_init (&lst);
break;
case ARGP_KEY_FINI:
mu_argp_node_list_finish (&lst, NULL, NULL);
break;
default:
return ARGP_ERR_UNKNOWN;
case ARGP_KEY_ERROR:
exit (EX_USAGE);
}
return 0;
}
static int
cb_debug (mu_debug_t debug, void *data, mu_config_value_t *val)
{
if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
return 1;
set_debug_flags (debug, val->v.string);
return 0;
}
struct mu_cfg_param mail_local_cfg_param[] = {
{ "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL,
N_("In case of multiple delivery, exit with code 0 if at least one "
"delivery succeeded.") },
{ "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
N_("Indicate temporary failure if the recipient is over his mail quota.")
},
#ifdef USE_DBM
{ "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
N_("Name of DBM quota database file."),
N_("file") },
#endif
#ifdef USE_SQL
{ "quota-query", mu_cfg_string, &quota_query, 0, NULL,
N_("SQL query to retrieve mailbox quota. This is deprecated, use "
"sql { ... } instead."),
N_("query") },
#endif
{ "sieve-filter", mu_cfg_string, &sieve_pattern, 0, NULL,
N_("File name or name pattern for Sieve filter file."),
N_("file-or-pattern") },
{ "message-id-header", mu_cfg_string, &message_id_header, 0, NULL,
N_("When logging Sieve actions, identify messages by the value of "
"this header."),
N_("name") },
#ifdef WITH_GUILE
{ "guile-filter", mu_cfg_string, &progfile_pattern, 0, NULL,
N_("File name or name pattern for Guile filter file."),
N_("file-or-pattern") },
#endif
{ "debug", mu_cfg_callback, NULL, 0, cb_debug,
N_("Set mail.local debug level. Debug level consists of one or more "
"of the following letters:\n"
" g - guimb stack traces\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n"
" l - sieve action logs\n") },
{ NULL }
};
static int
_sieve_debug_printer (void *unused, const char *fmt, va_list ap)
{
mu_diag_vprintf (MU_DIAG_DEBUG, fmt, ap);
return 0;
}
static void
_sieve_action_log (void *user_name,
const mu_sieve_locus_t *locus, size_t msgno,
mu_message_t msg,
const char *action, const char *fmt, va_list ap)
{
int pfx = 0;
mu_debug_t debug;
mu_diag_get_debug (&debug);
mu_debug_set_locus (debug, locus->source_file, locus->source_line);
mu_diag_printf (MU_DIAG_NOTICE, _("(user %s) "), (char*) user_name);
if (message_id_header)
{
mu_header_t hdr = NULL;
char *val = NULL;
mu_message_get_header (msg, &hdr);
if (mu_header_aget_value (hdr, message_id_header, &val) == 0
|| mu_header_aget_value (hdr, MU_HEADER_MESSAGE_ID, &val) == 0)
{
pfx = 1;
mu_diag_printf (MU_DIAG_NOTICE, _("%s on msg %s"), action, val);
free (val);
}
}
if (!pfx)
{
size_t uid = 0;
mu_message_get_uid (msg, &uid);
mu_diag_printf (MU_DIAG_NOTICE, _("%s on msg uid %d"), action, uid);
}
if (fmt && strlen (fmt))
{
mu_diag_printf (MU_DIAG_NOTICE, "; ");
mu_diag_vprintf (MU_DIAG_NOTICE, fmt, ap);
}
mu_diag_printf (MU_DIAG_NOTICE, "\n");
mu_debug_set_locus (debug, NULL, 0);
}
static int
_sieve_parse_error (void *user_name, const char *filename, int lineno,
const char *fmt, va_list ap)
{
mu_debug_t debug;
mu_diag_get_debug (&debug);
if (filename)
mu_debug_set_locus (debug, filename, lineno);
mu_diag_printf (MU_DIAG_NOTICE, _("(user %s) "), (char*) user_name);
mu_diag_vprintf (MU_DIAG_NOTICE, fmt, ap);
mu_diag_printf (MU_DIAG_NOTICE, "\n");
mu_debug_set_locus (debug, NULL, 0);
return 0;
}
int
main (int argc, char *argv[])
{
mu_mailbox_t mbox = NULL;
int arg_index;
/* Preparative work: close inherited fds, force a reasonable umask
and prepare a logging. */
close_fds ();
umask (0077);
/* Native Language Support */
MU_APP_INIT_NLS ();
/* Default locker settings */
mu_locker_set_default_flags (MU_LOCKER_PID|MU_LOCKER_RETRY,
mu_locker_assign);
mu_locker_set_default_retry_timeout (1);
mu_locker_set_default_retry_count (300);
/* Register needed modules */
MU_AUTH_REGISTER_ALL_MODULES();
/* Parse command line */
mu_gocs_register ("sieve", mu_sieve_module_init);
mu_argp_init (program_version, NULL);
if (mu_app_init (&argp, argp_capa, mail_local_cfg_param,
argc, argv, 0, &arg_index, NULL))
exit (EX_CONFIG);
uid = getuid ();
if (uid == 0)
{
mu_debug_t debug;
openlog (MU_LOG_TAG (), LOG_PID, mu_log_facility);
mu_diag_get_debug (&debug);
mu_debug_set_print (debug, mu_diag_syslog_printer, NULL);
}
if (debug_flags)
{
int rc;
if ((rc = mu_debug_create (&mudebug, NULL)))
{
mu_error (_("mu_debug_create failed: %s\n"), mu_strerror (rc));
exit (EX_TEMPFAIL);
}
if ((rc = mu_debug_set_level (mudebug, debug_flags)))
{
mu_error (_("mu_debug_set_level failed: %s\n"),
mu_strerror (rc));
exit (EX_TEMPFAIL);
}
}
argc -= arg_index;
argv += arg_index;
if (!argc)
{
if (uid)
{
static char *s_argv[2];
struct mu_auth_data *auth = mu_get_auth_by_uid (uid);
if (!uid)
{
mu_error (_("Cannot get username"));
return EX_UNAVAILABLE;
}
s_argv[0] = auth->name;
argv = s_argv;
argc = 1;
}
else
{
mu_error (_("Missing arguments. Try --help for more info."));
return EX_USAGE;
}
}
mu_register_all_formats ();
/* Possible supported mailers. */
mu_registrar_record (mu_sendmail_record);
mu_registrar_record (mu_smtp_record);
if (make_tmp (from, &mbox))
exit (exit_code);
if (multiple_delivery)
multiple_delivery = argc > 1;
#ifdef WITH_GUILE
if (progfile_pattern)
{
struct mda_data mda_data;
memset (&mda_data, 0, sizeof mda_data);
mda_data.mbox = mbox;
mda_data.argv = argv;
mda_data.progfile_pattern = progfile_pattern;
return prog_mda (&mda_data);
}
#endif
for (; *argv; argv++)
mda (mbox, *argv);
return exit_code;
}
int
sieve_test (struct mu_auth_data *auth, mu_mailbox_t mbx)
{
int rc = 1;
char *progfile;
if (!sieve_pattern)
return 1;
progfile = mu_expand_path_pattern (sieve_pattern, auth->name);
if (access (progfile, R_OK))
{
if (debug_level > 2)
mu_diag_output (MU_DIAG_DEBUG, _("Access to %s failed: %m"), progfile);
}
else
{
mu_sieve_machine_t mach;
rc = mu_sieve_machine_init (&mach, auth->name);
if (rc)
{
mu_error (_("Cannot initialize sieve machine: %s"),
mu_strerror (rc));
}
else
{
mu_sieve_set_debug (mach, _sieve_debug_printer);
mu_sieve_set_debug_object (mach, mudebug);
mu_sieve_set_debug_level (mach, sieve_debug_flags);
mu_sieve_set_parse_error (mach, _sieve_parse_error);
if (sieve_enable_log)
mu_sieve_set_logger (mach, _sieve_action_log);
rc = mu_sieve_compile (mach, progfile);
if (rc == 0)
{
mu_attribute_t attr;
mu_message_t msg = NULL;
mu_mailbox_get_message (mbx, 1, &msg);
mu_message_get_attribute (msg, &attr);
mu_attribute_unset_deleted (attr);
if (switch_user_id (auth, 1) == 0)
{
chdir (auth->dir);
rc = mu_sieve_message (mach, msg);
if (rc == 0)
rc = mu_attribute_is_deleted (attr) == 0;
switch_user_id (auth, 0);
chdir ("/");
}
mu_sieve_machine_destroy (&mach);
}
}
}
free (progfile);
return rc;
}
int
mda (mu_mailbox_t mbx, char *username)
{
deliver (mbx, username);
if (multiple_delivery)
exit_code = EX_OK;
return exit_code;
}
void
close_fds ()
{
int i;
long fdlimit = MAXFD;
#if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
fdlimit = sysconf (_SC_OPEN_MAX);
#elif defined (HAVE_GETDTABLESIZE)
fdlimit = getdtablesize ();
#endif
for (i = 3; i < fdlimit; i++)
close (i);
}
int
switch_user_id (struct mu_auth_data *auth, int user)
{
int rc;
uid_t uid;
if (!auth || auth->change_uid == 0)
return 0;
if (user)
uid = auth->uid;
else
uid = 0;
#if defined(HAVE_SETREUID)
rc = setreuid (0, uid);
#elif defined(HAVE_SETRESUID)
rc = setresuid (-1, uid, -1);
#elif defined(HAVE_SETEUID)
rc = seteuid (uid);
#else
# error "No way to reset user privileges?"
#endif
if (rc < 0)
mailer_err ("cannot set user priviledes", auth->name,
"setreuid(0, %d): %s (r=%d, e=%d)",
uid, strerror (errno), getuid (), geteuid ());
return rc;
}
static int
tmp_write (mu_stream_t stream, mu_off_t *poffset, char *buf, size_t len)
{
size_t n = 0;
int status = mu_stream_write (stream, buf, len, *poffset, &n);
if (status == 0 && n != len)
status = EIO;
*poffset += n;
return status;
}
int
make_tmp (const char *from, mu_mailbox_t *mbox)
{
mu_stream_t stream;
char *buf = NULL;
size_t n = 0;
mu_off_t offset = 0;
size_t line;
int status;
static char *newline = "\n";
char *tempfile;
tempfile = mu_tempname (NULL);
if ((status = mu_file_stream_create (&stream, tempfile, MU_STREAM_RDWR)))
{
mailer_err ("Temporary failure", NULL,
_("Unable to open temporary file: %s"),
mu_strerror (status));
exit (exit_code);
}
if ((status = mu_stream_open (stream)))
{
mailer_err ("Temporary failure", NULL,
_("unable to open temporary file: %s"), mu_strerror (status));
exit (exit_code);
}
line = 0;
while (getline (&buf, &n, stdin) > 0)
{
line++;
if (line == 1)
{
if (memcmp (buf, "From ", 5))
{
struct mu_auth_data *auth = NULL;
if (!from)
{
auth = mu_get_auth_by_uid (uid);
if (auth)
from = auth->name;
}
if (from)
{
time_t t;
time (&t);
asprintf (&saved_envelope, "From %s %s", from, ctime (&t));
status = tmp_write (stream, &offset, saved_envelope,
strlen (saved_envelope));
}
else
{
mailer_err ("Cannot determine sender address", NULL,
_("Cannot determine sender address"));
exit (EX_UNAVAILABLE);
}
if (auth)
mu_auth_data_free (auth);
}
else
{
saved_envelope = strdup (buf);
if (!saved_envelope)
status = ENOMEM;
}
}
else if (!memcmp (buf, "From ", 5))
{
static char *escape = ">";
status = tmp_write (stream, &offset, escape, 1);
}
if (!status)
status = tmp_write (stream, &offset, buf, strlen (buf));
if (status)
{
mailer_err ("Temporary failure", NULL,
_("Error writing temporary file: %s"),
mu_strerror (status));
mu_stream_destroy (&stream, mu_stream_get_owner (stream));
return status;
}
}
if (buf && strchr (buf, '\n') == NULL)
status = tmp_write (stream, &offset, newline, 1);
status = tmp_write (stream, &offset, newline, 1);
free (buf);
unlink (tempfile);
free (tempfile);
if (status)
{
errno = status;
mailer_err ("Error writing temporary file", NULL,
_("Error writing temporary file: %s"), mu_strerror (status));
mu_stream_destroy (&stream, mu_stream_get_owner (stream));
return status;
}
mu_stream_flush (stream);
if ((status = mu_mailbox_create (mbox, "/dev/null"))
|| (status = mu_mailbox_open (*mbox, MU_STREAM_READ))
|| (status = mu_mailbox_set_stream (*mbox, stream)))
{
mailer_err ("Error opening temporary file", NULL,
_("Error opening temporary file: %s"),
mu_strerror (status));
mu_stream_destroy (&stream, mu_stream_get_owner (stream));
return status;
}
status = mu_mailbox_messages_count (*mbox, &n);
if (status)
{
errno = status;
mailer_err ("Error collecting message", NULL,
_("Error creating temporary message: %s"),
mu_strerror (status));
mu_stream_destroy (&stream, mu_stream_get_owner (stream));
return status;
}
return status;
}
void
deliver (mu_mailbox_t imbx, char *name)
{
mu_mailbox_t mbox;
mu_message_t msg;
char *path;
mu_url_t url = NULL;
mu_locker_t lock;
struct mu_auth_data *auth;
int status;
mu_stream_t istream, ostream;
mu_off_t size;
int failed = 0;
auth = mu_get_auth_by_name (name);
if (!auth)
{
mailer_err ("no such user", name,
_("%s: no such user"), name);
exit_code = EX_UNAVAILABLE;
return;
}
if (uid)
auth->change_uid = 0;
if (!sieve_test (auth, imbx))
{
exit_code = EX_OK;
mu_auth_data_free (auth);
return;
}
if ((status = mu_mailbox_get_message (imbx, 1, &msg)) != 0)
{
mailer_err ("cannot read message", name,
_("Cannot get message from the temporary mailbox: %s"),
mu_strerror (status));
mu_auth_data_free (auth);
return;
}
if ((status = mu_message_get_stream (msg, &istream)) != 0)
{
mailer_err ("cannot read message", name,
_("Cannot get input message stream: %s"),
mu_strerror (status));
mu_auth_data_free (auth);
return;
}
if ((status = mu_mailbox_create (&mbox, auth->mailbox)) != 0)
{
mailer_err ("cannot read message", name,
_("Cannot open mailbox %s: %s"),
auth->mailbox, mu_strerror (status));
mu_auth_data_free (auth);
return;
}
mu_mailbox_get_url (mbox, &url);
path = (char*) mu_url_to_string (url);
/* Actually open the mailbox. Switch to the user's euid to make
sure the maildrop file will have right privileges, in case it
will be created */
if (switch_user_id (auth, 1))
return;
status = mu_mailbox_open (mbox, MU_STREAM_RDWR|MU_STREAM_CREAT);
if (switch_user_id (auth, 0))
return;
if (status != 0)
{
mailer_err ("cannot open mailbox", name,
_("Cannot open mailbox %s: %s"), path, mu_strerror (status));
mu_mailbox_destroy (&mbox);
return;
}
mu_mailbox_get_locker (mbox, &lock);
status = mu_locker_lock (lock);
if (status)
{
mailer_err ("cannot lock mailbox", name,
_("Cannot lock mailbox `%s': %s"), path,
mu_strerror (status));
mu_mailbox_destroy (&mbox);
exit_code = EX_TEMPFAIL;
return;
}
if ((status = mu_mailbox_get_stream (mbox, &ostream)))
{
mailer_err ("cannot access mailbox", name,
_("Cannot get stream for mailbox %s: %s"),
path, mu_strerror (status));
mu_mailbox_destroy (&mbox);
return;
}
if ((status = mu_stream_size (ostream, &size)))
{
mailer_err ("cannot access mailbox", name,
_("Cannot get stream size (mailbox %s): %s"),
path, mu_strerror (status));
mu_mailbox_destroy (&mbox);
return;
}
#if defined(USE_MAILBOX_QUOTAS)
{
mu_off_t n;
mu_off_t isize;
switch (check_quota (auth, size, &n))
{
case MQUOTA_EXCEEDED:
mailer_err ("mailbox quota exceeded for this recipient", name,
_("%s: mailbox quota exceeded for this recipient"), name);
exit_code = EX_QUOTA();
failed++;
break;
case MQUOTA_UNLIMITED:
break;
default:
if ((status = mu_stream_size (istream, &isize)))
{
mailer_err ("cannot access mailbox", name,
_("Cannot get stream size (input message %s): %s"),
path, mu_strerror (status));
exit_code = EX_UNAVAILABLE;
failed++;
}
else if (isize > n)
{
mailer_err ("message would exceed maximum mailbox size for this recipient",
name,
_("%s: message would exceed maximum mailbox size for this recipient"),
name);
exit_code = EX_QUOTA();
failed++;
}
break;
}
}
#endif
if (!failed && switch_user_id (auth, 1) == 0)
{
size_t nrd;
char *buf = NULL;
mu_off_t bufsize = 1024;
mu_stream_size (istream, &bufsize);
for (; (buf = malloc (bufsize)) == NULL && bufsize > 1; bufsize /= 2)
;
if (!buf)
{
status = errno = ENOMEM;
failed++;
}
else if ((status = mu_stream_seek (ostream, size, SEEK_SET)) != 0
|| (status = mu_stream_seek (istream, 0, SEEK_SET) != 0))
/* nothing: the error will be reported later */;
else
{
status = mu_stream_sequential_write (ostream, saved_envelope,
strlen (saved_envelope));
if (status == 0)
{
while ((status = mu_stream_sequential_read (istream,
buf, bufsize,
&nrd))
== 0
&& nrd > 0)
{
status = mu_stream_sequential_write (ostream, buf, nrd);
if (status)
break;
}
free (buf);
}
}
switch_user_id (auth, 0);
if (status)
{
/* Undo the delivery by truncating the mailbox back to its
original size */
int rc = mu_stream_truncate (ostream, size);
if (rc)
mailer_err ("write error", name,
_("Error writing to mailbox: %s. Mailbox NOT truncated: %s"),
mu_strerror (status), mu_strerror (rc));
else
mailer_err ("write error", name,
_("Error writing to mailbox: %s"),
mu_strerror (status));
}
}
if (!failed)
notify_biff (mbox, name, size);
mu_locker_unlock (lock);
mu_auth_data_free (auth);
mu_mailbox_close (mbox);
mu_mailbox_destroy (&mbox);
}
void
notify_biff (mu_mailbox_t mbox, char *name, size_t size)
{
static int fd = -1;
mu_url_t url = NULL;
char *buf = NULL;
static struct sockaddr_in inaddr;
if (fd == -1)
{
struct servent *sp;
if ((sp = getservbyname ("biff", "udp")) == NULL)
return;
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
inaddr.sin_port = sp->s_port;
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0)
fd = -2; /* Mark failed initialization */
}
if (fd < 0)
return;
mu_mailbox_get_url (mbox, &url);
asprintf (&buf, "%s@%lu:%s", name,
(unsigned long) size, mu_url_to_string (url));
if (buf)
{
sendto (fd, buf, strlen (buf), 0, (struct sockaddr *)&inaddr,
sizeof inaddr);
free (buf);
}
}
void
mailer_err (const char *msg, const char *arg, const char *fmt, ...)
{
va_list ap;
guess_retval (errno);
if (arg)
fprintf (stderr, "<%s>: %s", arg, msg);
else
fputs (msg, stderr);
fputc ('\n', stderr);
if (fmt)
{
va_start (ap, fmt);
mu_verror (fmt, ap);
va_end (ap);
}
}
int temp_errors[] = {
#ifdef EAGAIN
EAGAIN, /* Try again */
#endif
#ifdef EBUSY
EBUSY, /* Device or resource busy */
#endif
#ifdef EPROCLIM
EPROCLIM, /* Too many processes */
#endif
#ifdef EUSERS
EUSERS, /* Too many users */
#endif
#ifdef ECONNABORTED
ECONNABORTED, /* Software caused connection abort */
#endif
#ifdef ECONNREFUSED
ECONNREFUSED, /* Connection refused */
#endif
#ifdef ECONNRESET
ECONNRESET, /* Connection reset by peer */
#endif
#ifdef EDEADLK
EDEADLK, /* Resource deadlock would occur */
#endif
#ifdef EDEADLOCK
EDEADLOCK, /* Resource deadlock would occur */
#endif
#ifdef EFBIG
EFBIG, /* File too large */
#endif
#ifdef EHOSTDOWN
EHOSTDOWN, /* Host is down */
#endif
#ifdef EHOSTUNREACH
EHOSTUNREACH, /* No route to host */
#endif
#ifdef EMFILE
EMFILE, /* Too many open files */
#endif
#ifdef ENETDOWN
ENETDOWN, /* Network is down */
#endif
#ifdef ENETUNREACH
ENETUNREACH, /* Network is unreachable */
#endif
#ifdef ENETRESET
ENETRESET, /* Network dropped connection because of reset */
#endif
#ifdef ENFILE
ENFILE, /* File table overflow */
#endif
#ifdef ENOBUFS
ENOBUFS, /* No buffer space available */
#endif
#ifdef ENOMEM
ENOMEM, /* Out of memory */
#endif
#ifdef ENOSPC
ENOSPC, /* No space left on device */
#endif
#ifdef EROFS
EROFS, /* Read-only file system */
#endif
#ifdef ESTALE
ESTALE, /* Stale NFS file handle */
#endif
#ifdef ETIMEDOUT
ETIMEDOUT, /* Connection timed out */
#endif
#ifdef EWOULDBLOCK
EWOULDBLOCK, /* Operation would block */
#endif
};
void
guess_retval (int ec)
{
int i;
/* Temporary failures override hard errors. */
if (exit_code == EX_TEMPFAIL)
return;
#ifdef EDQUOT
if (ec == EDQUOT)
{
exit_code = EX_QUOTA();
return;
}
#endif
for (i = 0; i < sizeof (temp_errors)/sizeof (temp_errors[0]); i++)
if (temp_errors[i] == ec)
{
exit_code = EX_TEMPFAIL;
return;
}
exit_code = EX_UNAVAILABLE;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005,
2007 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
#include <mail.local.h>
#ifdef WITH_GUILE
#include <mailutils/guile.h>
int debug_guile;
SCM mda_catch_body (void *data, mu_mailbox_t mbox);
SCM mda_catch_handler (void *unused, SCM tag, SCM throw_args);
int mda_next (void *data, mu_mailbox_t mbox);
int mda_exit (void *data, mu_mailbox_t mbox);
int mda_init (void *data);
int
prog_mda (struct mda_data *data)
{
char *x_argv[2];
mu_guimb_param_t param;
x_argv[0] = "mail.local";
x_argv[1] = NULL;
param.debug_guile = debug_guile;
param.mbox = data->mbox;
param.user_name = NULL;
param.init = mda_init;
param.catch_body = mda_catch_body;
param.catch_handler = mda_catch_handler;
param.next = mda_next;
param.exit = mda_exit;
param.data = data;
mu_process_mailbox (1, x_argv, &param);
return EX_UNAVAILABLE;
}
int
mda_init (void *data)
{
struct mda_data *md = data;
md->progfile = mu_expand_path_pattern (md->progfile_pattern, md->argv[0]);
return 0;
}
static void
mda_switch_to_user (struct mda_data *md)
{
struct mu_auth_data *auth = NULL;
if (md && *md->argv != NULL)
auth = mu_get_auth_by_name (*md->argv);
if (auth)
{
switch_user_id (auth, 1);
chdir (auth->dir);
mu_auth_data_free (auth);
}
else
{
switch_user_id (auth, 0);
chdir ("/");
}
}
SCM
mda_catch_body (void *data, mu_mailbox_t mbox)
{
struct mda_data *md = data;
mu_message_t mesg = NULL;
mu_attribute_t attr = NULL;
if (access (md->progfile, R_OK))
{
if (debug_level > 2)
mu_diag_output (MU_DIAG_DEBUG, _("Access to %s failed: %m"), md->progfile);
}
else
{
mda_switch_to_user (md);
scm_primitive_load (scm_makfrom0str (md->progfile));
}
mu_mailbox_get_message (mbox, 1, &mesg);
mu_message_get_attribute (mesg, &attr);
if (mu_attribute_is_deleted (attr))
return SCM_BOOL_F;
mda_switch_to_user (NULL);
mda (md->mbox, md->argv[0]);
return SCM_BOOL_F;
}
SCM
mda_catch_handler (void *data, SCM tag, SCM throw_args)
{
exit_code = EX_TEMPFAIL;
return scm_handle_by_message_noexit ("mail.local", tag, throw_args);
}
int
mda_next (void *data, mu_mailbox_t mbox)
{
struct mda_data *md = data;
mu_message_t mesg = NULL;
mu_attribute_t attr = NULL;
md->argv++;
if (*md->argv == NULL)
return 0;
if (md->progfile)
free (md->progfile);
md->progfile = mu_expand_path_pattern (md->progfile_pattern, *md->argv);
mu_mailbox_get_message (mbox, 1, &mesg);
mu_message_get_attribute (mesg, &attr);
mu_attribute_unset_deleted (attr);
return md->progfile != NULL;
}
int
mda_exit (void *data, mu_mailbox_t mbox)
{
return exit_code;
}
#endif
Makefile
Makefile.in
*.log
*.sum
site.exp
remote.exp
data
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2007 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
MESSAGE Simple mail
FROM gray@gnu.org
TO user
BODY BEGIN
From: gray@gnu.org
To: bug-mailutils@gnu.org
Subject: Simple mail
This is a simple mail.
Data goes here.
BODY END
MESSAGE END
MESSAGE Second mail
FROM gray@runasimi.org
TO user
BODY BEGIN
From: gray@runasimi.org
To: bug-mailutils@gnu.org
Subject: Simple mail
This is a simple mail.
Data goes here.
BODY END
MESSAGE END
# end of data
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2002, 2007 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
AUTOMAKE_OPTIONS = dejagnu
DEJATOOL = mail.local
RUNTESTFLAGS =
CLEANFILES = *.log
test_dirs = lib mail.local
EXTRA_DIST = Data
dist-hook:
here=`cd $(top_builddir)/$(subdir) && pwd`; \
srcdir=`cd $(srcdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
for dir in $(test_dirs); \
do \
cd $$srcdir;\
mkdir $$distdir/$$dir;\
cd $$dir;\
for file in DISTFILES `cat DISTFILES`; do \
d=$$srcdir/$$dir; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $$distdir/$$dir/$$file; \
else \
test -f $$distdir/$$dir/$$file \
|| cp -p $$d/$$file $$distdir/$$dir/$$file || exit; \
fi; \
done;\
done;\
cd $$here
site.exp: Makefile remote.exp
@echo 'Making a new site.exp file...'
@test ! -f site.bak || rm -f site.bak
@echo '## these variables are automatically generated by make ##' > $@-t
@echo '# Do not edit here. If you wish to override these values' >> $@-t
@echo '# edit the last section' >> $@-t
@echo 'set tool $(DEJATOOL)' >> $@-t
@echo "set top_srcdir `cd $(top_srcdir); pwd`" >> $@-t
@echo "set srcdir `cd $(srcdir); pwd`" >> $@-t
@echo 'set objdir' `pwd` >> $@-t
@echo 'set host_alias "$(host_alias)"' >> $@-t
@echo 'set host_triplet $(host_triplet)' >> $@-t
@echo 'set target_alias "$(target_alias)"' >> $@-t
@echo 'set target_triplet $(target_triplet)' >> $@-t
@echo 'set build_alias "$(build_alias)"' >> $@-t
@echo 'set build_triplet $(build_triplet)' >> $@-t
@echo '## All variables above are generated by configure. Do Not Edit ##' >> $@-t
@test ! -f site.exp || sed '1,/^## All variables above are.*##/ d' site.exp >> $@-t
@test ! -f site.exp || mv site.exp site.bak
@mv $@-t site.exp
remote.exp:;
@echo 'Making a new remote.exp file...'
@test ! -f remote.bak || rm -f remote.bak
@echo '## These variables are used to set up for the remote testing.' >> $@-t
@echo '## Please, read file README in this directory for instructions' >> $@-t
@echo '## on how to use this file' >> $@-t
@echo "set host_board `hostname`" >> $@-t
@echo 'set board_info($$host_board,connect) rlogin' >> $@-t
@echo 'set board_info($$host_board,shell_prompt) "\\$$ "' >> $@-t
@echo "set board_info(\$$host_board,top_srcdir) `cd $(top_srcdir); pwd`" >> $@-t
@echo "set board_info(\$$host_board,srcdir) `cd $(srcdir); pwd`" >> $@-t
@echo "set board_info(\$$host_board,objdir) `pwd`" >> $@-t
@echo "set board_info(\$$host_board,top_srcdir) `cd $(top_srcdir); pwd`" >> $@-t
@echo "set board_info(\$$host_board,top_builddir) `cd $(top_builddir); pwd`" >> $@-t
@test ! -f remote.exp || mv remote.exp remote.bak
@mv $@-t remote.exp
DISTCLEANFILES=*.exp *.log *.sum
distclean-local:
-rm -rf data
# -*- tcl -*-
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2007, 2008 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
source $top_srcdir/testsuite/lib/mailutils.exp
mu_init "--authentication generic --authorization virtdomain"
mu_version
if ![mu_check_capability ENABLE_VIRTUAL_DOMAINS] {
clone_output "WARNING: Support for virtual domains not compiled in"
clone_output "WARNING: Skipping tests for mail.local"
exit 0
}
mu_prepare_spools
set ETC_DIR "$MU_DATA_DIR/etc"
mu_makespool "$MU_RC_DIR" "$ETC_DIR"
append MU_TOOL_FLAGS " --virtual-passwd-dir $ETC_DIR"
set mu_filename "$MU_SPOOL_DIR/INBOX"
set env(MTA_DIAG) "$mu_filename"
# mail_local_test [-message MESSAGE][-default (FAIL|XFAIL)]
# [-input INPUT-LIST]
# [-args ARGS][-pattern PATTERN-LIST][PATTERN...]
# INPUT-LIST - List of input strings for MU_TOOL
# PATTERN - Sequence to expect in return.
# MESSAGE - [optional] message to output
# ARGS - Additional arguments to MU_TOOL
proc mail_local_test { args } {
global MU_TOOL
global top_builddir
global verbose
global suppress_flag;
global mu_filename
upvar timeout timeout
set default ""
set message ""
set invocation ""
set input ""
set pattern ""
set invocation ""
for {set i 0} {$i < [llength $args]} {incr i} {
set a [lindex $args $i]
if {"$a" == "-default"} {
incr i
set default [lindex $args $i]
} elseif {"$a" == "-message"} {
incr i
set message [lindex $args $i]
} elseif {"$a" == "-pattern"} {
incr i
set pattern [lindex $args $i]
} elseif {"$a" == "-input"} {
incr i
set input [lindex $args $i]
} elseif {"$a" == "-args"} {
incr i
set a [lindex $args $i]
if {[llength $a] > 0} {
append invocation $a
}
} else {
set args [lrange $args $i end]
break
}
}
if {"$message" == ""} {
set message [lindex $args 0]
}
if $verbose>2 then {
send_user "Message is \"$message\"\n"
}
return [mailer_test -default $default -message $message -input $input -pattern $pattern -file $mu_filename -args $invocation]
}
# -*- tcl -*-
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2007 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
set chan [open ${srcdir}/Data r]
# States are:
# INITIAL 0
# MESSAGE 1
# BODY 2
# PATTERN 3
set state 0
# Current pattern. Notice that it is cumulative (i.e. it is not reset
# before each test) since the mailbox itself is cumulative too.
set pattern [list]
for {gets $chan line} {![eof $chan]} {gets $chan line} {
verbose "LINE $line" 1
switch -regexp -- "$line" {
"^#.*" { }
"^MESSAGE END" {
verbose "MAIL FROM $from" 1
verbose "MAIL TO $to" 1
verbose "INPUT $input" 1
verbose "PATTERN $pattern" 1
set args ""
if {$from != ""} {
append args " --from $from"
}
if {$to != ""} {
append args " ${to}@passwd"
}
if {$pattern == ""} {
set pattern [concat [list -re "From $from\[^\r\n\]*"] $input]
}
mail_local_test -message $message -input $input \
-pattern $pattern -args $args
lappend pattern ""
set state 0
}
"^MESSAGE" {
regexp "^MESSAGE (.*)" $line dummy message
set from ""
set to ""
set input [list]
set state 1
}
"^FROM" {
regexp "^FROM (.*)" $line dummy from
}
"^TO" {
regexp "^TO (.*)" $line dummy to
}
"^BODY BEGIN" {
set state 2
}
"^BODY END" {
set state 1
}
"^PATTERN BEGIN" {
set state 3
}
"^PATTERN END" {
set state 1
}
"^STOP" {
break
}
default {
if {$state == 2} {
lappend input $line
} elseif {$state == 3} {
lappend pattern $line
}
}
}
}
close $chan
# End of deliver.exp
Makefile
Makefile.in
mail.remote
out.sendmail
.gdbinit
.deps
.libs
.*.swp
_*
.gdbinit
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2002, 2007 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
INCLUDES = @MU_COMMON_INCLUDES@
SUBDIRS = testsuite
MU_SMTP_PROGRAMS_LIST = mail.remote$(EXEEXT)
EXTRA_PROGRAMS = mail.remote
libexec_PROGRAMS = @MU_SMTP_PROGRAMS_BUILD@
mail_remote_SOURCES = mail.remote.c
mail_remote_LDADD = \
${MU_APP_LIBRARIES}\
${MU_LIB_AUTH}\
${MU_LIB_MAILER}\
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS}\
@MU_COMMON_LIBRARIES@
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2004,
2005, 2007, 2008 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <mailutils/address.h>
#include <mailutils/debug.h>
#include <mailutils/errno.h>
#include <mailutils/list.h>
#include <mailutils/mailer.h>
#include <mailutils/mutil.h>
#include <mailutils/message.h>
#include <mailutils/registrar.h>
#include <mailutils/stream.h>
#include <mailutils/property.h>
#include <mailutils/error.h>
#include <mailutils/nls.h>
#include <mailutils/mu_auth.h>
#include "mailutils/libargp.h"
#include "mu_umaxtostr.h"
const char *program_version = "mail.remote (" PACKAGE_STRING ")";
static char doc[] =
N_("GNU mail.remote -- pseudo-sendmail interface for mail delivery")
"\v"
N_("This is a simple drop-in replacement for sendmail to forward mail directly\n\
to an SMTP gateway.\n\
You should always specify your SMTP gateway using --mailer option\n\
(the best place to do so is in your configuration file).\n\
\n\
Examples:\n\
\n\
Deliver mail via SMTP gateway at \"mail.example.com\", reading its\n\
contents for recipients of the message.\n\
\n\
mail.remote --mailer smtp://mail.example.com -t\n\
\n\
Deliver mail only to \"devnull@foo.bar\"\n\
\n\
mail.remote --mailer smtp://mail.example.com devnull@foo.bar\n\
\n\
Deliver mail to \"devnull@foo.bar\" as well as to the recipients\n\
specified in the message itself:\n\
\n\
mail.remote --mailer smtp://mail.example.com -t devnull@foo.bar\n");
static struct argp_option options[] = {
{"from", 'f', N_("ADDR"), 0, N_("Override the default from address")},
{"read-recipients", 't', NULL, 0, N_("Read message for recipients.") },
{"debug", 'd', NULL, 0, N_("Print envelope commands in the SMTP protocol transaction. If specified more than once, the data part of the protocol transaction will also be printed.")},
{ NULL, 'o', N_("OPT"), 0, N_("Ignored for sendmail compatibility")},
{ NULL, 'b', N_("OPT"), 0, N_("Ignored for sendmail compatibility")},
{ NULL, 'i', NULL, 0, N_("Ignored for sendmail compatibility")},
{ NULL }
};
static int optdebug;
static const char *optfrom;
static int read_recipients; /* Read recipients from the message */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
static struct mu_argp_node_list lst;
static int dbug = 0;
switch (key)
{
case 'f':
mu_argp_node_list_new (&lst, "from", arg);
break;
case 'd':
dbug++;
break;
case 'o':
case 'b':
case 'i':
break;
case 't':
mu_argp_node_list_new (&lst, "read-recipients", "yes");
break;
case ARGP_KEY_INIT:
mu_argp_node_list_init (&lst);
break;
case ARGP_KEY_FINI:
if (dbug)
mu_argp_node_list_new (&lst, "debug", mu_umaxtostr (0, dbug));
mu_argp_node_list_finish (&lst, NULL, NULL);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = {
options,
parse_opt,
N_("[TO-ADDR]..."),
doc,
};
struct mu_cfg_param mail_remote_cfg_param[] = {
{ "from", mu_cfg_string, &optfrom, 0, NULL,
N_("Set sender email address."),
N_("email") },
{ "read-recipients", mu_cfg_string, &read_recipients, 0, NULL,
N_("Read recipient addresses from the message.") },
{ "debug", mu_cfg_int, &optdebug, 0, NULL,
N_("Set debug verbosity level. Level 1 prints envelope commands in "
"the SMTP protocol transaction. Levels 2 and above print the data "
"part of the transaction as well.") },
{ NULL }
};
static const char *capa[] = {
"auth",
"common",
"debug",
"mailer",
"address",
"license",
NULL
};
mu_mailer_t mailer; /* Mailer object */
mu_address_t from; /* Sender address */
mu_address_t to; /* Recipient addresses */
mu_stream_t in; /* Input stream */
void
mr_exit (int status)
{
mu_address_destroy (&from);
mu_address_destroy (&to);
mu_stream_destroy (&in, NULL);
mu_mailer_destroy (&mailer);
exit (status ? 1 : 0);
}
int
main (int argc, char **argv)
{
int status = 0;
int optind = 0;
mu_message_t msg = 0;
int mailer_flags = 0;
/* Native Language Support */
MU_APP_INIT_NLS ();
/* Register mailers. */
mu_registrar_record (mu_smtp_record);
MU_AUTH_REGISTER_ALL_MODULES();
mu_argp_init (program_version, NULL);
if (mu_app_init (&argp, capa, mail_remote_cfg_param,
argc, argv, 0, &optind, NULL))
exit (1);
if (optfrom)
{
if ((status = mu_address_create (&from, optfrom)))
{
mu_error (_("Parsing from addresses failed: %s"),
mu_strerror (status));
mr_exit (status);
}
}
if (argv[optind])
{
if ((status = mu_address_createv (&to, (const char **) (argv + optind), -1)))
{
mu_error (_("Parsing recipient addresses failed: %s"),
mu_strerror (status));
mr_exit (status);
}
}
if ((status = mu_stdio_stream_create (&in, stdin, MU_STREAM_SEEKABLE)))
{
mu_error (_("Failed: %s"), mu_strerror (status));
mr_exit (status);
}
if ((status = mu_stream_open (in)))
{
mu_error (_("Opening stdin failed: %s"), mu_strerror (status));
mr_exit (status);
}
if ((status = mu_message_create (&msg, NULL)))
{
mu_error (_("Failed: %s"), mu_strerror (status));
mr_exit (status);
}
if ((status = mu_message_set_stream (msg, in, NULL)))
{
mu_error (_("Failed: %s"), mu_strerror (status));
mr_exit (status);
}
if ((status = mu_mailer_create (&mailer, NULL)))
{
const char *url = NULL;
mu_mailer_get_url_default (&url);
mu_error (_("Creating mailer `%s' failed: %s"),
url, mu_strerror (status));
mr_exit (status);
}
if (optdebug)
{
mu_debug_t debug;
mu_mailer_get_debug (mailer, &debug);
mu_debug_set_level (debug, MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT));
if (optdebug > 1)
mailer_flags = MAILER_FLAG_DEBUG_DATA;
}
if (read_recipients)
{
mu_property_t property = NULL;
mu_mailer_get_property (mailer, &property);
mu_property_set_value (property, "READ_RECIPIENTS", "true", 1);
}
if ((status = mu_mailer_open (mailer, mailer_flags)))
{
const char *url = NULL;
mu_mailer_get_url_default (&url);
mu_error (_("Opening mailer `%s' failed: %s"),
url, mu_strerror (status));
mr_exit (status);
}
if ((status = mu_mailer_send_message (mailer, msg, from, to)))
{
mu_error (_("Sending message failed: %s"), mu_strerror (status));
mr_exit (status);
}
if ((status = mu_mailer_close (mailer)))
{
mu_error (_("Closing mailer failed: %s"), mu_strerror (status));
mr_exit (status);
}
mr_exit (status);
}
Makefile
Makefile.in
*.log
*.sum
site.exp
remote.exp
data
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2004, 2007 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
MESSAGE Simple mail
BODY BEGIN
From: gray@gnu.org
To: bug-mailutils@gnu.org
Subject: Simple mail
This is a simple mail.
Data goes here.
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <bug-mailutils@gnu.org>
0: From: gray@gnu.org
1: To: bug-mailutils@gnu.org
2: Subject: Simple mail
3:
4: This is a simple mail.
5: Data goes here.
6:
END OF MESSAGE
PATTERN END
MESSAGE END
MESSAGE Explicit from
FROM <gray@localhost>
BODY BEGIN
From: gray@gnu.org
To: bug-mailutils@gnu.org
Subject: Explicit from test.
This is a simple mail.
Data goes here.
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@localhost>
ENVELOPE TO: <bug-mailutils@gnu.org>
0: From: gray@gnu.org
1: To: bug-mailutils@gnu.org
2: Subject: Explicit from test.
3:
4: This is a simple mail.
5: Data goes here.
6:
END OF MESSAGE
PATTERN END
MESSAGE END
MESSAGE Explicit To
TO <alainm@gnu.org> <jbailey@gnu.org>
BODY BEGIN
From: gray@gnu.org
Subject: Expicit destinations
This is a test for working explicit destinations.
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <alainm@gnu.org>,<jbailey@gnu.org>
0: To: <alainm@gnu.org>,<jbailey@gnu.org>
1: From: gray@gnu.org
2: Subject: Expicit destinations
3:
4: This is a test for working explicit destinations.
5:
END OF MESSAGE
PATTERN END
MESSAGE END
MESSAGE CC
BODY BEGIN
From: gray@gnu.org
To: bug-mailutils@gnu.org
Cc: alainm@gnu.org
Subject: Carbon copy test
CC works.
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <bug-mailutils@gnu.org>,<alainm@gnu.org>
0: From: gray@gnu.org
1: To: bug-mailutils@gnu.org
2: Cc: alainm@gnu.org
3: Subject: Carbon copy test
4:
5: CC works.
6:
END OF MESSAGE
PATTERN END
MESSAGE END
MESSAGE BCC
BODY BEGIN
From: gray@gnu.org
To: alainm@gnu.org
Bcc: bug-mailutils@gnu.org
Subject: Blind carbon copy test.
Bcc works too.
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <alainm@gnu.org>
0: From: gray@gnu.org
1: To: alainm@gnu.org
2: Subject: Blind carbon copy test.
3:
4: Bcc works too.
5:
END OF MESSAGE
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <bug-mailutils@gnu.org>
0: Bcc: bug-mailutils@gnu.org
1: From: gray@gnu.org
2: To: alainm@gnu.org
3: Subject: Blind carbon copy test.
4:
5: Bcc works too.
6:
END OF MESSAGE
PATTERN END
MESSAGE END
MESSAGE Complex
TO <root@localhost>
BODY BEGIN
From: gray@gnu.org
Cc: "Alain Magloire" <alainm@gnu.org>, "Jeff Bailey" <jbailey@gnu.org>
Bcc: bug-mailutils@gnu.org
Subject: A complex test
It works?
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <root@localhost>
0: To: <root@localhost>
1: From: gray@gnu.org
2: Cc: "Alain Magloire" <alainm@gnu.org>, "Jeff Bailey" <jbailey@gnu.org>
3: Subject: A complex test
4:
5: It works?
6:
END OF MESSAGE
PATTERN END
MESSAGE END
MESSAGE Complex+Read recipients
OPTIONS -t
TO <root@localhost>
BODY BEGIN
From: gray@gnu.org
Cc: "Alain Magloire" <alainm@gnu.org>, "Jeff Bailey" <jbailey@gnu.org>
Bcc: bug-mailutils@gnu.org
Subject: A complex test
It works?
BODY END
PATTERN BEGIN
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <root@localhost>,<alainm@gnu.org>,<jbailey@gnu.org>
0: To: <root@localhost>,<alainm@gnu.org>,<jbailey@gnu.org>
1: From: gray@gnu.org
2: Cc: "Alain Magloire" <alainm@gnu.org>, "Jeff Bailey" <jbailey@gnu.org>
3: Subject: A complex test
4:
5: It works?
6:
END OF MESSAGE
ENVELOPE FROM: <gray@gnu.org>
ENVELOPE TO: <bug-mailutils@gnu.org>
0: To: <bug-mailutils@gnu.org>
1: Bcc: bug-mailutils@gnu.org
2: From: gray@gnu.org
3: Cc: "Alain Magloire" <alainm@gnu.org>, "Jeff Bailey" <jbailey@gnu.org>
4: Subject: A complex test
5:
6: It works?
7:
END OF MESSAGE
PATTERN END
MESSAGE END
# End of data
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2002, 2007 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
## 02110-1301 USA
AUTOMAKE_OPTIONS = dejagnu
SMTP_DEJATOOL = mail.remote
DEJATOOL = @MU_SMTP_DEJATOOL@
RUNTESTFLAGS =
CLEANFILES = *.log
test_dirs = lib mail.remote
EXTRA_DIST = Data
dist-hook:
here=`cd $(top_builddir)/$(subdir) && pwd`; \
srcdir=`cd $(srcdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
for dir in $(test_dirs); \
do \
cd $$srcdir;\
mkdir $$distdir/$$dir;\
cd $$dir;\
for file in DISTFILES `cat DISTFILES`; do \
d=$$srcdir/$$dir; \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $$distdir/$$dir/$$file; \
else \
test -f $$distdir/$$dir/$$file \
|| cp -p $$d/$$file $$distdir/$$dir/$$file || exit; \
fi; \
done;\
done;\
cd $$here
site.exp: Makefile remote.exp
@echo 'Making a new site.exp file...'
@test ! -f site.bak || rm -f site.bak
@echo '## these variables are automatically generated by make ##' > $@-t
@echo '# Do not edit here. If you wish to override these values' >> $@-t
@echo '# edit the last section' >> $@-t
@echo 'set tool $(DEJATOOL)' >> $@-t
@echo "set top_srcdir `cd $(top_srcdir); pwd`" >> $@-t
@echo "set top_builddir `cd $(top_builddir); pwd`" >> $@-t
@echo "set srcdir `cd $(srcdir); pwd`" >> $@-t
@echo 'set objdir' `pwd` >> $@-t
@echo 'set host_alias "$(host_alias)"' >> $@-t
@echo 'set host_triplet $(host_triplet)' >> $@-t
@echo 'set target_alias "$(target_alias)"' >> $@-t
@echo 'set target_triplet $(target_triplet)' >> $@-t
@echo 'set build_alias "$(build_alias)"' >> $@-t
@echo 'set build_triplet $(build_triplet)' >> $@-t
@echo '## All variables above are generated by configure. Do Not Edit ##' >> $@-t
@test ! -f site.exp || sed '1,/^## All variables above are.*##/ d' site.exp >> $@-t
@test ! -f site.exp || mv site.exp site.bak
@mv $@-t site.exp
remote.exp:;
@echo 'Making a new remote.exp file...'
@test ! -f remote.bak || rm -f remote.bak
@echo '## These variables are used to set up for the remote testing.' >> $@-t
@echo '## Please, read file README in this directory for instructions' >> $@-t
@echo '## on how to use this file' >> $@-t
@echo "set host_board `hostname`" >> $@-t
@echo 'set board_info($$host_board,connect) rlogin' >> $@-t
@echo 'set board_info($$host_board,shell_prompt) "\\$$ "' >> $@-t
@echo "set board_info(\$$host_board,srcdir) `cd $(srcdir); pwd`" >> $@-t
@echo "set board_info(\$$host_board,objdir) `pwd`" >> $@-t
@echo "set board_info(\$$host_board,top_srcdir) `cd $(top_srcdir); pwd`" >> $@-t
@echo "set board_info(\$$host_board,top_builddir) `cd $(top_builddir); pwd`" >> $@-t
@test ! -f remote.exp || mv remote.exp remote.bak
@mv $@-t remote.exp
DISTCLEANFILES=*.exp *.log *.sum
distclean-local:
-rm -rf data
# -*- tcl -*-
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2004, 2007 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
source $top_srcdir/testsuite/lib/mailutils.exp
mu_init -noflags
mu_prepare_spools
set mu_filename "$MU_FOLDER_DIR/mta.diag"
set env(MTA_DIAG) "$mu_filename"
# mail_remote_test [-message MESSAGE][-default (FAIL|XFAIL)]
# [-input INPUT-LIST]
# [-args ARGS][-pattern PATTERN-LIST][PATTERN...]
# INPUT-LIST - List of input strings for MU_TOOL
# PATTERN - Sequence to expect in return.
# MESSAGE - [optional] message to output
# ARGS - Additional arguments to MU_TOOL
proc mail_remote_test { args } {
global MU_TOOL
global top_builddir
global verbose
global suppress_flag;
global mu_filename
upvar timeout timeout
set default ""
set message ""
set invocation ""
set input ""
set pattern ""
for {set i 0} {$i < [llength $args]} {incr i} {
set a [lindex $args $i]
if {"$a" == "-default"} {
incr i
set default [lindex $args $i]
} elseif {"$a" == "-message"} {
incr i
set message [lindex $args $i]
} elseif {"$a" == "-pattern"} {
incr i
set pattern [lindex $args $i]
} elseif {"$a" == "-input"} {
incr i
set input [lindex $args $i]
} elseif {"$a" == "-args"} {
incr i
set a [lindex $args $i]
if {[llength $a] > 0} {
append invocation $a
}
} else {
set args [lrange $args $i end]
break
}
}
set res [remote_spawn host "${top_builddir}/examples/mta -bd"]
if { $res < 0 || $res == "" } {
perror "Spawning mta failed."
return 1
}
remote_expect host 60 {
-re "\[0-9\]\[0-9\]*" {
set port $expect_out(buffer)
set url "smtp://127.0.0.1:$port"
verbose "URL: $url" 1
}
default {
perror "Spawning mta failed."
return 1
}
}
if {"$message" == ""} {
set message [lindex $args 0]
}
if $verbose>2 then {
send_user "Message is \"$message\"\n"
}
return [mailer_test -default $default -message $message \
-input $input -pattern $pattern -file \
$mu_filename -args "--mailer $url $invocation"]
}
# -*- tcl -*-
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2004, 2007 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
set chan [open ${srcdir}/Data r]
set state 0
set command ""
for {gets $chan line} {![eof $chan]} {gets $chan line} {
verbose "LINE $line" 1
switch -regexp -- "$line" {
"^#.*" { }
"^MESSAGE END" {
verbose "MAIL FROM $from" 1
verbose "MAIL TO $to" 1
verbose "INPUT $input" 1
verbose "OPTIONS $options" 1
verbose "PATTERN $pattern" 1
set args ""
if {$from != ""} {
append args " --from $from"
}
if {$options != ""} {
append args " $options"
}
if {$to != ""} {
append args " $to"
}
mail_remote_test -message $message -input $input \
-pattern $pattern -args $args
set state 0
}
"^MESSAGE" {
regexp "^MESSAGE (.*)" $line dummy message
set from ""
set to ""
set options ""
set input [list]
set pattern [list]
set state 1
}
"^FROM" {
regexp "^FROM (.*)" $line dummy from
}
"^TO" {
regexp "^TO (.*)" $line dummy to
}
"^OPTIONS" {
regexp "^OPTIONS (.*)" $line dummy options
}
"^BODY BEGIN" {
set state 2
}
"^BODY END" {
set state 1
}
"^PATTERN BEGIN" {
set state 3
}
"^PATTERN END" {
set state 1
}
"^STOP" {
break
}
default {
if {$state == 2} {
lappend input $line
} elseif {$state == 3} {
lappend pattern $line
}
}
}
}
close $chan
# End of send.exp
......@@ -31,8 +31,8 @@ BuildRequires: python
GNU Mailutils contains a series of useful mail clients, servers, and
libraries. These are the primary mail utilities of the GNU system.
This package provides a replacement for /bin/mail(x) conforming to
the UNIX98 specification for mailx. Provides also mail.local,
mail.remote, and other tools including guimb, dotlock, movemail,
the UNIX98 specification for mailx. It provides also a mail delivery
agent maidag, and other tools including guimb, dotlock, movemail,
frm.
%package -n libmailutils
......
......@@ -99,12 +99,6 @@ maidag/mailquota.c
maidag/mailtmp.c
maidag/script.c
mail.local/mailquota.c
mail.local/main.c
mail.local/script.c
mail.remote/mail.remote.c
mail/alias.c
mail/alt.c
mail/cd.c
......