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