commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg-264-gd971eab
Date: Wed, 15 Apr 2009 14:49:35 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=d971eaba5417d3a06c332d1a6bf1929bb51f4d90

The branch, master has been updated
       via  d971eaba5417d3a06c332d1a6bf1929bb51f4d90 (commit)
      from  b1594c2aaaaf49641fa93d568a41613c6d8de9aa (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d971eaba5417d3a06c332d1a6bf1929bb51f4d90
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Apr 15 17:49:12 2009 +0300

    Improve RFC822 address parsing.
    
    * examples/addr.c: Allow to modify hints via command line (-v)
    and within the shell (\...).
    * include/mailutils/address.h (MU_ADDR_HINT_*): New defines.
    (struct _mu_address): Definition.
    (mu_address_create_hint): New prototype.
    * include/mailutils/parse822.h (mu_parse822_address_list)
    (mu_parse822_mail_box, mu_parse822_group)
    (mu_parse822_address, mu_parse822_route_addr)
    (mu_parse822_route, mu_parse822_addr_spec)
    (mu_parse822_unix_mbox, mu_parse822_local_part): Take hint and hint flags.
    * mailbox/parse822.c: Likewise.
    
    * libproto/include/Makefile.am (noinst_HEADERS): Remove address0.h
    * libproto/include/address0.h: Removed.
    * mailbox/address.c (mu_address_create_hint): New function.
    (mu_address_create): Rewrite using mu_address_create_hint.
    
    * mh/mh_init.c (mh_expand_aliases): Use mu_header_sget_field_name
    * mh/mh_whom.c (mh_alias_expand): Rewrite using mu_address_create_hint.
    This fixes parsing addresses similar to "address@hidden <address@hidden>".
    * mh/send.c: New command line option --preserve (--keep)

-----------------------------------------------------------------------

Summary of changes:
 examples/addr.c              |  100 ++++++++++++++++--
 include/mailutils/address.h  |   43 ++++++++-
 include/mailutils/parse822.h |  117 +++++++++++++--------
 libproto/include/Makefile.am |    4 +-
 libproto/include/address0.h  |   65 ------------
 mailbox/address.c            |   47 ++++++---
 mailbox/parse822.c           |  235 +++++++++++++++++++++++++++--------------
 mh/mh_init.c                 |    7 +-
 mh/mh_whom.c                 |   82 ++++++---------
 mh/send.c                    |   19 +++-
 10 files changed, 443 insertions(+), 276 deletions(-)
 delete mode 100644 libproto/include/address0.h

diff --git a/examples/addr.c b/examples/addr.c
index 277352b..f8b5874 100644
--- a/examples/addr.c
+++ b/examples/addr.c
@@ -26,10 +26,14 @@
 
 #include <mailutils/address.h>
 #include <mailutils/errno.h>
+#include <mailutils/kwd.h>
 #include <mailutils/mutil.h>
 
 #define EPARSE MU_ERR_NOENT
 
+struct _mu_address hint;
+int hflags;
+
 static int
 parse (const char *str)
 {
@@ -39,8 +43,7 @@ parse (const char *str)
   const char *buf;
   mu_address_t address = NULL;
 
-  mu_set_user_email_domain ("localhost");
-  status = mu_address_create (&address, str);
+  status = mu_address_create_hint (&address, str, &hint, hflags);
   mu_address_get_count (address, &pcount);
 
   if (status)
@@ -96,6 +99,73 @@ parse (const char *str)
   return 0;
 }
 
+struct mu_kwd hintnames[] = {
+  { "comments", MU_ADDR_HINT_COMMENTS },
+  { "personal", MU_ADDR_HINT_PERSONAL },
+  { "email", MU_ADDR_HINT_EMAIL },
+  { "local", MU_ADDR_HINT_LOCAL },
+  { "domain", MU_ADDR_HINT_DOMAIN },
+  { "route", MU_ADDR_HINT_ROUTE },
+  { NULL }
+};
+
+static char **
+addr_fieldptr_by_mask (mu_address_t addr, int mask)
+{
+  switch (mask)                                                
+    {
+    case MU_ADDR_HINT_ADDR:
+      return &addr->addr;
+         
+    case MU_ADDR_HINT_COMMENTS:                                
+      return &addr->comments;                                  
+         
+    case MU_ADDR_HINT_PERSONAL:                                
+      return &addr->personal;                                  
+
+    case MU_ADDR_HINT_EMAIL:
+      return &addr->email;
+
+    case MU_ADDR_HINT_LOCAL:
+      return &addr->local_part;
+      
+    case MU_ADDR_HINT_DOMAIN:                          
+      return &addr->domain;                                    
+
+    case MU_ADDR_HINT_ROUTE:
+      return &addr->route;
+    }
+  return NULL;
+}                                                      
+
+void
+sethint (char *str)
+{
+  int mask;
+  char *p = strchr (str, '=');
+
+  if (!p)
+    {
+      printf ("%s=> bad assignment\n\n", str);
+      return;
+    }
+  *p++ = 0;
+  if (mu_kwd_xlat_name (hintnames, str, &mask) == 0)
+    {
+      char **fptr = addr_fieldptr_by_mask (&hint, mask);
+
+      if (*p == 0)
+       hflags &= ~mask;
+      else
+       {
+         *fptr = strdup (p);
+         hflags |= mask;
+       }
+    }
+  else
+    printf ("%s=> unknown hint name\n\n", str);
+}
+       
 static int
 parseinput (void)
 {
@@ -104,26 +174,34 @@ parseinput (void)
   while (fgets (buf, sizeof (buf), stdin) != 0)
     {
       buf[strlen (buf) - 1] = 0;
-      parse (buf);
+      if (buf[0] == '\\')
+       sethint (buf + 1);
+      else
+       parse (buf);
     }
 
   return 0;
 }
 
 int
-main (int argc, const char *argv[])
+main (int argc, char *argv[])
 {
-  argc = 1;
-
-  if (!argv[argc])
+  int i;
+  
+  hint.domain = "localhost";
+  hflags = MU_ADDR_HINT_DOMAIN;
+  
+  if (argc == 1)
     return parseinput ();
-
-  for (; argv[argc]; argc++)
+  
+  for (i = 1; i < argc; i++)
     {
-      if (strcmp (argv[argc], "-") == 0)
+      if (strcmp (argv[i], "-") == 0)
        parseinput ();
+      else if (strncmp (argv[i], "-v", 2) == 0)
+       sethint (argv[i] + 2);
       else
-       parse (argv[argc]);
+       parse (argv[i]);
     }
 
   return 0;
diff --git a/include/mailutils/address.h b/include/mailutils/address.h
index 5adaa57..c68811c 100644
--- a/include/mailutils/address.h
+++ b/include/mailutils/address.h
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2005, 2006, 2007,
+   2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,46 @@
 extern "C" {
 #endif
 
+#define MU_ADDR_HINT_ADDR       0x0001 /* Not used yet */
+#define MU_ADDR_HINT_COMMENTS   0x0002
+#define MU_ADDR_HINT_PERSONAL   0x0004
+#define MU_ADDR_HINT_EMAIL      0x0008
+#define MU_ADDR_HINT_LOCAL      0x0010
+#define MU_ADDR_HINT_DOMAIN     0x0020
+#define MU_ADDR_HINT_ROUTE      0x0040
+
+/*
+ * The data-structure representing an RFC822 MAILBOX. It may be
+ * one MAILBOX or a list of them, as found in an ADDRESS or
+ * a MAILBOX list (as found in a GROUP).
+ *  
+ * Capitalized names are from RFC 822, section 6.1 (Address Syntax).
+ */
+struct _mu_address
+{
+  char *addr;
+       /* the original string that this list of addresses was created
+        * from, only present at the head of the list */
+
+  char *comments;
+       /* the collection of comments stripped during parsing this MAILBOX */
+  char *personal;
+       /* the PHRASE portion of a MAILBOX, called the DISPLAY-NAME in drums */
+  char *email;
+       /* the ADDR-SPEC, the address@hidden */
+  char *local_part;
+       /* the LOCAL-PART of a MAILBOX */
+  char *domain;
+       /* the DOMAIN of a MAILBOX */
+  char *route;
+       /* the optional ROUTE in the ROUTE-ADDR form of MAILBOX */
+
+  struct _mu_address *next;
+};
+
+extern int mu_address_create_hint (mu_address_t *, const char *,
+                                  mu_address_t, int);
+  
 extern int mu_address_create   (mu_address_t *, const char *);
 extern int mu_address_createv  (mu_address_t *, const char *v[], size_t);
 extern void mu_address_destroy (mu_address_t *);
diff --git a/include/mailutils/parse822.h b/include/mailutils/parse822.h
index f1aad60..83e3820 100644
--- a/include/mailutils/parse822.h
+++ b/include/mailutils/parse822.h
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2005, 2007  Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2005, 2007,
+   2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -49,57 +50,89 @@ extern int mu_parse822_is_q_text      (char c);
 extern int mu_parse822_is_d_text      (char c);
 extern int mu_parse822_is_smtp_q      (char c);
 
-extern int mu_parse822_skip_crlf      (const char** p, const char* e);
-extern int mu_parse822_skip_lwsp_char (const char** p, const char* e);
-extern int mu_parse822_skip_lwsp      (const char** p, const char* e);
-extern int mu_parse822_skip_comments  (const char** p, const char* e);
-extern int mu_parse822_skip_nl        (const char** p, const char* e);
-
-extern int mu_parse822_digits         (const char** p, const char* e, int min, 
int max, int* digits);
-extern int mu_parse822_special        (const char** p, const char* e, char c);
-extern int mu_parse822_comment        (const char** p, const char* e, char** 
comment);
-extern int mu_parse822_atom           (const char** p, const char* e, char** 
atom);
-extern int mu_parse822_quoted_pair    (const char** p, const char* e, char** 
qpair);
-extern int mu_parse822_quoted_string  (const char** p, const char* e, char** 
qstr);
-extern int mu_parse822_word           (const char** p, const char* e, char** 
word);
-extern int mu_parse822_phrase         (const char** p, const char* e, char** 
phrase);
-extern int mu_parse822_d_text         (const char** p, const char* e, char** 
dtext);
+extern int mu_parse822_skip_crlf      (const char **p, const char *e);
+extern int mu_parse822_skip_lwsp_char (const char **p, const char *e);
+extern int mu_parse822_skip_lwsp      (const char **p, const char *e);
+extern int mu_parse822_skip_comments  (const char **p, const char *e);
+extern int mu_parse822_skip_nl        (const char **p, const char *e);
+
+extern int mu_parse822_digits         (const char **p, const char *e,
+                                      int min, int max, int *digits);
+extern int mu_parse822_special        (const char **p, const char *e, char c);
+extern int mu_parse822_comment        (const char **p, const char *e,
+                                      char **comment);
+extern int mu_parse822_atom           (const char **p, const char *e,
+                                      char **atom);
+extern int mu_parse822_quoted_pair    (const char **p, const char *e,
+                                      char **qpair);
+extern int mu_parse822_quoted_string  (const char **p, const char *e,
+                                      char **qstr);
+extern int mu_parse822_word           (const char **p, const char *e,
+                                      char **word);
+extern int mu_parse822_phrase         (const char **p, const char *e,
+                                      char **phrase);
+extern int mu_parse822_d_text         (const char **p, const char *e,
+                                      char **dtext);
 
 /* From RFC 822, 6.1 Address Specification Syntax */
 
-extern int mu_parse822_address_list   (mu_address_t* a, const char* s);
-extern int mu_parse822_mail_box       (const char** p, const char* e, 
mu_address_t* a);
-extern int mu_parse822_group          (const char** p, const char* e, 
mu_address_t* a);
-extern int mu_parse822_address        (const char** p, const char* e, 
mu_address_t* a);
-extern int mu_parse822_route_addr     (const char** p, const char* e, 
mu_address_t* a);
-extern int mu_parse822_route          (const char** p, const char* e, char** 
route);
-extern int mu_parse822_addr_spec      (const char** p, const char* e, 
mu_address_t* a);
-extern int mu_parse822_unix_mbox      (const char** p, const char* e, 
mu_address_t* a);
-extern int mu_parse822_local_part     (const char** p, const char* e, char** 
local_part);
-extern int mu_parse822_domain         (const char** p, const char* e, char** 
domain);
-extern int mu_parse822_sub_domain     (const char** p, const char* e, char** 
sub_domain);
-extern int mu_parse822_domain_ref     (const char** p, const char* e, char** 
domain_ref);
-extern int mu_parse822_domain_literal (const char** p, const char* e, char** 
domain_literal);
+extern int mu_parse822_address_list   (mu_address_t *a, const char *s,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_mail_box       (const char **p, const char *e,
+                                      mu_address_t *a,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_group          (const char **p, const char *e,
+                                      mu_address_t *a,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_address        (const char **p, const char *e,
+                                      mu_address_t *a,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_route_addr     (const char **p, const char *e,
+                                      mu_address_t *a,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_route          (const char **p, const char *e,
+                                      char **route);
+extern int mu_parse822_addr_spec      (const char **p, const char *e,
+                                      mu_address_t *a,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_unix_mbox      (const char **p, const char *e,
+                                      mu_address_t *a,
+                                      mu_address_t hint, int hflags);
+extern int mu_parse822_local_part     (const char **p, const char *e,
+                                      char **local_part);
+extern int mu_parse822_domain         (const char **p, const char *e,
+                                      char **domain);
+extern int mu_parse822_sub_domain     (const char **p, const char *e,
+                                      char **sub_domain);
+extern int mu_parse822_domain_ref     (const char **p, const char *e,
+                                      char **domain_ref);
+extern int mu_parse822_domain_literal (const char **p, const char *e,
+                                      char **domain_literal);
 
 /* RFC 822 Quoting Functions
-* Various elements must be quoted if then contain non-safe characters. What
-* characters are allowed depend on the element. The following functions will
-* allocate a quoted version of the raw element, it may not actually be
-* quoted if no unsafe characters were in the raw string.
-*/
+ * Various elements must be quoted if then contain non-safe characters. What
+ * characters are allowed depend on the element. The following functions will
+ * allocate a quoted version of the raw element, it may not actually be
+ * quoted if no unsafe characters were in the raw string.
+ */
 
-extern int mu_parse822_quote_string     (char** quoted, const char* raw);
-extern int mu_parse822_quote_local_part (char** quoted, const char* raw);
+extern int mu_parse822_quote_string     (char **quoted, const char *raw);
+extern int mu_parse822_quote_local_part (char **quoted, const char *raw);
 
-extern int mu_parse822_field_body       (const char** p, const char *e, char** 
fieldbody);
-extern int mu_parse822_field_name       (const char** p, const char *e, char** 
fieldname);
+extern int mu_parse822_field_body       (const char **p, const char *e,
+                                        char **fieldbody);
+extern int mu_parse822_field_name       (const char **p, const char *e,
+                                        char **fieldname);
 
 /***** From RFC 822, 5.1 Date and Time Specification Syntax *****/
 
-extern int mu_parse822_day       (const char** p, const char* e, int* day);
-extern int mu_parse822_date      (const char** p, const char* e, int* day, 
int* mon, int* year);
-extern int mu_parse822_time      (const char** p, const char* e, int* h, int* 
m, int* s, int* tz, const char** tz_name);
-extern int mu_parse822_date_time (const char** p, const char* e, struct tm* 
tm, mu_timezone* tz);
+extern int mu_parse822_day       (const char **p, const char *e, int *day);
+extern int mu_parse822_date      (const char **p, const char *e, int *day,
+                                 int *mon, int *year);
+extern int mu_parse822_time      (const char **p, const char *e, int *h,
+                                 int *m, int *s, int *tz, const char 
**tz_name);
+extern int mu_parse822_date_time (const char **p, const char *e,
+                                 struct tm *tm, mu_timezone *tz);
 
 
 #ifdef __cplusplus
diff --git a/libproto/include/Makefile.am b/libproto/include/Makefile.am
index 406e550..b2be394 100644
--- a/libproto/include/Makefile.am
+++ b/libproto/include/Makefile.am
@@ -1,6 +1,7 @@
 ## Process this file with GNU Automake to create Makefile.in
 
-##   Copyright (C) 2000, 2001, 2002, 2007 Free Software Foundation, Inc.
+##   Copyright (C) 2000, 2001, 2002, 2007,
+##   2009 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
@@ -18,7 +19,6 @@
 ##   02110-1301 USA
 
 noinst_HEADERS = \
-address0.h \
 attribute0.h \
 amd.h \
 auth0.h \
diff --git a/libproto/include/address0.h b/libproto/include/address0.h
deleted file mode 100644
index da5ea95..0000000
--- a/libproto/include/address0.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 3 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General
-   Public License along with this library; if not, write to the
-   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301 USA */
-
-#ifndef _ADDRESS0_H
-#define _ADDRESS0_H
-
-#ifdef DMALLOC
-#  include <dmalloc.h>
-#endif
-
-#include <mailutils/address.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * The data-structure representing an RFC822 MAILBOX. It may be
- * one MAILBOX or a list of them, as found in an ADDRESS or
- * a MAILBOX list (as found in a GROUP).
- *  
- * Capitalized names are from RFC 822, section 6.1 (Address Syntax).
- */
-struct _mu_address
-{
-  char *addr;
-       /* the original string that this list of addresses was created
-        * from, only present at the head of the list */
-
-  char *comments;
-       /* the collection of comments stripped during parsing this MAILBOX */
-  char *personal;
-       /* the PHRASE portion of a MAILBOX, called the DISPLAY-NAME in drums */
-  char *email;
-       /* the ADDR-SPEC, the address@hidden */
-  char *local_part;
-       /* the LOCAL-PART of a MAILBOX */
-  char *domain;
-       /* the DOMAIN of a MAILBOX */
-  char *route;
-       /* the optional ROUTE in the ROUTE-ADDR form of MAILBOX */
-
-  struct _mu_address *next;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ADDRESS0_H */
diff --git a/mailbox/address.c b/mailbox/address.c
index a22fb1e..115ee86 100644
--- a/mailbox/address.c
+++ b/mailbox/address.c
@@ -1,6 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
    Copyright (C) 1999, 2000, 2001, 2005, 2006,
-   2007 Free Software Foundation, Inc.
+   2007, 2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -34,12 +34,12 @@
 #include <mailutils/errno.h>
 #include <mailutils/mutil.h>
 #include <mailutils/parse822.h>
-
-#include <address0.h>
+#include <mailutils/address.h>
 
 /* Get email addresses from rfc822 address.  */
 int
-mu_address_create (mu_address_t * a, const char *s)
+mu_address_create_hint (mu_address_t *a, const char *s, mu_address_t hint,
+                       int hflags)
 {
   /* 'a' must exist, and can't already have been initialized
    */
@@ -52,7 +52,7 @@ mu_address_create (mu_address_t * a, const char *s)
     return EINVAL;
 
   *a = NULL;
-  status = mu_parse822_address_list (a, s);
+  status = mu_parse822_address_list (a, s, hint, hflags);
   if (status == 0)
     {
       /* And address-list may contain 0 addresses but parse correctly.
@@ -70,9 +70,20 @@ mu_address_create (mu_address_t * a, const char *s)
   return status;
 }
 
-/* Get email addresses from array of rfc822 addresses. */
 int
-mu_address_createv (mu_address_t * a, const char *sv[], size_t len)
+mu_address_create (mu_address_t *a, const char *s)
+{
+  struct _mu_address hint;
+  const char *d;
+  mu_get_user_email_domain (&d);
+  hint.domain = (char*) d;
+  return mu_address_create_hint (a, s, &hint, MU_ADDR_HINT_DOMAIN);
+}
+
+/* Get email addresses from array of rfc822 addresses.
+   FIXME: No hints? */
+int
+mu_address_createv (mu_address_t *a, const char *sv[], size_t len)
 {
   int status = 0;
   size_t buflen = 0;
@@ -130,7 +141,7 @@ mu_address_createv (mu_address_t * a, const char *sv[], 
size_t len)
 }
 
 void
-mu_address_destroy (mu_address_t * paddress)
+mu_address_destroy (mu_address_t *paddress)
 {
   if (paddress && *paddress)
     {
@@ -160,7 +171,7 @@ mu_address_destroy (mu_address_t * paddress)
 }
 
 int
-mu_address_concatenate (mu_address_t to, mu_address_t * from)
+mu_address_concatenate (mu_address_t to, mu_address_t *from)
 {
   if (!to || !from || !*from)
     return EINVAL;
@@ -254,7 +265,6 @@ ACCESSOR(sget,field) (mu_address_t addr, size_t no, char 
const **sptr)      \
   subaddr = _address_get_nth (addr, no);                               \
   if (!subaddr)                                                                
\
     return MU_ERR_NOENT;                                               \
-                                                                       \
   *sptr = subaddr->field;                                              \
   return 0;                                                            \
 }
@@ -262,7 +272,7 @@ ACCESSOR(sget,field) (mu_address_t addr, size_t no, char 
const **sptr)      \
 #define DECL_GET(field)                                                        
  \
 int                                                                      \
 ACCESSOR(get,field) (mu_address_t addr, size_t no, char *buf, size_t len, \
-                    size_t * n)                                          \
+                    size_t *n)                                           \
 {                                                                        \
   size_t i;                                                              \
   const char *str;                                                       \
@@ -429,7 +439,7 @@ mu_address_is_group (mu_address_t addr, size_t no, int *yes)
 }
 
 int
-mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t * n)
+mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t *n)
 {
   size_t i;
   if (addr == NULL)
@@ -453,7 +463,7 @@ mu_address_to_string (mu_address_t addr, char *buf, size_t 
len, size_t * n)
 }
 
 int
-mu_address_get_count (mu_address_t addr, size_t * pcount)
+mu_address_get_count (mu_address_t addr, size_t *pcount)
 {
   size_t j;
   for (j = 0; addr; addr = addr->next, j++)
@@ -464,7 +474,7 @@ mu_address_get_count (mu_address_t addr, size_t * pcount)
 }
 
 int
-mu_address_get_group_count (mu_address_t addr, size_t * pcount)
+mu_address_get_group_count (mu_address_t addr, size_t *pcount)
 {
   size_t j;
   for (j = 0; addr; addr = addr->next)
@@ -478,7 +488,7 @@ mu_address_get_group_count (mu_address_t addr, size_t * 
pcount)
 }
 
 int
-mu_address_get_email_count (mu_address_t addr, size_t * pcount)
+mu_address_get_email_count (mu_address_t addr, size_t *pcount)
 {
   size_t j;
   for (j = 0; addr; addr = addr->next)
@@ -492,7 +502,7 @@ mu_address_get_email_count (mu_address_t addr, size_t * 
pcount)
 }
 
 int
-mu_address_get_unix_mailbox_count (mu_address_t addr, size_t * pcount)
+mu_address_get_unix_mailbox_count (mu_address_t addr, size_t *pcount)
 {
   size_t j;
   for (j = 0; addr; addr = addr->next)
@@ -522,6 +532,11 @@ mu_address_dup (mu_address_t src)
   if (!dst)
     return NULL;
 
+  /* FIXME: How about:
+    if (src->addr)
+      dst->addr = strdup (src->addr);
+    ?
+  */
   if (src->comments)
     dst->comments = strdup (src->comments);
   if (src->personal)
diff --git a/mailbox/parse822.c b/mailbox/parse822.c
index 0501144..a26815d 100644
--- a/mailbox/parse822.c
+++ b/mailbox/parse822.c
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2005, 2007,
+   2009 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -87,10 +88,9 @@ actually help.
 # include <strings.h>
 #endif
 
-#include "address0.h"
-
 #include <mailutils/errno.h>
 #include <mailutils/parse822.h>
+#include <mailutils/address.h>
 
 #ifdef EOK
 # undef EOK
@@ -478,7 +478,7 @@ mu_parse822_atom (const char **p, const char *e, char 
**atom)
 
   save = *p;
 
-  while ((*p != e) && mu_parse822_is_atom_char (**p))
+  while ((*p != e) && (**p == '.' || mu_parse822_is_atom_char (**p)))
     {
       rc = str_append_char (atom, **p);
       *p += 1;
@@ -495,24 +495,18 @@ int
 parse822_atom_ex (const char **p, const char *e, char **atom)
 {
   /* atom = 1*<an atom char> */
-
-  const char *save = *p;
-  int rc = EPARSE;
+  const char *ptr;
+  int rc;
 
   mu_parse822_skip_comments (p, e);
 
-  save = *p;
-
-  while ((*p != e) && parse822_is_atom_char_ex (**p))
-    {
-      rc = str_append_char (atom, **p);
-      *p += 1;
-      if (rc != EOK)
-       {
-         *p = save;
-         break;
-       }
-    }
+  for (ptr = *p; (ptr != e) && parse822_is_atom_char_ex (*ptr); ptr++)
+    ;
+  if (ptr - *p == 0)
+    return EPARSE;
+  rc = str_append_n (atom, *p, ptr - *p);
+  if (rc == 0)
+    *p = ptr;
   return rc;
 }
 
@@ -714,59 +708,133 @@ new_mb (void)
   return calloc (1, sizeof (struct _mu_address));
 }
 
+static char *
+addr_field_by_mask (mu_address_t addr, int mask)
+{
+  switch (mask)                                                
+    {
+    case MU_ADDR_HINT_ADDR:
+      return addr->addr;
+         
+    case MU_ADDR_HINT_COMMENTS:                                
+      return addr->comments;                                   
+         
+    case MU_ADDR_HINT_PERSONAL:                                
+      return addr->personal;                                   
+
+    case MU_ADDR_HINT_EMAIL:
+      return addr->email;
+
+    case MU_ADDR_HINT_LOCAL:
+      return addr->local_part;
+      
+    case MU_ADDR_HINT_DOMAIN:                          
+      return addr->domain;                                     
+
+    case MU_ADDR_HINT_ROUTE:
+      return addr->route;
+    }
+  return NULL;
+}                                                      
+
+static char *
+get_val (mu_address_t hint, int hflags, char *value, int mask, int *memflag)
+{
+  if (!value && hint && (hflags & mask))
+    {
+      char *p = addr_field_by_mask (hint, mask);
+      if (p)                                                   
+       {
+         if (memflag)
+           *memflag |= mask;
+         value = strdup (p);
+       }
+    }
+  return value;
+}
+
+static void
+addr_free_fields (mu_address_t a, int memflag)
+{
+  char *p;
+  
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_ADDR)))
+    free (p);
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_COMMENTS)))
+    free (p);
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_PERSONAL)))
+    free (p);
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_EMAIL)))
+    free (p);
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_LOCAL)))
+    free (p);
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_DOMAIN)))
+    free (p);
+  if ((p = addr_field_by_mask (a, memflag & MU_ADDR_HINT_ROUTE)))
+    free (p);
+}
+
 static int
