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 = \ ...@@ -90,6 +90,7 @@ pkginclude_HEADERS = \
90 secret.h\ 90 secret.h\
91 server.h\ 91 server.h\
92 sieve.h\ 92 sieve.h\
93 smtp.h\
93 stream.h\ 94 stream.h\
94 syslog.h\ 95 syslog.h\
95 sql.h\ 96 sql.h\
......
...@@ -28,6 +28,7 @@ extern "C" { ...@@ -28,6 +28,7 @@ extern "C" {
28 28
29 extern int mu_list_create (mu_list_t *); 29 extern int mu_list_create (mu_list_t *);
30 extern void mu_list_destroy (mu_list_t *); 30 extern void mu_list_destroy (mu_list_t *);
31 extern void mu_list_clear (mu_list_t list);
31 extern int mu_list_append (mu_list_t, void *item); 32 extern int mu_list_append (mu_list_t, void *item);
32 extern int mu_list_prepend (mu_list_t, void *item); 33 extern int mu_list_prepend (mu_list_t, void *item);
33 extern int mu_list_insert (mu_list_t list, void *item, void *new_item, 34 extern int mu_list_insert (mu_list_t list, void *item, void *new_item,
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifndef _MAILUTILS_SMTP_H
18 # define _MAILUTILS_SMTP_H
19
20 # include <sys/types.h>
21 # include <sys/socket.h>
22 # include <mailutils/types.h>
23
24 typedef struct _mu_smtp *mu_smtp_t;
25
26 int mu_smtp_create (mu_smtp_t *);
27 void mu_smtp_destroy (mu_smtp_t *);
28 int mu_smtp_set_carrier (mu_smtp_t smtp, mu_stream_t str);
29 int mu_smtp_get_carrier (mu_smtp_t smtp, mu_stream_t *pcarrier);
30
31 int mu_smtp_open (mu_smtp_t);
32 int mu_smtp_response (mu_smtp_t smtp);
33 int mu_smtp_write (mu_smtp_t smtp, const char *fmt, ...);
34
35 #define MU_SMTP_TRACE_CLR 0
36 #define MU_SMTP_TRACE_SET 1
37 #define MU_SMTP_TRACE_QRY 2
38 int mu_smtp_trace (mu_smtp_t smtp, int op);
39 int mu_smtp_trace_mask (mu_smtp_t smtp, int op, int lev);
40
41 int mu_smtp_disconnect (mu_smtp_t smtp);
42 int mu_smtp_ehlo (mu_smtp_t smtp);
43 int mu_smtp_set_domain (mu_smtp_t smtp, const char *newdom);
44 int mu_smtp_get_domain (mu_smtp_t smtp, const char **pdom);
45 int mu_smtp_capa_test (mu_smtp_t smtp, const char *capa, const char **pret);
46 int mu_smtp_starttls (mu_smtp_t smtp);
47
48 #endif
...@@ -51,6 +51,7 @@ sysinclude_HEADERS = \ ...@@ -51,6 +51,7 @@ sysinclude_HEADERS = \
51 property.h\ 51 property.h\
52 rdcache_stream.h\ 52 rdcache_stream.h\
53 registrar.h\ 53 registrar.h\
54 smtp.h\
54 streamref.h\ 55 streamref.h\
55 streamtrans.h\ 56 streamtrans.h\
56 stream.h\ 57 stream.h\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifndef _MAILUTILS_SYS_SMTP_H
18 # define _MAILUTILS_SYS_SMTP_H
19
20 # include <sys/types.h>
21 # include <sys/socket.h>
22 # include <mailutils/types.h>
23 # include <mailutils/smtp.h>
24
25 # define _MU_SMTP_ESMTP 0x01 /* Connection supports ESMTP */
26 # define _MU_SMTP_TRACE 0x02 /* Session trace required/enabled */
27 # define _MU_SMTP_ERR 0x04 /* Object in error state */
28 # define _MU_SMTP_MLREPL 0x08 /* Last reply was multi-line */
29 # define _MU_SMTP_TLS 0x10 /* TLS initiated */
30 # define _MU_SMTP_AUTH 0x20 /* Authorization passed */
31
32 #define MU_SMTP_XSCRIPT_MASK(n) (0x100<<(n))
33
34 enum mu_smtp_state
35 {
36 MU_SMTP_INIT,
37 MU_SMTP_EHLO,
38 MU_SMTP_MAIL,
39 };
40
41 struct _mu_smtp
42 {
43 int flags;
44 char *domain;
45 mu_stream_t carrier;
46 enum mu_smtp_state state;
47 mu_list_t capa;
48
49 char replcode[4];
50 char *replptr;
51
52 char *rdbuf;
53 size_t rdsize;
54
55 char *flbuf;
56 size_t flsize;
57
58 mu_list_t mlrepl;
59 };
60
61 #define MU_SMTP_FSET(p,f) ((p)->flags |= (f))
62 #define MU_SMTP_FISSET(p,f) ((p)->flags & (f))
63 #define MU_SMTP_FCLR(p,f) ((p)->flags &= ~(f))
64
65 #define MU_SMTP_CHECK_ERROR(smtp, status) \
66 do \
67 { \
68 if (status != 0) \
69 { \
70 smtp->flags |= _MU_SMTP_ERR; \
71 return status; \
72 } \
73 } \
74 while (0)
75
76 int _mu_smtp_trace_enable (mu_smtp_t smtp);
77 int _mu_smtp_trace_disable (mu_smtp_t smtp);
78
79
80 #endif
...@@ -60,6 +60,9 @@ MU_ERR_BAD_2047_ENCODING _("Not a valid RFC 2047 encoding") ...@@ -60,6 +60,9 @@ MU_ERR_BAD_2047_ENCODING _("Not a valid RFC 2047 encoding")
60 60
61 MU_ERR_NOUSERNAME _("User name is not supplied") 61 MU_ERR_NOUSERNAME _("User name is not supplied")
62 MU_ERR_NOPASSWORD _("User password is not supplied") 62 MU_ERR_NOPASSWORD _("User password is not supplied")
63 MU_ERR_BADREPLY _("Invalid reply from the remote host")
64
65 MU_ERR_SEQ _("Bad command sequence")
63 66
64 MU_ERR_UNSAFE_PERMS _("Unsafe file permissions. Set 0600") 67 MU_ERR_UNSAFE_PERMS _("Unsafe file permissions. Set 0600")
65 MU_ERR_BAD_AUTH_SCHEME _("Unsupported authentication scheme") 68 MU_ERR_BAD_AUTH_SCHEME _("Unsupported authentication scheme")
......
...@@ -61,23 +61,30 @@ mu_list_create (mu_list_t *plist) ...@@ -61,23 +61,30 @@ mu_list_create (mu_list_t *plist)
61 } 61 }
62 62
63 void 63 void
64 mu_list_clear (mu_list_t list)
65 {
66 struct list_data *current;
67 struct list_data *previous;
68
69 mu_monitor_wrlock (list->monitor);
70 for (current = list->head.next; current != &list->head;)
71 {
72 previous = current;
73 current = current->next;
74 DESTROY_ITEM (list, previous);
75 free (previous);
76 }
77 list->head.next = list->head.prev = &list->head;
78 mu_monitor_unlock (list->monitor);
79 }
80
81 void
64 mu_list_destroy (mu_list_t *plist) 82 mu_list_destroy (mu_list_t *plist)
65 { 83 {
66 if (plist && *plist) 84 if (plist && *plist)
67 { 85 {
68 mu_list_t list = *plist; 86 mu_list_t list = *plist;
69 struct list_data *current; 87 mu_list_clear (list);
70 struct list_data *previous;
71
72 mu_monitor_wrlock (list->monitor);
73 for (current = list->head.next; current != &list->head;)
74 {
75 previous = current;
76 current = current->next;
77 DESTROY_ITEM (list, previous);
78 free (previous);
79 }
80 mu_monitor_unlock (list->monitor);
81 mu_monitor_destroy (&list->monitor, list); 88 mu_monitor_destroy (&list->monitor, list);
82 free (list); 89 free (list);
83 *plist = NULL; 90 *plist = NULL;
......
...@@ -28,5 +28,15 @@ libmu_mailer_la_SOURCES = \ ...@@ -28,5 +28,15 @@ libmu_mailer_la_SOURCES = \
28 prog.c\ 28 prog.c\
29 sendmail.c\ 29 sendmail.c\
30 smtp.c\ 30 smtp.c\
31 smtp_capa.c\
32 smtp_carrier.c\
33 smtp_create.c\
34 smtp_disconnect.c\
35 smtp_domain.c\
36 smtp_ehlo.c\
37 smtp_io.c\
38 smtp_open.c\
39 smtp_starttls.c\
40 smtp_trace.c\
31 remote.c 41 remote.c
32 42
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <mailutils/errno.h>
24 #include <mailutils/list.h>
25 #include <mailutils/smtp.h>
26 #include <mailutils/sys/smtp.h>
27
28 int
29 mu_smtp_capa_test (mu_smtp_t smtp, const char *name, const char **pret)
30 {
31 if (!smtp || !name)
32 return EINVAL;
33 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
34 return MU_ERR_FAILURE;
35 if (!smtp->capa)
36 {
37 int rc = mu_smtp_ehlo (smtp);
38 if (rc)
39 return rc;
40 }
41 if (!MU_SMTP_FISSET (smtp, _MU_SMTP_ESMTP))
42 return MU_ERR_FAILURE;
43 return mu_list_locate (smtp->capa, (void*) name, (void**)pret);
44 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <mailutils/list.h>
23 #include <mailutils/smtp.h>
24 #include <mailutils/stream.h>
25 #include <mailutils/sys/smtp.h>
26
27 int
28 mu_smtp_set_carrier (mu_smtp_t smtp, mu_stream_t carrier)
29 {
30 /* Sanity checks. */
31 if (smtp == NULL)
32 return EINVAL;
33
34 if (smtp->carrier)
35 {
36 /* Close any old carrier. */
37 mu_smtp_disconnect (smtp);
38 mu_stream_destroy (&smtp->carrier);
39 }
40 mu_stream_ref (carrier);
41 smtp->carrier = carrier;
42 if (MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE))
43 _mu_smtp_trace_enable (smtp);
44 return 0;
45 }
46
47 int
48 mu_smtp_get_carrier (mu_smtp_t smtp, mu_stream_t *pcarrier)
49 {
50 /*FIXME*/
51 return ENOSYS;
52 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <mailutils/list.h>
23 #include <mailutils/smtp.h>
24 #include <mailutils/stream.h>
25 #include <mailutils/sys/smtp.h>
26
27 int
28 mu_smtp_create (mu_smtp_t *psmtp)
29 {
30 struct _mu_smtp *smtp;
31
32 if (!psmtp)
33 return EINVAL;
34
35 smtp = calloc (1, sizeof (*smtp));
36
37 if (!smtp)
38 return ENOMEM;
39
40 smtp->state = MU_SMTP_INIT;
41 *psmtp = smtp;
42 return 0;
43 }
44
45 void
46 mu_smtp_destroy (mu_smtp_t *psmtp)
47 {
48 struct _mu_smtp *smtp;
49
50 if (!psmtp || !*psmtp)
51 return;
52 smtp = *psmtp;
53 mu_stream_destroy (&smtp->carrier);
54 mu_list_destroy (&smtp->capa);
55 free (smtp->rdbuf);
56 free (smtp->flbuf);
57 mu_list_destroy (&smtp->mlrepl);
58 free (smtp);
59 *psmtp = NULL;
60 }
61
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <mailutils/stream.h>
25 #include <mailutils/sys/smtp.h>
26
27 int
28 mu_smtp_disconnect (mu_smtp_t smtp)
29 {
30 if (smtp == NULL)
31 return EINVAL;
32
33 smtp->state = MU_SMTP_INIT;
34
35 if (smtp->rdbuf)
36 smtp->rdbuf[0] = 0;
37
38 return mu_stream_close (smtp->carrier);
39 }
1
2 /* GNU Mailutils -- a suite of utilities for electronic mail
3 Copyright (C) 2010 Free Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <mailutils/errno.h>
26 #include <mailutils/cctype.h>
27 #include <mailutils/list.h>
28 #include <mailutils/smtp.h>
29 #include <mailutils/sys/smtp.h>
30
31 int
32 mu_smtp_set_domain (mu_smtp_t smtp, const char *newdom)
33 {
34 char *dom;
35
36 if (!smtp)
37 return EINVAL;
38
39 dom = strdup (newdom);
40 if (!dom)
41 return ENOMEM;
42 free (smtp->domain);
43 smtp->domain = dom;
44 return 0;
45 }
46
47 int
48 mu_smtp_get_domain (mu_smtp_t smtp, const char **pdom)
49 {
50 if (!smtp)
51 return EINVAL;
52 *pdom = smtp->domain;
53 return 0;
54 }
55
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <mailutils/errno.h>
25 #include <mailutils/cctype.h>
26 #include <mailutils/list.h>
27 #include <mailutils/mutil.h>
28 #include <mailutils/smtp.h>
29 #include <mailutils/sys/smtp.h>
30
31 static int
32 capa_comp (const void *item, const void *value)
33 {
34 const char *capa = item;
35 const char *needle = value;
36 for (; *needle; capa++, needle++)
37 {
38 if (!*capa)
39 return 1;
40 if (mu_tolower (*capa) != mu_tolower (*needle))
41 return 1;
42 }
43 return !(*capa == 0 || mu_isspace (*capa));
44 }
45
46 int
47 mu_smtp_ehlo (mu_smtp_t smtp)
48 {
49 int status;
50
51 if (!smtp)
52 return EINVAL;
53 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
54 return MU_ERR_FAILURE;
55
56 if (!smtp->domain)
57 {
58 char *host;
59 char *p;
60
61 status = mu_get_host_name (&host);
62 MU_SMTP_CHECK_ERROR (smtp, status);
63 p = strchr (host, '.');
64 if (p)
65 p++;
66 else
67 p = host;
68 status = mu_smtp_set_domain (smtp, p);
69 MU_SMTP_CHECK_ERROR (smtp, status);
70 }
71
72 status = mu_smtp_write (smtp, "EHLO %s\r\n", smtp->domain);
73 MU_SMTP_CHECK_ERROR (smtp, status);
74 status = mu_smtp_response (smtp);
75 MU_SMTP_CHECK_ERROR (smtp, status);
76 if (smtp->replcode[0] == '2')
77 {
78 smtp->flags |= _MU_SMTP_ESMTP;
79 smtp->capa = smtp->mlrepl;
80 smtp->mlrepl = NULL;
81 mu_list_set_comparator (smtp->capa, capa_comp);
82 }
83 else if (smtp->replcode[0] == '4')
84 return EAGAIN;
85 else
86 {
87 status = mu_smtp_write (smtp, "HELO %s\r\n", smtp->domain);
88 MU_SMTP_CHECK_ERROR (smtp, status);
89 status = mu_smtp_response (smtp);
90 MU_SMTP_CHECK_ERROR (smtp, status);
91 smtp->flags &= ~_MU_SMTP_ESMTP;
92 if (smtp->replcode[0] == '4')
93 return EAGAIN;
94 else if (smtp->replcode[0] != '2')
95 return MU_ERR_FAILURE;
96 }
97 smtp->state = MU_SMTP_MAIL;
98 return 0;
99 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <mailutils/cstr.h>
26 #include <mailutils/cctype.h>
27 #include <mailutils/diag.h>
28 #include <mailutils/errno.h>
29 #include <mailutils/list.h>
30 #include <mailutils/smtp.h>
31 #include <mailutils/stream.h>
32 #include <mailutils/sys/smtp.h>
33
34 int
35 mu_smtp_write (mu_smtp_t smtp, const char *fmt, ...)
36 {
37 va_list ap;
38 int rc;
39
40 va_start (ap, fmt);
41 rc = mu_stream_vprintf (smtp->carrier, fmt, ap);
42 va_end (ap);
43 return rc;
44 }
45
46 static int
47 _mu_smtp_init_mlist (mu_smtp_t smtp)
48 {
49 if (!smtp->mlrepl)
50 {
51 int rc = mu_list_create (&smtp->mlrepl);
52 if (rc == 0)
53 mu_list_set_destroy_item (smtp->mlrepl, mu_list_free_item);
54 return rc;
55 }
56 else
57 mu_list_clear (smtp->mlrepl);
58 return 0;
59 }
60
61 int
62 mu_smtp_response (mu_smtp_t smtp)
63 {
64 int rc;
65 size_t n;
66
67 rc = mu_stream_getline (smtp->carrier, &smtp->rdbuf, &smtp->rdsize, &n);
68 MU_SMTP_CHECK_ERROR (smtp, rc);
69 if (n == 0)
70 MU_SMTP_CHECK_ERROR (smtp, EIO);
71 n = mu_rtrim_cset (smtp->rdbuf, "\r\n");
72 if (n < 3 || !mu_isdigit (smtp->rdbuf[0]))
73 {
74 mu_diag_output (MU_DIAG_NOTICE,
75 "received invalid reply from SMTP server");
76 MU_SMTP_CHECK_ERROR (smtp, MU_ERR_BADREPLY);
77 }
78 memcpy (smtp->replcode, smtp->rdbuf, 3);
79 smtp->replcode[3] = 0;
80 if (smtp->rdbuf[3] == '-')
81 {
82 smtp->flags |= _MU_SMTP_MLREPL;
83 n -= 3;
84 if (smtp->flsize < n)
85 {
86 char *p = realloc (smtp->flbuf, n);
87 if (!p)
88 MU_SMTP_CHECK_ERROR (smtp, ENOMEM);
89 smtp->flbuf = p;
90 smtp->flsize = n;
91 }
92 memcpy (smtp->flbuf, smtp->rdbuf + 4, n - 3);
93 smtp->replptr = smtp->flbuf;
94
95 rc = _mu_smtp_init_mlist (smtp);
96 MU_SMTP_CHECK_ERROR (smtp, rc);
97 do
98 {
99 rc = mu_stream_getline (smtp->carrier, &smtp->rdbuf, &smtp->rdsize,
100 &n);
101 MU_SMTP_CHECK_ERROR (smtp, rc);
102 if (n == 0)
103 MU_SMTP_CHECK_ERROR (smtp, EIO);
104 n = mu_rtrim_cset (smtp->rdbuf, "\r\n");
105 if (n < 3 || memcmp (smtp->rdbuf, smtp->replcode, 3))
106 {
107 mu_diag_output (MU_DIAG_NOTICE,
108 "received invalid reply from SMTP server");
109 MU_SMTP_CHECK_ERROR (smtp, MU_ERR_BADREPLY);
110 }
111 mu_list_append (smtp->mlrepl, strdup (smtp->rdbuf + 4));
112 }
113 while (smtp->rdbuf[3] == '-');
114 }
115 else
116 {
117 smtp->flags &= ~_MU_SMTP_MLREPL;
118 smtp->replptr = smtp->rdbuf + 4;
119 }
120 return 0;
121 }
122
123
124
125
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <mailutils/errno.h>
24 #include <mailutils/cctype.h>
25 #include <mailutils/list.h>
26 #include <mailutils/smtp.h>
27 #include <mailutils/sys/smtp.h>
28
29 int
30 mu_smtp_open (mu_smtp_t smtp)
31 {
32 int status;
33
34 if (!smtp)
35 return EINVAL;
36 if (smtp->state != MU_SMTP_INIT)
37 return MU_ERR_SEQ;
38 status = mu_smtp_response (smtp);
39 MU_SMTP_CHECK_ERROR (smtp, status);
40 if (smtp->replcode[0] == '5')
41 MU_SMTP_CHECK_ERROR (smtp, MU_ERR_FAILURE);
42 else if (smtp->replcode[0] == '4')
43 MU_SMTP_CHECK_ERROR (smtp, EAGAIN);
44 else if (smtp->replcode[0] != '2')
45 MU_SMTP_CHECK_ERROR (smtp, MU_ERR_FAILURE);
46 smtp->state = MU_SMTP_EHLO;
47 return 0;
48 }
49
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <mailutils/errno.h>
24 #include <mailutils/list.h>
25 #include <mailutils/smtp.h>
26 #include <mailutils/stream.h>
27 #include <mailutils/sys/smtp.h>
28 #include <mailutils/tls.h>
29
30 static int
31 smtp_swap_streams (mu_smtp_t smtp, mu_stream_t *streams)
32 {
33 int rc;
34
35 if (MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE))
36 rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, streams);
37 else if (streams[0] != streams[1])
38 rc = EINVAL;
39 else
40 {
41 mu_stream_t str = streams[0];
42 streams[0] = streams[1] = smtp->carrier;
43 smtp->carrier = str;
44 rc = 0;
45 }
46 return rc;
47 }
48
49 int
50 mu_smtp_starttls (mu_smtp_t smtp)
51 {
52 #ifdef WITH_TLS
53 int status;
54 mu_stream_t tlsstream, streams[2];
55
56 if (!smtp)
57 return EINVAL;
58 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
59 return MU_ERR_FAILURE;
60 if (MU_SMTP_FISSET (smtp, _MU_SMTP_TLS))
61 return MU_ERR_SEQ;
62 if (smtp->state != MU_SMTP_MAIL)
63 return MU_ERR_SEQ;
64
65 status = mu_smtp_write (smtp, "STARTTLS\r\n");
66 MU_SMTP_CHECK_ERROR (smtp, status);
67 status = mu_smtp_response (smtp);
68 MU_SMTP_CHECK_ERROR (smtp, status);
69 if (smtp->replcode[0] == '4')
70 return EAGAIN;
71 else if (smtp->replcode[0] != '2')
72 return MU_ERR_FAILURE;
73
74 mu_stream_flush (smtp->carrier);
75 streams[0] = streams[1] = NULL;
76 status = smtp_swap_streams (smtp, streams);
77 MU_SMTP_CHECK_ERROR (smtp, status);
78
79 status = mu_tls_client_stream_create (&tlsstream,
80 streams[0], streams[1], 0);
81 MU_SMTP_CHECK_ERROR (smtp, status);
82 status = mu_stream_open (tlsstream);
83 if (status)
84 {
85 mu_stream_destroy (&tlsstream);
86 return status;
87 }
88 streams[0] = streams[1] = tlsstream;
89 status = smtp_swap_streams (smtp, streams);
90 MU_SMTP_CHECK_ERROR (smtp, status);
91 /* Invalidate the capability list */
92 mu_list_destroy (&smtp->capa);
93 return 0;
94 #else
95 return ENOTSUP;
96 #endif
97 }
98
99
100
101
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <string.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <mailutils/errno.h>
25 #include <mailutils/error.h>
26 #include <mailutils/nls.h>
27 #include <mailutils/stream.h>
28 #include <mailutils/sys/smtp.h>
29
30 static const char *smtp_prefix[] = {
31 "S: ", "C: "
32 };
33
34 int
35 _mu_smtp_trace_enable (mu_smtp_t smtp)
36 {
37 int rc = 0;
38 mu_debug_t debug;
39 mu_stream_t dstr, xstr;
40
41 if (!smtp->carrier)
42 {
43 MU_SMTP_FSET (smtp, _MU_SMTP_TRACE);
44 return 0;
45 }
46
47 mu_diag_get_debug (&debug);
48
49 rc = mu_dbgstream_create (&dstr, debug, MU_DIAG_DEBUG, 0);
50 if (rc)
51 mu_error (_("cannot create debug stream; transcript disabled: %s"),
52 mu_strerror (rc));
53 else
54 {
55 rc = mu_xscript_stream_create (&xstr, smtp->carrier, dstr,
56 smtp_prefix);
57 if (rc)
58 mu_error (_("cannot create transcript stream: %s"),
59 mu_strerror (rc));
60 else
61 {
62 mu_stream_unref (smtp->carrier);
63 smtp->carrier = xstr;
64 MU_SMTP_FSET (smtp, _MU_SMTP_TRACE);
65 }
66 }
67
68 return rc;
69 }
70
71 int
72 _mu_smtp_trace_disable (mu_smtp_t smtp)
73 {
74 mu_stream_t xstr = smtp->carrier;
75 mu_stream_t stream[2];
76 int rc;
77
78 if (!xstr)
79 return 0;
80
81 rc = mu_stream_ioctl (xstr, MU_IOCTL_GET_TRANSPORT, stream);
82 if (rc)
83 return rc;
84
85 smtp->carrier = stream[0];
86 mu_stream_destroy (&xstr);
87 MU_SMTP_FCLR (smtp, _MU_SMTP_TRACE);
88 return 0;
89 }
90
91 int
92 mu_smtp_trace (mu_smtp_t smtp, int op)
93 {
94 int trace_on = MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE);
95
96 switch (op)
97 {
98 case MU_SMTP_TRACE_SET:
99 if (trace_on)
100 return MU_ERR_EXISTS;
101 return _mu_smtp_trace_enable (smtp);
102
103 case MU_SMTP_TRACE_CLR:
104 if (!trace_on)
105 return MU_ERR_NOENT;
106 return _mu_smtp_trace_disable (smtp);
107
108 case MU_SMTP_TRACE_QRY:
109 if (!trace_on)
110 return MU_ERR_NOENT;
111 return 0;
112 }
113 return EINVAL;
114 }
115
116 int
117 mu_smtp_trace_mask (mu_smtp_t smtp, int op, int lev)
118 {
119 switch (op)
120 {
121 case MU_SMTP_TRACE_SET:
122 smtp->flags |= MU_SMTP_XSCRIPT_MASK (lev);
123 break;
124
125 case MU_SMTP_TRACE_CLR:
126 smtp->flags &= ~MU_SMTP_XSCRIPT_MASK (lev);
127 break;
128
129 case MU_SMTP_TRACE_QRY:
130 if (smtp->flags & MU_SMTP_XSCRIPT_MASK (lev))
131 break;
132 return MU_ERR_NOENT;
133
134 default:
135 return EINVAL;
136 }
137 return 0;
138 }
139
140 int
141 _mu_smtp_xscript_level (mu_smtp_t smtp, int xlev)
142 {
143 if (mu_stream_ioctl (smtp->carrier, MU_IOCTL_LEVEL, &xlev) == 0)
144 return xlev;
145 return MU_XSCRIPT_NORMAL;
146 }
...@@ -41,7 +41,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac ...@@ -41,7 +41,8 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
41 INCLUDES = @MU_LIB_COMMON_INCLUDES@ 41 INCLUDES = @MU_LIB_COMMON_INCLUDES@
42 noinst_PROGRAMS = \ 42 noinst_PROGRAMS = \
43 mbdel\ 43 mbdel\
44 mimetest 44 mimetest\
45 smtpsend
45 46
46 LDADD = \ 47 LDADD = \
47 ${MU_LIB_MBOX}\ 48 ${MU_LIB_MBOX}\
...@@ -55,6 +56,11 @@ LDADD = \ ...@@ -55,6 +56,11 @@ LDADD = \
55 @MU_AUTHLIBS@\ 56 @MU_AUTHLIBS@\
56 ${MU_LIB_MAILUTILS} 57 ${MU_LIB_MAILUTILS}
57 58
59 smtpsend_LDADD = \
60 ${MU_LIB_MAILER} \
61 @MU_AUTHLIBS@\
62 ${MU_LIB_MAILUTILS}
63
58 ## ------------ ## 64 ## ------------ ##
59 ## Test suite. ## 65 ## Test suite. ##
60 ## ------------ ## 66 ## ------------ ##
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <mailutils/mailutils.h>
24 #include <mailutils/smtp.h>
25
26 int
27 main (int argc, char **argv)
28 {
29 int i;
30 char *host;
31 int port = 25;
32 int trace = 0;
33 int tls = 0;
34 mu_stream_t stream;
35 mu_smtp_t smtp;
36
37 mu_set_program_name (argv[0]);
38 #ifdef WITH_TLS
39 mu_init_tls_libs ();
40 #endif
41
42 if (argc < 2)
43 {
44 fprintf (stderr, "usage: %s hostname [port=N] [trace=N] [tls=N]\n", argv[0]);
45 return 1;
46 }
47
48 for (i = 1; i < argc; i++)
49 {
50 if (strncmp (argv[i], "port=", 5) == 0)
51 {
52 port = atoi (argv[i] + 5);
53 if (port == 0)
54 {
55 mu_error ("invalid port");
56 return 1;
57 }
58 }
59 else if (strncmp (argv[i], "trace=", 6) == 0)
60 trace = atoi (argv[i] + 6);
61 else if (strncmp (argv[i], "tls=", 4) == 0)
62 tls = atoi (argv[i] + 4);
63 else
64 host = argv[i];
65 }
66
67 if (!host)
68 {
69 fprintf (stderr, "usage: %s hostname [port=N] [trace=N]\n", argv[0]);
70 return 1;
71 }
72
73
74 MU_ASSERT (mu_smtp_create (&smtp));
75
76 host = argv[1];
77 MU_ASSERT (mu_tcp_stream_create (&stream, host, port, MU_STREAM_RDWR));
78 MU_ASSERT (mu_stream_open (stream));
79 mu_smtp_set_carrier (smtp, stream);
80 //mu_stream_unref (stream);
81
82 if (trace)
83 mu_smtp_trace (smtp, MU_SMTP_TRACE_SET);
84 MU_ASSERT (mu_smtp_open (smtp));
85 MU_ASSERT (mu_smtp_ehlo (smtp));
86
87 if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0)
88 {
89 MU_ASSERT (mu_smtp_starttls (smtp));
90 MU_ASSERT (mu_smtp_ehlo (smtp));
91 }
92
93 mu_smtp_destroy (&smtp);
94 return 0;
95 }