Commit 4362a34e 4362a34e703c6057a91c3501879f1faa55069aed by Sergey Poznyakoff

Begin new implementation of the SMTP client.

* include/mailutils/smtp.h: New file.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add smtp.h.
* include/mailutils/list.h (mu_list_clear): New proto.
* include/mailutils/sys/smtp.h: New file.
* include/mailutils/sys/Makefile.am (sysinclude_HEADERS): Add smtp.h.
* libmailutils/errors (MU_ERR_BADREPLY, MU_ERR_SEQ): New error codes.
* libmailutils/list.c (mu_list_clear): New function.
* libproto/mailer/Makefile.am (libmu_mailer_la_SOURCES): Add new sources.
* libproto/mailer/smtp_capa.c: New file.
* libproto/mailer/smtp_carrier.c: New file.
* libproto/mailer/smtp_create.c: New file.
* libproto/mailer/smtp_disconnect.c: New file.
* libproto/mailer/smtp_domain.c: New file.
* libproto/mailer/smtp_ehlo.c: New file.
* libproto/mailer/smtp_io.c: New file.
* libproto/mailer/smtp_open.c: New file.
* libproto/mailer/smtp_starttls.c: New file.
* libproto/mailer/smtp_trace.c: New file.
* testsuite/smtpsend.c: New file.
* testsuite/Makefile.am (noinst_PROGRAMS): Add smtpsend.
1 parent 52d2552d
......@@ -90,6 +90,7 @@ pkginclude_HEADERS = \
secret.h\
server.h\
sieve.h\
smtp.h\
stream.h\
syslog.h\
sql.h\
......
......@@ -28,6 +28,7 @@ extern "C" {
extern int mu_list_create (mu_list_t *);
extern void mu_list_destroy (mu_list_t *);
extern void mu_list_clear (mu_list_t list);
extern int mu_list_append (mu_list_t, void *item);
extern int mu_list_prepend (mu_list_t, void *item);
extern int mu_list_insert (mu_list_t list, void *item, void *new_item,
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _MAILUTILS_SMTP_H
# define _MAILUTILS_SMTP_H
# include <sys/types.h>
# include <sys/socket.h>
# include <mailutils/types.h>
typedef struct _mu_smtp *mu_smtp_t;
int mu_smtp_create (mu_smtp_t *);
void mu_smtp_destroy (mu_smtp_t *);
int mu_smtp_set_carrier (mu_smtp_t smtp, mu_stream_t str);
int mu_smtp_get_carrier (mu_smtp_t smtp, mu_stream_t *pcarrier);
int mu_smtp_open (mu_smtp_t);
int mu_smtp_response (mu_smtp_t smtp);
int mu_smtp_write (mu_smtp_t smtp, const char *fmt, ...);
#define MU_SMTP_TRACE_CLR 0
#define MU_SMTP_TRACE_SET 1
#define MU_SMTP_TRACE_QRY 2
int mu_smtp_trace (mu_smtp_t smtp, int op);
int mu_smtp_trace_mask (mu_smtp_t smtp, int op, int lev);
int mu_smtp_disconnect (mu_smtp_t smtp);
int mu_smtp_ehlo (mu_smtp_t smtp);
int mu_smtp_set_domain (mu_smtp_t smtp, const char *newdom);
int mu_smtp_get_domain (mu_smtp_t smtp, const char **pdom);
int mu_smtp_capa_test (mu_smtp_t smtp, const char *capa, const char **pret);
int mu_smtp_starttls (mu_smtp_t smtp);
#endif
......@@ -51,6 +51,7 @@ sysinclude_HEADERS = \
property.h\
rdcache_stream.h\
registrar.h\
smtp.h\
streamref.h\
streamtrans.h\
stream.h\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _MAILUTILS_SYS_SMTP_H
# define _MAILUTILS_SYS_SMTP_H
# include <sys/types.h>
# include <sys/socket.h>
# include <mailutils/types.h>
# include <mailutils/smtp.h>
# define _MU_SMTP_ESMTP 0x01 /* Connection supports ESMTP */
# define _MU_SMTP_TRACE 0x02 /* Session trace required/enabled */
# define _MU_SMTP_ERR 0x04 /* Object in error state */
# define _MU_SMTP_MLREPL 0x08 /* Last reply was multi-line */
# define _MU_SMTP_TLS 0x10 /* TLS initiated */
# define _MU_SMTP_AUTH 0x20 /* Authorization passed */
#define MU_SMTP_XSCRIPT_MASK(n) (0x100<<(n))
enum mu_smtp_state
{
MU_SMTP_INIT,
MU_SMTP_EHLO,
MU_SMTP_MAIL,
};
struct _mu_smtp
{
int flags;
char *domain;
mu_stream_t carrier;
enum mu_smtp_state state;
mu_list_t capa;
char replcode[4];
char *replptr;
char *rdbuf;
size_t rdsize;
char *flbuf;
size_t flsize;
mu_list_t mlrepl;
};
#define MU_SMTP_FSET(p,f) ((p)->flags |= (f))
#define MU_SMTP_FISSET(p,f) ((p)->flags & (f))
#define MU_SMTP_FCLR(p,f) ((p)->flags &= ~(f))
#define MU_SMTP_CHECK_ERROR(smtp, status) \
do \
{ \
if (status != 0) \
{ \
smtp->flags |= _MU_SMTP_ERR; \
return status; \
} \
} \
while (0)
int _mu_smtp_trace_enable (mu_smtp_t smtp);
int _mu_smtp_trace_disable (mu_smtp_t smtp);
#endif
......@@ -60,6 +60,9 @@ MU_ERR_BAD_2047_ENCODING _("Not a valid RFC 2047 encoding")
MU_ERR_NOUSERNAME _("User name is not supplied")
MU_ERR_NOPASSWORD _("User password is not supplied")
MU_ERR_BADREPLY _("Invalid reply from the remote host")
MU_ERR_SEQ _("Bad command sequence")
MU_ERR_UNSAFE_PERMS _("Unsafe file permissions. Set 0600")
MU_ERR_BAD_AUTH_SCHEME _("Unsupported authentication scheme")
......
......@@ -61,11 +61,8 @@ mu_list_create (mu_list_t *plist)
}
void
mu_list_destroy (mu_list_t *plist)
mu_list_clear (mu_list_t list)
{
if (plist && *plist)
{
mu_list_t list = *plist;
struct list_data *current;
struct list_data *previous;
......@@ -77,7 +74,17 @@ mu_list_destroy (mu_list_t *plist)
DESTROY_ITEM (list, previous);
free (previous);
}
list->head.next = list->head.prev = &list->head;
mu_monitor_unlock (list->monitor);
}
void
mu_list_destroy (mu_list_t *plist)
{
if (plist && *plist)
{
mu_list_t list = *plist;
mu_list_clear (list);
mu_monitor_destroy (&list->monitor, list);
free (list);
*plist = NULL;
......
......@@ -28,5 +28,15 @@ libmu_mailer_la_SOURCES = \
prog.c\
sendmail.c\
smtp.c\
smtp_capa.c\
smtp_carrier.c\
smtp_create.c\
smtp_disconnect.c\
smtp_domain.c\
smtp_ehlo.c\
smtp_io.c\
smtp_open.c\
smtp_starttls.c\
smtp_trace.c\
remote.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <mailutils/errno.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_capa_test (mu_smtp_t smtp, const char *name, const char **pret)
{
if (!smtp || !name)
return EINVAL;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
return MU_ERR_FAILURE;
if (!smtp->capa)
{
int rc = mu_smtp_ehlo (smtp);
if (rc)
return rc;
}
if (!MU_SMTP_FISSET (smtp, _MU_SMTP_ESMTP))
return MU_ERR_FAILURE;
return mu_list_locate (smtp->capa, (void*) name, (void**)pret);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/stream.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_set_carrier (mu_smtp_t smtp, mu_stream_t carrier)
{
/* Sanity checks. */
if (smtp == NULL)
return EINVAL;
if (smtp->carrier)
{
/* Close any old carrier. */
mu_smtp_disconnect (smtp);
mu_stream_destroy (&smtp->carrier);
}
mu_stream_ref (carrier);
smtp->carrier = carrier;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE))
_mu_smtp_trace_enable (smtp);
return 0;
}
int
mu_smtp_get_carrier (mu_smtp_t smtp, mu_stream_t *pcarrier)
{
/*FIXME*/
return ENOSYS;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/stream.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_create (mu_smtp_t *psmtp)
{
struct _mu_smtp *smtp;
if (!psmtp)
return EINVAL;
smtp = calloc (1, sizeof (*smtp));
if (!smtp)
return ENOMEM;
smtp->state = MU_SMTP_INIT;
*psmtp = smtp;
return 0;
}
void
mu_smtp_destroy (mu_smtp_t *psmtp)
{
struct _mu_smtp *smtp;
if (!psmtp || !*psmtp)
return;
smtp = *psmtp;
mu_stream_destroy (&smtp->carrier);
mu_list_destroy (&smtp->capa);
free (smtp->rdbuf);
free (smtp->flbuf);
mu_list_destroy (&smtp->mlrepl);
free (smtp);
*psmtp = NULL;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/stream.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_disconnect (mu_smtp_t smtp)
{
if (smtp == NULL)
return EINVAL;
smtp->state = MU_SMTP_INIT;
if (smtp->rdbuf)
smtp->rdbuf[0] = 0;
return mu_stream_close (smtp->carrier);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/errno.h>
#include <mailutils/cctype.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_set_domain (mu_smtp_t smtp, const char *newdom)
{
char *dom;
if (!smtp)
return EINVAL;
dom = strdup (newdom);
if (!dom)
return ENOMEM;
free (smtp->domain);
smtp->domain = dom;
return 0;
}
int
mu_smtp_get_domain (mu_smtp_t smtp, const char **pdom)
{
if (!smtp)
return EINVAL;
*pdom = smtp->domain;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/errno.h>
#include <mailutils/cctype.h>
#include <mailutils/list.h>
#include <mailutils/mutil.h>
#include <mailutils/smtp.h>
#include <mailutils/sys/smtp.h>
static int
capa_comp (const void *item, const void *value)
{
const char *capa = item;
const char *needle = value;
for (; *needle; capa++, needle++)
{
if (!*capa)
return 1;
if (mu_tolower (*capa) != mu_tolower (*needle))
return 1;
}
return !(*capa == 0 || mu_isspace (*capa));
}
int
mu_smtp_ehlo (mu_smtp_t smtp)
{
int status;
if (!smtp)
return EINVAL;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
return MU_ERR_FAILURE;
if (!smtp->domain)
{
char *host;
char *p;
status = mu_get_host_name (&host);
MU_SMTP_CHECK_ERROR (smtp, status);
p = strchr (host, '.');
if (p)
p++;
else
p = host;
status = mu_smtp_set_domain (smtp, p);
MU_SMTP_CHECK_ERROR (smtp, status);
}
status = mu_smtp_write (smtp, "EHLO %s\r\n", smtp->domain);
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_smtp_response (smtp);
MU_SMTP_CHECK_ERROR (smtp, status);
if (smtp->replcode[0] == '2')
{
smtp->flags |= _MU_SMTP_ESMTP;
smtp->capa = smtp->mlrepl;
smtp->mlrepl = NULL;
mu_list_set_comparator (smtp->capa, capa_comp);
}
else if (smtp->replcode[0] == '4')
return EAGAIN;
else
{
status = mu_smtp_write (smtp, "HELO %s\r\n", smtp->domain);
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_smtp_response (smtp);
MU_SMTP_CHECK_ERROR (smtp, status);
smtp->flags &= ~_MU_SMTP_ESMTP;
if (smtp->replcode[0] == '4')
return EAGAIN;
else if (smtp->replcode[0] != '2')
return MU_ERR_FAILURE;
}
smtp->state = MU_SMTP_MAIL;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <mailutils/cstr.h>
#include <mailutils/cctype.h>
#include <mailutils/diag.h>
#include <mailutils/errno.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/stream.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_write (mu_smtp_t smtp, const char *fmt, ...)
{
va_list ap;
int rc;
va_start (ap, fmt);
rc = mu_stream_vprintf (smtp->carrier, fmt, ap);
va_end (ap);
return rc;
}
static int
_mu_smtp_init_mlist (mu_smtp_t smtp)
{
if (!smtp->mlrepl)
{
int rc = mu_list_create (&smtp->mlrepl);
if (rc == 0)
mu_list_set_destroy_item (smtp->mlrepl, mu_list_free_item);
return rc;
}
else
mu_list_clear (smtp->mlrepl);
return 0;
}
int
mu_smtp_response (mu_smtp_t smtp)
{
int rc;
size_t n;
rc = mu_stream_getline (smtp->carrier, &smtp->rdbuf, &smtp->rdsize, &n);
MU_SMTP_CHECK_ERROR (smtp, rc);
if (n == 0)
MU_SMTP_CHECK_ERROR (smtp, EIO);
n = mu_rtrim_cset (smtp->rdbuf, "\r\n");
if (n < 3 || !mu_isdigit (smtp->rdbuf[0]))
{
mu_diag_output (MU_DIAG_NOTICE,
"received invalid reply from SMTP server");
MU_SMTP_CHECK_ERROR (smtp, MU_ERR_BADREPLY);
}
memcpy (smtp->replcode, smtp->rdbuf, 3);
smtp->replcode[3] = 0;
if (smtp->rdbuf[3] == '-')
{
smtp->flags |= _MU_SMTP_MLREPL;
n -= 3;
if (smtp->flsize < n)
{
char *p = realloc (smtp->flbuf, n);
if (!p)
MU_SMTP_CHECK_ERROR (smtp, ENOMEM);
smtp->flbuf = p;
smtp->flsize = n;
}
memcpy (smtp->flbuf, smtp->rdbuf + 4, n - 3);
smtp->replptr = smtp->flbuf;
rc = _mu_smtp_init_mlist (smtp);
MU_SMTP_CHECK_ERROR (smtp, rc);
do
{
rc = mu_stream_getline (smtp->carrier, &smtp->rdbuf, &smtp->rdsize,
&n);
MU_SMTP_CHECK_ERROR (smtp, rc);
if (n == 0)
MU_SMTP_CHECK_ERROR (smtp, EIO);
n = mu_rtrim_cset (smtp->rdbuf, "\r\n");
if (n < 3 || memcmp (smtp->rdbuf, smtp->replcode, 3))
{
mu_diag_output (MU_DIAG_NOTICE,
"received invalid reply from SMTP server");
MU_SMTP_CHECK_ERROR (smtp, MU_ERR_BADREPLY);
}
mu_list_append (smtp->mlrepl, strdup (smtp->rdbuf + 4));
}
while (smtp->rdbuf[3] == '-');
}
else
{
smtp->flags &= ~_MU_SMTP_MLREPL;
smtp->replptr = smtp->rdbuf + 4;
}
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <mailutils/errno.h>
#include <mailutils/cctype.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/sys/smtp.h>
int
mu_smtp_open (mu_smtp_t smtp)
{
int status;
if (!smtp)
return EINVAL;
if (smtp->state != MU_SMTP_INIT)
return MU_ERR_SEQ;
status = mu_smtp_response (smtp);
MU_SMTP_CHECK_ERROR (smtp, status);
if (smtp->replcode[0] == '5')
MU_SMTP_CHECK_ERROR (smtp, MU_ERR_FAILURE);
else if (smtp->replcode[0] == '4')
MU_SMTP_CHECK_ERROR (smtp, EAGAIN);
else if (smtp->replcode[0] != '2')
MU_SMTP_CHECK_ERROR (smtp, MU_ERR_FAILURE);
smtp->state = MU_SMTP_EHLO;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <mailutils/errno.h>
#include <mailutils/list.h>
#include <mailutils/smtp.h>
#include <mailutils/stream.h>
#include <mailutils/sys/smtp.h>
#include <mailutils/tls.h>
static int
smtp_swap_streams (mu_smtp_t smtp, mu_stream_t *streams)
{
int rc;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE))
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, streams);
else if (streams[0] != streams[1])
rc = EINVAL;
else
{
mu_stream_t str = streams[0];
streams[0] = streams[1] = smtp->carrier;
smtp->carrier = str;
rc = 0;
}
return rc;
}
int
mu_smtp_starttls (mu_smtp_t smtp)
{
#ifdef WITH_TLS
int status;
mu_stream_t tlsstream, streams[2];
if (!smtp)
return EINVAL;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
return MU_ERR_FAILURE;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_TLS))
return MU_ERR_SEQ;
if (smtp->state != MU_SMTP_MAIL)
return MU_ERR_SEQ;
status = mu_smtp_write (smtp, "STARTTLS\r\n");
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_smtp_response (smtp);
MU_SMTP_CHECK_ERROR (smtp, status);
if (smtp->replcode[0] == '4')
return EAGAIN;
else if (smtp->replcode[0] != '2')
return MU_ERR_FAILURE;
mu_stream_flush (smtp->carrier);
streams[0] = streams[1] = NULL;
status = smtp_swap_streams (smtp, streams);
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_tls_client_stream_create (&tlsstream,
streams[0], streams[1], 0);
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_stream_open (tlsstream);
if (status)
{
mu_stream_destroy (&tlsstream);
return status;
}
streams[0] = streams[1] = tlsstream;
status = smtp_swap_streams (smtp, streams);
MU_SMTP_CHECK_ERROR (smtp, status);
/* Invalidate the capability list */
mu_list_destroy (&smtp->capa);
return 0;
#else
return ENOTSUP;
#endif
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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, 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <mailutils/sys/smtp.h>
static const char *smtp_prefix[] = {
"S: ", "C: "
};
int
_mu_smtp_trace_enable (mu_smtp_t smtp)
{
int rc = 0;
mu_debug_t debug;
mu_stream_t dstr, xstr;
if (!smtp->carrier)
{
MU_SMTP_FSET (smtp, _MU_SMTP_TRACE);
return 0;
}
mu_diag_get_debug (&debug);
rc = mu_dbgstream_create (&dstr, debug, MU_DIAG_DEBUG, 0);
if (rc)
mu_error (_("cannot create debug stream; transcript disabled: %s"),
mu_strerror (rc));
else
{
rc = mu_xscript_stream_create (&xstr, smtp->carrier, dstr,
smtp_prefix);
if (rc)
mu_error (_("cannot create transcript stream: %s"),
mu_strerror (rc));
else
{
mu_stream_unref (smtp->carrier);
smtp->carrier = xstr;
MU_SMTP_FSET (smtp, _MU_SMTP_TRACE);
}
}
return rc;
}
int
_mu_smtp_trace_disable (mu_smtp_t smtp)
{
mu_stream_t xstr = smtp->carrier;
mu_stream_t stream[2];
int rc;
if (!xstr)
return 0;
rc = mu_stream_ioctl (xstr, MU_IOCTL_GET_TRANSPORT, stream);
if (rc)
return rc;
smtp->carrier = stream[0];
mu_stream_destroy (&xstr);
MU_SMTP_FCLR (smtp, _MU_SMTP_TRACE);
return 0;
}
int
mu_smtp_trace (mu_smtp_t smtp, int op)
{
int trace_on = MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE);
switch (op)
{
case MU_SMTP_TRACE_SET:
if (trace_on)
return MU_ERR_EXISTS;
return _mu_smtp_trace_enable (smtp);
case MU_SMTP_TRACE_CLR:
if (!trace_on)
return MU_ERR_NOENT;
return _mu_smtp_trace_disable (smtp);
case MU_SMTP_TRACE_QRY:
if (!trace_on)
return MU_ERR_NOENT;
return 0;
}
return EINVAL;
}
int
mu_smtp_trace_mask (mu_smtp_t smtp, int op, int lev)
{
switch (op)
{
case MU_SMTP_TRACE_SET:
smtp->flags |= MU_SMTP_XSCRIPT_MASK (lev);
break;
case MU_SMTP_TRACE_CLR:
smtp->flags &= ~MU_SMTP_XSCRIPT_MASK (lev);
break;
case MU_SMTP_TRACE_QRY:
if (smtp->flags & MU_SMTP_XSCRIPT_MASK (lev))
break;
return MU_ERR_NOENT;
default:
return EINVAL;
}
return 0;
}
int
_mu_smtp_xscript_level (mu_smtp_t smtp, int xlev)
{
if (mu_stream_ioctl (smtp->carrier, MU_IOCTL_LEVEL, &xlev) == 0)
return xlev;
return MU_XSCRIPT_NORMAL;
}
......@@ -41,7 +41,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
INCLUDES = @MU_LIB_COMMON_INCLUDES@
noinst_PROGRAMS = \
mbdel\
mimetest
mimetest\
smtpsend
LDADD = \
${MU_LIB_MBOX}\
......@@ -55,6 +56,11 @@ LDADD = \
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS}
smtpsend_LDADD = \
${MU_LIB_MAILER} \
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS}
## ------------ ##
## Test suite. ##
## ------------ ##
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010 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 this program. 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 <mailutils/mailutils.h>
#include <mailutils/smtp.h>
int
main (int argc, char **argv)
{
int i;
char *host;
int port = 25;
int trace = 0;
int tls = 0;
mu_stream_t stream;
mu_smtp_t smtp;
mu_set_program_name (argv[0]);
#ifdef WITH_TLS
mu_init_tls_libs ();
#endif
if (argc < 2)
{
fprintf (stderr, "usage: %s hostname [port=N] [trace=N] [tls=N]\n", argv[0]);
return 1;
}
for (i = 1; i < argc; i++)
{
if (strncmp (argv[i], "port=", 5) == 0)
{
port = atoi (argv[i] + 5);
if (port == 0)
{
mu_error ("invalid port");
return 1;
}
}
else if (strncmp (argv[i], "trace=", 6) == 0)
trace = atoi (argv[i] + 6);
else if (strncmp (argv[i], "tls=", 4) == 0)
tls = atoi (argv[i] + 4);
else
host = argv[i];
}
if (!host)
{
fprintf (stderr, "usage: %s hostname [port=N] [trace=N]\n", argv[0]);
return 1;
}
MU_ASSERT (mu_smtp_create (&smtp));
host = argv[1];
MU_ASSERT (mu_tcp_stream_create (&stream, host, port, MU_STREAM_RDWR));
MU_ASSERT (mu_stream_open (stream));
mu_smtp_set_carrier (smtp, stream);
//mu_stream_unref (stream);
if (trace)
mu_smtp_trace (smtp, MU_SMTP_TRACE_SET);
MU_ASSERT (mu_smtp_open (smtp));
MU_ASSERT (mu_smtp_ehlo (smtp));
if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0)
{
MU_ASSERT (mu_smtp_starttls (smtp));
MU_ASSERT (mu_smtp_ehlo (smtp));
}
mu_smtp_destroy (&smtp);
return 0;
}