-fill_mb (mu_address_t * a,
-        char *comments, char *personal, char *local, char *domain)
+fill_mb (mu_address_t *pa,
+        char *comments, char *personal, char *local, char *domain,
+        mu_address_t hint, int hflags)
 {
   int rc = EOK;
+  mu_address_t a;
+  int memflag = 0;
 
-  *a = new_mb ();
+  a = new_mb ();
 
-  if (!*a)
-    {
-      return ENOMEM;
-    }
+  if (!a)
+    return ENOMEM;
 
-  (*a)->comments = comments;
-  (*a)->personal = personal;
+  a->comments = get_val (hint, hflags, comments, MU_ADDR_HINT_COMMENTS,
+                        &memflag);
+  a->personal = get_val (hint, hflags, personal, MU_ADDR_HINT_PERSONAL,
+                        &memflag);
 
+  domain = get_val (hint, hflags, domain, MU_ADDR_HINT_DOMAIN,
+                   &memflag);
+  local = get_val (hint, hflags, local, MU_ADDR_HINT_LOCAL,
+                  &memflag);
   do
     {
       /* loop exists only to break out of */
-      const char *d = domain;
-      if (!d)
-       {
-         mu_get_user_email_domain (&d);
-       }
-      if (!local || !d)
-       {
-         /* no email to construct */
-         break;
-       }
-      if ((rc = mu_parse822_quote_local_part (&(*a)->email, local)))
-       break;
-      if ((rc = str_append (&(*a)->email, "@")))
+      if (!local)
+       /* no email to construct */
        break;
-      if ((rc = str_append (&(*a)->email, d)))
+
+      if ((rc = mu_parse822_quote_local_part (&a->email, local)))
        break;
+      if (domain)
+       {
+         if ((rc = str_append (&a->email, "@")))
+           break;
+         if ((rc = str_append (&a->email, domain)))
+           break;
+       }
     }
   while (0);
 
-  (*a)->local_part = local;
-  (*a)->domain = domain;
+  a->local_part = local;
+  a->domain = domain;
 
   if (rc != EOK)
     {
+      addr_free_fields (a, memflag);
       /* note that the arguments have NOT been freed, we only own
        * them on success. */
-      free (*a);
+      free (a);
     }
+  else
+    *pa = a;
 
   return rc;
 }
 
 int
