1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010-2021 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/diag.h>
26 #include <mailutils/filter.h>
27 #include <mailutils/list.h>
28 #include <mailutils/smtp.h>
29 #include <mailutils/stream.h>
30 #include <mailutils/sys/stream.h>
31 #include <mailutils/sys/smtp.h>
32
33 int
_mu_smtp_data_begin(mu_smtp_t smtp)34 _mu_smtp_data_begin (mu_smtp_t smtp)
35 {
36 int status;
37
38 status = mu_smtp_write (smtp, "DATA\r\n");
39 MU_SMTP_CHECK_ERROR (smtp, status);
40 status = mu_smtp_response (smtp);
41 MU_SMTP_CHECK_ERROR (smtp, status);
42
43 if (smtp->replcode[0] != '3')
44 return MU_ERR_REPLY;
45
46 if (mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_QRY, MU_XSCRIPT_PAYLOAD))
47 _mu_smtp_xscript_level (smtp, MU_XSCRIPT_PAYLOAD);
48
49 smtp->savebuf.type = MU_TRANSPORT_OUTPUT;
50 if (mu_stream_ioctl (smtp->carrier, MU_IOCTL_TRANSPORT_BUFFER,
51 MU_IOCTL_OP_GET, &smtp->savebuf) == 0)
52 {
53 struct mu_buffer_query newbuf;
54 newbuf.type = MU_TRANSPORT_OUTPUT;
55 newbuf.buftype = mu_buffer_full;
56 newbuf.bufsize = 64*1024;
57 if (mu_stream_ioctl (smtp->carrier, MU_IOCTL_TRANSPORT_BUFFER,
58 MU_IOCTL_OP_SET, &newbuf) == 0)
59 MU_SMTP_FSET (smtp, _MU_SMTP_SAVEBUF);
60 }
61 return 0;
62 }
63
64 int
_mu_smtp_data_end(mu_smtp_t smtp)65 _mu_smtp_data_end (mu_smtp_t smtp)
66 {
67 int status = 0;
68 /* code is always _MU_STR_EVENT_CLOSE */
69 if (MU_SMTP_FISSET (smtp, _MU_SMTP_SAVEBUF))
70 {
71 status = mu_stream_ioctl (smtp->carrier, MU_IOCTL_TRANSPORT_BUFFER,
72 MU_IOCTL_OP_SET, &smtp->savebuf);
73 if (status)
74 mu_diag_output (MU_DIAG_NOTICE,
75 "failed to restore buffer state on SMTP carrier: %s",
76 mu_strerror (status));
77 }
78 _mu_smtp_xscript_level (smtp, MU_XSCRIPT_NORMAL);
79 smtp->state = MU_SMTP_DOT;
80 return status;
81 }
82
83 static void
_smtp_event_cb(struct _mu_stream * str,int code,unsigned long lval,void * pval)84 _smtp_event_cb (struct _mu_stream *str, int code,
85 unsigned long lval, void *pval)
86 {
87 mu_smtp_t smtp = str->event_cb_data;
88 _mu_smtp_data_end (smtp);
89 }
90
91 int
mu_smtp_data(mu_smtp_t smtp,mu_stream_t * pstream)92 mu_smtp_data (mu_smtp_t smtp, mu_stream_t *pstream)
93 {
94 int status;
95 mu_stream_t input;
96
97 if (!smtp)
98 return EINVAL;
99 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
100 return MU_ERR_FAILURE;
101 if (smtp->state != MU_SMTP_MORE)
102 return MU_ERR_SEQ;
103
104 status = _mu_smtp_data_begin (smtp);
105 if (status)
106 return status;
107
108 status = mu_filter_create (&input, smtp->carrier, "CRLFDOT",
109 MU_FILTER_ENCODE, MU_STREAM_WRITE);
110 if (status)
111 return status;
112 input->event_cb = _smtp_event_cb;
113 input->event_cb_data = smtp;
114 input->event_mask = _MU_STR_EVMASK (_MU_STR_EVENT_CLOSE);
115 *pstream = input;
116 return 0;
117 }
118