summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--include/mailutils/registrar.h4
-rw-r--r--include/mailutils/sys/registrar.h4
-rw-r--r--libmailutils/address/address.c115
-rw-r--r--libmailutils/base/nullrec.c4
-rw-r--r--libproto/mailer/smtp.c65
-rw-r--r--mu/Makefile.am1
-rw-r--r--mu/send.c202
8 files changed, 344 insertions, 55 deletions
diff --git a/NEWS b/NEWS
index 4a5534238..29ce7ccc6 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 f0fbd0afe..ae1797432 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 5d3992bf9..c725b14a0 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 19c33fa46..f77230ac4 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 a507a245d..80aadbf0a 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 7177f3b7d..1c8042822 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 e28b98485..05408fa6b 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 000000000..0d4402d5e
--- /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:
+*/

Return to:

Send suggestions and report system problems to the System administrator.