-mu_parse822_address_list (mu_address_t * a, const char *s)
+mu_parse822_address_list (mu_address_t *a, const char *s,
+                         mu_address_t hint, int hflags)
 {
   /* address-list = #(address) */
 
@@ -775,7 +843,7 @@ mu_parse822_address_list (mu_address_t * a, const char *s)
   int rc = EOK;
   mu_address_t *n = a;         /* the next address we'll be creating */
 
-  rc = mu_parse822_address (p, e, n);
+  rc = mu_parse822_address (p, e, n, hint, hflags);
 
   /* A list may start with a leading <,>, we'll find out if
    * that's not the case at the top of the while, but give
@@ -808,7 +876,7 @@ mu_parse822_address_list (mu_address_t * a, const char *s)
        }
       mu_parse822_skip_comments (p, e);
 
-      rc = mu_parse822_address (p, e, n);
+      rc = mu_parse822_address (p, e, n, hint, hflags);
 
       if (rc == EOK || rc == EPARSE)
        {
@@ -833,20 +901,24 @@ mu_parse822_address_list (mu_address_t * a, const char *s)
 }
 
 int
-mu_parse822_address (const char **p, const char *e, mu_address_t * a)
+mu_parse822_address (const char **p, const char *e, mu_address_t *a,
+                    mu_address_t hint, int hflags)
 {
   /* address = mailbox / group / unix-mbox */
 
   int rc;
 
-  if ((rc = mu_parse822_mail_box (p, e, a)) == EPARSE)
+  if ((rc = mu_parse822_mail_box (p, e, a, hint, hflags)) == EPARSE)
     {
-      if ((rc = mu_parse822_group (p, e, a)) == EPARSE)
+      if ((rc = mu_parse822_group (p, e, a, hint, hflags)) == EPARSE)
        {
-         rc = mu_parse822_unix_mbox (p, e, a);
+         rc = mu_parse822_unix_mbox (p, e, a, hint, hflags);
        }
     }
 
+  if (rc == 0 && *a && !(*a)->route)
+    (*a)->route = get_val (hint, hflags, NULL, MU_ADDR_HINT_ROUTE, NULL);
+
   return rc;
 }
 
