commit-mailutils
[Top][All Lists]
Advanced

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

[SCM] GNU Mailutils branch, master, updated. release-2.2-561-gf8a9693


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-561-gf8a9693
Date: Sat, 31 Dec 2011 14:57:13 +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=f8a96930b6ec84c63b36e5789c9fdf74285f420c

The branch, master has been updated
       via  f8a96930b6ec84c63b36e5789c9fdf74285f420c (commit)
      from  356c07542f39f1ff159e2646bd97e1791f493aad (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 f8a96930b6ec84c63b36e5789c9fdf74285f420c
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Dec 31 16:48:38 2011 +0200

    Implement SMTPS.
    
    * NEWS: Update.
    * include/mailutils/registrar.h (mu_smtps_record): New extern.
    (mu_register_all_mailer_formats): Register mu_smtps_record.
    * include/mailutils/sys/registrar.h (MU_SMTPS_SCHEME)
    (MU_SMTPS_SCHEME_LEN,MU_SMTPS_PORT): New defines.
    * libmailutils/address/address.c (mu_address_get_count): Don't
    count parts with NULL emails.
    (mu_address_contains_email): Validate email before comparison.
    (mu_list_copy): New static.
    (mu_address_union): Reuse last subaddress if its email is NULL.
    * libmailutils/base/nullrec.c (mu_smtps_record): New placeholder.
    * libproto/mailer/smtp.c (mu_smtps_record): New global.
    (smtp_open): Implement SMTPS
    
    * mu/send.c: New file.
    * mu/Makefile.am (MODULES): Add send.c

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

Summary of changes:
 NEWS                              |    4 +-
 include/mailutils/registrar.h     |    4 +-
 include/mailutils/sys/registrar.h |    4 +
 libmailutils/address/address.c    |  115 +++++++++++++--------
 libmailutils/base/nullrec.c       |    4 +
 libproto/mailer/smtp.c            |   65 ++++++++++--
 mu/Makefile.am                    |    1 +
 mu/send.c                         |  202 +++++++++++++++++++++++++++++++++++++
 8 files changed, 344 insertions(+), 55 deletions(-)
 create mode 100644 mu/send.c

diff --git a/NEWS b/NEWS
index 4a55342..29ce7cc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2011-12-23
+GNU mailutils NEWS -- history of user-visible changes. 2011-12-31
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 Free Software Foundation, Inc.
 See the end of file for copying conditions.
@@ -91,6 +91,8 @@ This feature is useful for those system administrators who 
don't wish
 to permit simultaneous access to mailboxes, even when the nature of the
 mailbox allows that (e.g. maildir).
 
+** SMTPS support.
+
 ** Sieve: new extensions
 
 New extension action `pipe' invokes arbitrary external program and
diff --git a/include/mailutils/registrar.h b/include/mailutils/registrar.h
index f0fbd0a..ae17974 100644
--- a/include/mailutils/registrar.h
+++ b/include/mailutils/registrar.h
@@ -122,8 +122,9 @@ extern mu_record_t mu_maildir_record;
 #define MU_SENDMAIL_PRIO    10000
 #define MU_PROG_PRIO        10000
   
-/* SMTP mailer, "smtp://"  */
+/* SMTP mailer, "smtp://" and "smtps://"  */
 extern mu_record_t mu_smtp_record;
+extern mu_record_t mu_smtps_record;
 /* Sendmail, "sendmail:"  */
 extern mu_record_t mu_sendmail_record;
 /* Program mailer, "prog://", "|" */
@@ -158,6 +159,7 @@ extern mu_record_t mu_prog_record;
 #define mu_register_all_mailer_formats() do {\
   mu_registrar_record (mu_sendmail_record);\
   mu_registrar_record (mu_smtp_record);\
+  mu_registrar_record (mu_smtps_record);\
   mu_registrar_record (mu_prog_record);\
 } while (0)
 
diff --git a/include/mailutils/sys/registrar.h 
b/include/mailutils/sys/registrar.h
index 5d3992b..c725b14 100644
--- a/include/mailutils/sys/registrar.h
+++ b/include/mailutils/sys/registrar.h
@@ -74,6 +74,10 @@ extern int _folder_path_init      (mu_folder_t);
 # define MU_SMTP_SCHEME_LEN (sizeof (MU_SMTP_SCHEME) - 1)
 # define MU_SMTP_PORT 25
 
+# define MU_SMTPS_SCHEME "smtps"
+# define MU_SMTPS_SCHEME_LEN (sizeof (MU_SMTPS_SCHEME) - 1)
+# define MU_SMTPS_PORT 465
+  
 # define MU_SENDMAIL_SCHEME "sendmail"
 # define MU_SENDMAIL_SCHEME_LEN (sizeof (MU_SENDMAIL_SCHEME) - 1)
 extern int _mu_mailer_sendmail_init (mu_mailer_t mailer);
diff --git a/libmailutils/address/address.c b/libmailutils/address/address.c
index 19c33fa..f77230a 100644
--- a/libmailutils/address/address.c
+++ b/libmailutils/address/address.c
@@ -151,6 +151,18 @@ mu_address_createv (mu_address_t *a, const char *sv[], 
size_t len)
   return status;
 }
 
+static void
+_address_free (mu_address_t address)
+{
+  free (address->printable);
+  free (address->comments);
+  free (address->personal);
+  free (address->email);
+  free (address->local_part);
+  free (address->domain);
+  free (address->route);
+}
+
 void
 mu_address_destroy (mu_address_t *paddress)
 {
@@ -160,21 +172,8 @@ mu_address_destroy (mu_address_t *paddress)
       mu_address_t current;
       for (; address; address = current)
        {
-         if (address->printable)
-           free (address->printable);
-         if (address->comments)
-           free (address->comments);
-         if (address->personal)
-           free (address->personal);
-         if (address->email)
-           free (address->email);
-         if (address->local_part)
-           free (address->local_part);
-         if (address->domain)
-           free (address->domain);
-         if (address->route)
-           free (address->route);
          current = address->next;
+         _address_free (address);
          free (address);
        }
       *paddress = NULL;
@@ -642,11 +641,15 @@ 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)
 {
-  size_t j;
-  for (j = 0; addr; addr = addr->next, j++)
-    ;
+  size_t i, count = 0;
+  for (i = 0; addr; addr = addr->next, i++)
+    {
+      mu_validate_email (addr);
+      if (addr->email)
+       ++count;
+    }
   if (pcount)
-    *pcount = j;
+    *pcount = count;
   return 0;
 }
 
@@ -696,37 +699,48 @@ int
 mu_address_contains_email (mu_address_t addr, const char *email)
 {
   for (; addr; addr = addr->next)
-    if (mu_c_strcasecmp (addr->email, email) == 0)
-      return 1;
+    {
+      mu_validate_email (addr);
+      if (!addr->email)
+       break;
+      if (mu_c_strcasecmp (addr->email, email) == 0)
+       return 1;
+    }
   return 0;
 }
 
-mu_address_t
-mu_address_dup (mu_address_t src)
+static int
+mu_list_copy (mu_address_t dst, mu_address_t src)
 {
-  mu_address_t dst = calloc (1, sizeof (*dst));
-
-  if (!dst)
-    return NULL;
-
   /* FIXME: How about:
     if (src->printable)
       dst->printable = strdup (src->printable);
     ?
   */
-  if (src->comments)
-    dst->comments = strdup (src->comments);
-  if (src->personal)
-    dst->personal = strdup (src->personal);
-  if (src->email)
-    dst->email = strdup (src->email);
-  if (src->local_part)
-    dst->local_part = strdup (src->local_part);
-  if (src->domain)
-    dst->domain = strdup (src->domain);
-  if (src->route)
-    dst->route = strdup (src->route);
+  if (src->comments && !(dst->comments = strdup (src->comments)))
+    return ENOMEM;
+  if (src->personal && !(dst->personal = strdup (src->personal)))
+    return ENOMEM;
+  if (src->email && !(dst->email = strdup (src->email)))
+    return ENOMEM;
+  if (src->local_part && !(dst->local_part = strdup (src->local_part)))
+    return ENOMEM;
+  if (src->domain && !(dst->domain = strdup (src->domain)))
+    return ENOMEM;
+  if (src->route && !(dst->route = strdup (src->route)))
+    return ENOMEM;
+  return 0;
+}  
 
+mu_address_t
+mu_address_dup (mu_address_t src)
+{
+  mu_address_t dst = calloc (1, sizeof (*dst));
+
+  if (!dst)
+    return NULL;
+  if (mu_list_copy (dst, src))
+    mu_address_destroy (&dst);
   return dst;
 }
 
@@ -760,11 +774,24 @@ mu_address_union (mu_address_t *a, mu_address_t b)
   for (; b; b = b->next)
     if (!mu_address_contains_email (*a, b->email))
       {
-       mu_address_t next = mu_address_dup (b);
-       if (!next)
-         return ENOMEM;
-       last->next = next;
-       last = next;
+       if (last->email)
+         {
+           mu_address_t next = mu_address_dup (b);
+           if (!next)
+             return ENOMEM;
+           last->next = next;
+           last = next;
+         }
+       else
+         {
+           int rc = mu_list_copy (last, b);
+           if (rc)
+             {
+               _address_free (last);
+               memset (last, 0, sizeof (last));
+               return rc;
+             }
+         }
       }
   return 0;
 }
diff --git a/libmailutils/base/nullrec.c b/libmailutils/base/nullrec.c
index a507a24..80aadbf 100644
--- a/libmailutils/base/nullrec.c
+++ b/libmailutils/base/nullrec.c
@@ -47,3 +47,7 @@ mu_record_t mu_mh_record = NULL;
 mu_record_t mu_maildir_record = NULL;
 #endif
 
+#ifndef WITH_TLS
+mu_record_t mu_smtps_record = NULL;
+#endif
+
diff --git a/libproto/mailer/smtp.c b/libproto/mailer/smtp.c
index 7177f3b..1c80428 100644
--- a/libproto/mailer/smtp.c
+++ b/libproto/mailer/smtp.c
@@ -86,6 +86,27 @@ static struct _mu_record _smtp_record = {
    the mailbox, via the register entry/record.  */
 mu_record_t     mu_smtp_record = &_smtp_record;
 
+#ifdef WITH_TLS
+static struct _mu_record _smtps_record = {
+  MU_SMTP_PRIO,
+  MU_SMTPS_SCHEME,
+  MU_RECORD_DEFAULT,
+  MU_URL_SCHEME | MU_URL_CRED | MU_URL_INET | MU_URL_PARAM,
+  MU_URL_HOST,
+  _url_smtp_init,              /* url init.  */
+  _mu_mailer_mailbox_init,     /* Mailbox init.  */
+  _mailer_smtp_init,           /* Mailer init.  */
+  _mu_mailer_folder_init,      /* Folder init.  */
+  NULL,                                /* No need for a back pointer.  */
+  NULL,                                /* _is_scheme method.  */
+  NULL,                                /* _get_url method.  */
+  NULL,                                /* _get_mailbox method.  */
+  NULL,                                /* _get_mailer method.  */
+  NULL                         /* _get_folder method.  */
+};
+mu_record_t     mu_smtps_record = &_smtps_record;
+#endif
+
 struct _smtp_mailer
 {
   mu_mailer_t     mailer;
@@ -116,14 +137,19 @@ smtp_mailer_add_auth_mech (struct _smtp_mailer 
*smtp_mailer, const char *str)
 static int
 smtp_open (mu_mailer_t mailer, int flags)
 {
-  const char *auth;
+  const char *auth, *scheme;
   struct _smtp_mailer *smtp_mailer = mailer->data;
   int rc;
   size_t parmc = 0;
   char **parmv = NULL;
-  int notls = 0;
+  int tls = 0;
+  int nostarttls = 0;
   int noauth = 0;
-  
+
+  rc = mu_url_sget_scheme (mailer->url, &scheme);
+  if (rc == 0) 
+    tls = strcmp (scheme, "smtps") == 0;
+
   rc = mu_smtp_create (&smtp_mailer->smtp);
   if (rc)
     return rc;
@@ -150,7 +176,7 @@ smtp_open (mu_mailer_t mailer, int flags)
       for (i = 0; i < parmc; i++)
        {
          if (strcmp (parmv[i], "notls") == 0)
-           notls = 1;
+           nostarttls = 1;
          else if (strcmp (parmv[i], "noauth") == 0)
            noauth = 1;
          else if (strncmp (parmv[i], "auth=", 5) == 0)
@@ -163,23 +189,44 @@ smtp_open (mu_mailer_t mailer, int flags)
     {
       struct mu_sockaddr *sa;
       struct mu_sockaddr_hints hints;
-
+      mu_stream_t transport;
+      
       memset (&hints, 0, sizeof (hints));
       hints.flags = MU_AH_DETECT_FAMILY;
-      hints.port = 25;
+      hints.port = tls ? MU_SMTPS_PORT : MU_SMTP_PORT;
       hints.protocol = IPPROTO_TCP;
       hints.socktype = SOCK_STREAM;
       rc = mu_sockaddr_from_url (&sa, mailer->url, &hints);
       if (rc)
        return rc;
       
-      rc = mu_tcp_stream_create_from_sa (&mailer->stream, sa, NULL,
-                                        mailer->flags);
+      rc = mu_tcp_stream_create_from_sa (&transport, sa, NULL, mailer->flags);
       if (rc)
         {
           mu_sockaddr_free (sa);
          return rc;
        }
+#ifdef WITH_TLS
+      if (tls && mu_tls_enable)
+       {
+         mu_stream_t tlsstream;
+         
+         rc = mu_tls_client_stream_create (&tlsstream, transport, transport,
+                                           0);
+         mu_stream_unref (transport);
+         if (rc)
+           {
+             mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
+                       (_("cannot create TLS stream: %s"),
+                        mu_strerror (rc)));
+             mu_sockaddr_free (sa);
+             return rc;
+           }
+         transport = tlsstream;
+         nostarttls = 1;
+       }
+#endif
+      mailer->stream = transport;
       mu_stream_set_buffer (mailer->stream, mu_buffer_line, 0);
     }
   mu_smtp_set_carrier (smtp_mailer->smtp, mailer->stream);
@@ -194,7 +241,7 @@ smtp_open (mu_mailer_t mailer, int flags)
     return rc;
 
 #ifdef WITH_TLS
-  if (!notls && mu_tls_enable &&
+  if (!nostarttls && mu_tls_enable &&
       mu_smtp_capa_test (smtp_mailer->smtp, "STARTTLS", NULL) == 0)
     {
       rc = mu_smtp_starttls (smtp_mailer->smtp);
diff --git a/mu/Makefile.am b/mu/Makefile.am
index e28b984..05408fa 100644
--- a/mu/Makefile.am
+++ b/mu/Makefile.am
@@ -51,6 +51,7 @@ MODULES = \
  ldflags.c\
  logger.c\
  $(POP_C)\
+ send.c\
  query.c\
  wicket.c
 
diff --git a/mu/send.c b/mu/send.c
new file mode 100644
index 0000000..0d4402d
--- /dev/null
+++ b/mu/send.c
@@ -0,0 +1,202 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2010, 2011 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, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <mailutils/cctype.h>
+#include <mailutils/mailutils.h>
+#include <argp.h>
+#include "mu.h"
+
+static int read_recipients;
+static mu_address_t rcpt_addr;
+static mu_address_t from_addr;
+
+static void
+send_address_add (mu_address_t *paddr, const char *value)
+{
+  mu_address_t addr = NULL;
+  int rc;
+
+  rc = mu_address_create (&addr, value);
+  if (rc)
+    {
+      mu_error (_("%s: %s"), value, mu_strerror (rc));
+      exit (1);
+    }
+  MU_ASSERT (mu_address_union (paddr, addr));
+  mu_address_destroy (&addr);
+}
+
+static char send_doc[] = N_("mu send - send a message.");
+char send_docstring[] = N_("send a message");
+static char send_args_doc[] = "URL-or-HOST [FILE]";
+
+static struct argp_option send_options[] = {
+  { "from",  'F', N_("ADDRESS"), 0,
+    N_("send mail from this ADDRESS") },
+  { "rcpt",  'T', N_("ADDRESS"), 0,
+    N_("send mail to this ADDRESS") },
+  { "read-recipients", 't', NULL, 0,
+    N_("read recipients from the message") },
+  { NULL }
+};
+
+static error_t
+send_parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'F':
+      MU_ASSERT (mu_address_create_null (&from_addr));
+      send_address_add (&from_addr, arg);
+      break;
+
+    case 'T':
+      send_address_add (&rcpt_addr, arg);
+      break;
+
+    case 't':
+      read_recipients = 1;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp send_argp = {
+  send_options,
+  send_parse_opt,
+  send_args_doc,
+  send_doc,
+  NULL,
+  NULL,
+  NULL
+};
+
+int
+mutool_send (int argc, char **argv)
+{
+  int index;
+  char *infile;
+  mu_stream_t instr;
+  mu_message_t msg;
+  size_t count;
+  mu_url_t urlhint, url;
+  mu_mailer_t mailer;
+  
+  MU_ASSERT (mu_address_create_null (&rcpt_addr));
+  mu_register_all_mailer_formats ();
+  
+  if (argp_parse (&send_argp, argc, argv, 0, &index, NULL))
+    return 1;
+
+  argc -= index;
+  argv += index;
+
+  if (argc < 1)
+    {
+      mu_error (_("not enough arguments"));
+      return 1;
+    }
+
+  infile = argv[1];
+  if (infile)
+    MU_ASSERT (mu_file_stream_create (&instr, infile,
+                                     MU_STREAM_READ|MU_STREAM_SEEK));
+  else
+    MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD,
+                                      MU_STREAM_READ|MU_STREAM_SEEK));
+
+  MU_ASSERT (mu_stream_to_message (instr, &msg));
+  mu_stream_unref (instr);
+
+  mu_address_get_count (rcpt_addr, &count);
+  if (count == 0)
+    read_recipients = 1;
+
+  if (read_recipients)
+    {
+      int rc;
+      mu_header_t header;
+      const char *value;
+
+      MU_ASSERT (mu_message_get_header (msg, &header));
+         
+      rc = mu_header_sget_value (header, MU_HEADER_TO, &value);
+      if (rc == 0)
+       send_address_add (&rcpt_addr, value);
+      else if (rc != MU_ERR_NOENT)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value",
+                          MU_HEADER_TO, rc);
+         exit (1);
+       }
+      
+      rc = mu_header_sget_value (header, MU_HEADER_CC, &value);
+      if (rc == 0)
+       send_address_add (&rcpt_addr, value);
+      else if (rc != MU_ERR_NOENT)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value",
+                          MU_HEADER_CC, rc);
+         exit (1);
+       }
+
+      rc = mu_header_sget_value (header, MU_HEADER_BCC, &value);
+      if (rc == 0)
+       send_address_add (&rcpt_addr, value);
+      else if (rc != MU_ERR_NOENT)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value",
+                          MU_HEADER_BCC, rc);
+         exit (1);
+       }
+    }
+
+  mu_address_get_count (rcpt_addr, &count);
+  if (count == 0)
+    {
+      mu_error (_("no recipients"));
+      exit (1);
+    }
+  
+  MU_ASSERT (mu_url_create (&urlhint, "smtp://"));
+  MU_ASSERT (mu_url_create_hint (&url, argv[0], MU_URL_PARSE_DEFAULT,
+                                urlhint));
+  mu_url_invalidate (url);
+  MU_ASSERT (mu_mailer_create_from_url (&mailer, url));
+  MU_ASSERT (mu_mailer_open (mailer, MU_STREAM_RDWR));
+  MU_ASSERT (mu_mailer_send_message (mailer, msg, from_addr, rcpt_addr));
+  mu_mailer_close (mailer);
+  mu_mailer_destroy (&mailer);
+  return 0;
+}
+
+/*
+  MU Setup: send
+  mu-handler: mutool_send
+  mu-docstring: send_docstring
+  End MU Setup:
+*/


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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