@@ -856,7 +928,8 @@ mu_parse822_address (const char **p, const char *e, 
mu_address_t * a)
  */
 #undef ADD_GROUPS
 int
-mu_parse822_group (const char **p, const char *e, mu_address_t * a)
+mu_parse822_group (const char **p, const char *e, mu_address_t *a,
+                  mu_address_t hint, int hflags)
 {
   /* group = phrase ":" [#mailbox] ";" */
 
@@ -886,7 +959,7 @@ mu_parse822_group (const char **p, const char *e, 
mu_address_t * a)
   /* fake up an address node for the group's descriptive phrase, if
    * it fails, clean-up will happen after the loop
    */
-  if ((rc = fill_mb (a, 0, phrase, 0, 0)) == EOK)
+  if ((rc = fill_mb (a, 0, phrase, 0, 0, hint, hflags)) == EOK)
     {
       a = &(*a)->next;
     }
@@ -907,7 +980,7 @@ mu_parse822_group (const char **p, const char *e, 
mu_address_t * a)
       mu_parse822_skip_comments (p, e);
 
       /* it's ok not be a mailbox, but other errors are fatal */
-      rc = mu_parse822_mail_box (p, e, a);
+      rc = mu_parse822_mail_box (p, e, a, hint, hflags);
       if (rc == EOK)
        {
          a = &(*a)->next;
@@ -941,7 +1014,8 @@ mu_parse822_group (const char **p, const char *e, 
mu_address_t * a)
 }
 
 int
-mu_parse822_mail_box (const char **p, const char *e, mu_address_t * a)
+mu_parse822_mail_box (const char **p, const char *e, mu_address_t *a,
+                     mu_address_t hint, int hflags)
 {
   /* mailbox =
    *     addr-spec [ "(" comment ")" ] /
@@ -956,7 +1030,7 @@ mu_parse822_mail_box (const char **p, const char *e, 
mu_address_t * a)
   int rc;
 
   /* -> addr-spec */
-  if ((rc = mu_parse822_addr_spec (p, e, a)) == EOK)
+  if ((rc = mu_parse822_addr_spec (p, e, a, hint, hflags)) == EOK)
     {
       mu_parse822_skip_lwsp (p, e);
 
@@ -987,7 +1061,7 @@ mu_parse822_mail_box (const char **p, const char *e, 
mu_address_t * a)
        return rc;
       }
 
-    if ((rc = mu_parse822_route_addr (p, e, a)) == EOK)
+    if ((rc = mu_parse822_route_addr (p, e, a, hint, hflags)) == EOK)
       {
        /* add the phrase */
        (*a)->personal = phrase;
@@ -1005,14 +1079,16 @@ mu_parse822_mail_box (const char **p, const char *e, 
mu_address_t * a)
 }
 
 int
-mu_parse822_route_addr (const char **p, const char *e, mu_address_t * a)
+mu_parse822_route_addr (const char **p, const char *e, mu_address_t *a,
+                       mu_address_t hint, int hflags)
 {
   /* route-addr = "<" [route] addr-spec ">" */
 
   const char *save = *p;
-  char *route = 0;
+  char *route = NULL;
   int rc;
-
+  int memflag = 0;
+  
   mu_parse822_skip_comments (p, e);
 
   if ((rc = mu_parse822_special (p, e, '<')))
@@ -1023,15 +1099,15 @@ mu_parse822_route_addr (const char **p, const char *e, 
mu_address_t * a)
     }
   if (!(rc = mu_parse822_special (p, e, '>')))
     {
-      (void) (((rc = fill_mb (a, 0, 0, 0, 0)) == EOK)
-          && ((rc = str_append (&(*a)->email, "")) == EOK));
+      if ((rc = fill_mb (a, 0, 0, 0, 0, hint, hflags)) == EOK)
+       rc = str_append (&(*a)->email, "");
        
       return rc;
     }
 
   mu_parse822_route (p, e, &route);
 
-  if ((rc = mu_parse822_addr_spec (p, e, a)))
+  if ((rc = mu_parse822_addr_spec (p, e, a, hint, hflags)))
     {
       *p = save;
 
@@ -1040,7 +1116,8 @@ mu_parse822_route_addr (const char **p, const char *e, 
mu_address_t * a)
       return rc;
     }
 
-  (*a)->route = route;         /* now we don't have to free our local */
+  (*a)->route = get_val (hint, hflags, route, MU_ADDR_HINT_ROUTE,
+                        &memflag);
 
   mu_parse822_skip_comments (p, e);
 
@@ -1121,7 +1198,8 @@ mu_parse822_route (const char **p, const char *e, char 
**route)
 }
 
 int
-mu_parse822_addr_spec (const char **p, const char *e, mu_address_t * a)
+mu_parse822_addr_spec (const char **p, const char *e, mu_address_t *a,
+                      mu_address_t hint, int hflags)
 {
   /* addr-spec = local-part "@" domain */
 
@@ -1137,18 +1215,16 @@ mu_parse822_addr_spec (const char **p, const char *e, 
mu_address_t * a)
   if (!rc)
     {
       rc = mu_parse822_special (p, e, '@');
-    }
-
-  if (!rc)
-    {
-      rc = mu_parse822_domain (p, e, &domain);
-    }
+      
+      if (!rc)
+       {
+         rc = mu_parse822_domain (p, e, &domain);
 
-  if (!rc)
-    {
-      rc = fill_mb (a, 0, 0, local_part, domain);
+         if (!rc)
+           rc = fill_mb (a, 0, 0, local_part, domain, hint, hflags);
+       }
     }
-
+  
   if (rc)
     {
       *p = save;
@@ -1159,7 +1235,8 @@ mu_parse822_addr_spec (const char **p, const char *e, 
mu_address_t * a)
 }
 
 int
-mu_parse822_unix_mbox (const char **p, const char *e, mu_address_t * a)
+mu_parse822_unix_mbox (const char **p, const char *e, mu_address_t *a,
+                      mu_address_t hint, int hflags)
 {
   /* unix-mbox = atom */
 
@@ -1172,9 +1249,7 @@ mu_parse822_unix_mbox (const char **p, const char *e, 
mu_address_t * a)
   rc = mu_parse822_atom (p, e, &mbox);
 
   if (!rc)
-    {
-      rc = fill_mb (a, 0, 0, mbox, 0);
-    }
+    rc = fill_mb (a, 0, 0, mbox, 0, hint, hflags);
 
   if (rc)
     {
diff --git a/mh/mh_init.c b/mh/mh_init.c
index 7fc2629..629fb04 100644
--- a/mh/mh_init.c
+++ b/mh/mh_init.c
@@ -1,6 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
    Copyright (C) 1999, 2000, 2001, 2002, 2003, 
-   2005, 2006, 2007 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2009 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
@@ -931,13 +931,13 @@ mh_expand_aliases (mu_message_t msg,
 {
   mu_header_t hdr;
   size_t i, num;
-  char *buf;
+  const char *buf;
   
   mu_message_get_header (msg, &hdr);
   mu_header_get_field_count (hdr, &num);
   for (i = 1; i <= num; i++)
     {
-      if (mu_header_aget_field_name (hdr, i, &buf) == 0)
+      if (mu_header_sget_field_name (hdr, i, &buf) == 0)
        {
          if (strcasecmp (buf, MU_HEADER_TO) == 0
              || strcasecmp (buf, MU_HEADER_CC) == 0
@@ -958,7 +958,6 @@ mh_expand_aliases (mu_message_t msg,
              else if (strcasecmp (buf, MU_HEADER_BCC) == 0)
                mu_address_union (addr_bcc ? addr_bcc : addr_to, addr);
            }
-         free (buf);
        }
     }
 }
diff --git a/mh/mh_whom.c b/mh/mh_whom.c
index 1fb3410..70371c7 100644
--- a/mh/mh_whom.c
+++ b/mh/mh_whom.c
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005, 2006, 2007, 2009 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
@@ -51,69 +51,47 @@ ismydomain (char *p)
   return strcasecmp (domain, p + 1) == 0;
 }
 
+/* FIXME: incl is not used */
 int
 mh_alias_expand (const char *str, mu_address_t *paddr, int *incl)
 {
-  int argc;
-  char **argv;
-  int i;
-  char *buf;
-  mu_address_t exaddr = NULL;
-
+  size_t i, count;
+  mu_address_t addr;
+  int status;
+  
   if (incl)
     *incl = 0;
-  mu_argcv_get (str, ",", NULL, &argc, &argv);
-  for (i = 0; i < argc;)
+  status = mu_address_create_hint (&addr, str, NULL, 0);
+  if (status)
     {
-      if (i + 1 == argc)
-       {
-         if (mh_alias_get_address (argv[i], &exaddr, incl) == 0)
-           {
-             free (argv[i]);
-             memcpy (&argv[i], &argv[i+1],
-                     (argc - i + 1) * sizeof (argv[0]));
-             argc--;
-           }
-         else
-           i++;
-       }
-      else if (argv[i + 1][0] == ',')
+      mu_error (_("Bad address `%s': %s"), str, mu_strerror (status));
+      return 1;
+    }
+
+  mu_address_get_count (addr, &count);
+  for (i = 1; i <= count; i++)
+    {
+      mu_address_t subaddr = NULL;
+      const char *key;
+
+      if (mu_address_sget_domain (addr, i, &key) == 0 && key == NULL)
        {
-         if (mh_alias_get_address (argv[i], &exaddr, incl) == 0)
-           {
-             free (argv[i]);
-             free (argv[i+1]);
-             memcpy (&argv[i], &argv[i+2],
-                     (argc - i) * sizeof (argv[0]));
-             argc -= 2;
-           }
-         else
-           i += 2;
+         if (mu_address_sget_local_part (addr, i, &key) == 0
+             && mh_alias_get_address (key, paddr, incl) == 0)
+           continue;
        }
-      else
+
+      status = mu_address_get_nth (addr, i, &subaddr);
+      if (status)
        {
-         for (; i < argc; i++)
-           if (argv[i][0] == ',')
-             {
-               i++;
-               break;
-             }
+         mu_error (_("%s: cannot get address #%lu: %s"),
+                   str, (unsigned long) i, mu_strerror (status));
+         continue;
        }
-    }
 
-  if (argc)
-    {
-      int status;
-      mu_argcv_string (argc, argv, &buf);
-      if ((status = mu_address_create (paddr, buf)))
-       mu_error (_("Bad address `%s': %s"), buf, mu_strerror (status));
-      free (buf);
+      mu_address_union (paddr, subaddr);
+      mu_address_destroy (&subaddr);
     }
-
-  mu_argcv_free (argc, argv);
-  
-  mu_address_union (paddr, exaddr);
-  mu_address_destroy (&exaddr);
   return 0;
 }
 
diff --git a/mh/send.c b/mh/send.c
index 42a60fc..7563b24 100644
--- a/mh/send.c
+++ b/mh/send.c
@@ -1,5 +1,6 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005, 2006, 2007, 2008,
+   2009 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
@@ -61,6 +62,9 @@ static struct argp_option options[] = {
   {"push",          ARG_PUSH,          N_("BOOL"), OPTION_ARG_OPTIONAL,
    N_("Run in the backround.") },
   {"nopush",        ARG_NOPUSH,        NULL, OPTION_HIDDEN, "" },
+  {"preserve",      ARG_PRESERVE,      N_("BOOL"), OPTION_ARG_OPTIONAL,
+   N_("Keep draft files") },
+  {"keep",          0, NULL, OPTION_ALIAS, NULL},
   {"split",         ARG_SPLIT,         N_("SECONDS"), 0,
    N_("Split the draft into several partial messages and send them with 
SECONDS interval") },
   {"chunksize",     ARG_CHUNKSIZE,     N_("NUMBER"), 0,
@@ -91,7 +95,9 @@ struct mh_option mh_option[] = {
   {"forward",       4, MH_OPT_BOOL, NULL},
   {"mime",          2, MH_OPT_BOOL, NULL},
   {"msgid",         2, MH_OPT_BOOL, NULL},
-  {"push",          1, MH_OPT_BOOL, NULL},
+  {"push",          2, MH_OPT_BOOL, NULL},
+  {"preserve",      2, MH_OPT_BOOL, NULL},
+  {"keep",          1, MH_OPT_BOOL, NULL},
   {"split",         1, 0, "seconds"},
   {"verbose",       1, MH_OPT_BOOL, NULL},
   {"watch",         2, MH_OPT_BOOL, NULL},
@@ -116,6 +122,8 @@ static int verbose;              /* Produce verbose 
diagnostics */
 static int watch;                /* Watch the delivery process */
 static unsigned width = 76;      /* Maximum width of header fields */
 
+static int keep_files;           /* Keep draft files */
+
 #define DEFAULT_X_MAILER "MH (" PACKAGE_STRING ")"
 
 #define WATCH(c) do {\
@@ -196,6 +204,10 @@ opt_handler (int key, char *arg, void *unused, struct 
argp_state *state)
     case ARG_NOMSGID:
       append_msgid = 0;
       break;
+
+    case ARG_PRESERVE:
+      keep_files = is_true (arg);
+      break;
       
     case ARG_PUSH:
       background = is_true (arg);
@@ -690,7 +702,8 @@ _action_send (void *item, void *data)
   mu_mailer_close (mailer);
   mu_mailer_destroy (&mailer);
 
-  backup_file (elt->file_name);
+  if (!keep_files)
+    backup_file (elt->file_name);
   
   return 0;
 }


hooks/post-receive
--
GNU Mailutils




reply via email to

[Prev in Thread] Current Thread [Next in Thread]