1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the BSD package               *
4 *Copyright (c) 1978-2006 The Regents of the University of California an*
5 *                                                                      *
6 * Redistribution and use in source and binary forms, with or           *
7 * without modification, are permitted provided that the following      *
8 * conditions are met:                                                  *
9 *                                                                      *
10 *    1. Redistributions of source code must retain the above           *
11 *       copyright notice, this list of conditions and the              *
12 *       following disclaimer.                                          *
13 *                                                                      *
14 *    2. Redistributions in binary form must reproduce the above        *
15 *       copyright notice, this list of conditions and the              *
16 *       following disclaimer in the documentation and/or other         *
17 *       materials provided with the distribution.                      *
18 *                                                                      *
19 *    3. Neither the name of The Regents of the University of California*
20 *       names of its contributors may be used to endorse or            *
21 *       promote products derived from this software without            *
22 *       specific prior written permission.                             *
23 *                                                                      *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND               *
25 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,          *
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF             *
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE             *
28 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS    *
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,             *
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED      *
31 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,        *
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    *
33 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,      *
34 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY       *
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE              *
36 * POSSIBILITY OF SUCH DAMAGE.                                          *
37 *                                                                      *
38 * Redistribution and use in source and binary forms, with or without   *
39 * modification, are permitted provided that the following conditions   *
40 * are met:                                                             *
41 * 1. Redistributions of source code must retain the above copyright    *
42 *    notice, this list of conditions and the following disclaimer.     *
43 * 2. Redistributions in binary form must reproduce the above copyright *
44 *    notice, this list of conditions and the following disclaimer in   *
45 *    the documentation and/or other materials provided with the        *
46 *    distribution.                                                     *
47 * 3. Neither the name of the University nor the names of its           *
48 *    contributors may be used to endorse or promote products derived   *
49 *    from this software without specific prior written permission.     *
50 *                                                                      *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS"    *
52 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED    *
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A      *
54 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS    *
55 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,      *
56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF     *
58 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND  *
59 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,   *
60 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT   *
61 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   *
62 * SUCH DAMAGE.                                                         *
63 *                                                                      *
64 *                          Kurt Shoens (UCB)                           *
65 *                                 gsf                                  *
66 *                                                                      *
67 ***********************************************************************/
68 #pragma prototyped
69 /*
70  * IMAP client
71  *
72  * Glenn Fowler
73  * AT&T Research
74  */
75 
76 #include "mailx.h"
77 
78 #if _PACKAGE_ast
79 
80 #include <css.h>
81 #include <tm.h>
82 
83 #define SMTP_READY	220
84 #define SMTP_OK		250
85 #define SMTP_START	354
86 #define SMTP_CLOSE	221
87 
88 /*
89  * send the message in fp to the SMTP server on host
90  * for recipients argv ...
91  * if original!=0 then it is the size of the message
92  * and the original sender is retrived from the
93  * message and preserved
94  */
95 
96 int
sendsmtp(Sfio_t * fp,char * host,char ** argv,off_t original)97 sendsmtp(Sfio_t* fp, char* host, char** argv, off_t original)
98 {
99 	register char*	s;
100 	register char*	t;
101 	char*		e;
102 	int		n;
103 	int		fd;
104 	int		r;
105 	off_t		z;
106 	Sfio_t*		sp;
107 	Sfio_t*		rp;
108 	char		buf[PATH_MAX];
109 	char		svc[PATH_MAX];
110 
111 	/*
112 	 * connect to the service
113 	 */
114 
115 	sfsprintf(svc, sizeof(svc), "/dev/tcp/%s/inet.smtp", host);
116 	if ((fd = csopen(&cs, svc, 0)) < 0)
117 	{
118 		note(SYSTEM, "smtp: %s: cannot connect to service", svc);
119 		return -1;
120 	}
121 	if (!(sp = sfnew(NiL, NiL, SF_UNBOUND, fd, SF_WRITE)) ||
122 	    !(rp = sfnew(NiL, NiL, SF_UNBOUND, fd, SF_READ)))
123 	{
124 		if (sp)
125 			sfclose(sp);
126 		else
127 			close(fd);
128 		note(SYSTEM, "smtp: %s: cannot buffer service", svc);
129 		return -1;
130 	}
131 
132 	/*
133 	 * verify
134 	 */
135 
136 	do
137 	{
138 		if (!(s = sfgetr(rp, '\n', 1)))
139 			goto bad_recv;
140 		if (strtol(s, &e, 10) != SMTP_READY)
141 			goto bad_prot;
142 	} while (*e == '-');
143 
144 	/*
145 	 * identify
146 	 */
147 
148 	if (!(s = state.var.domain) || !*s)
149 		s = state.var.hostname;
150 	if (sfprintf(sp, "HELO %s\r\n", s) < 0)
151 		goto bad_send;
152 	do
153 	{
154 		if (!(s = sfgetr(rp, '\n', 1)))
155 			goto bad_recv;
156 		if (strtol(s, &e, 10) != SMTP_OK)
157 			goto bad_prot;
158 	} while (*(unsigned char*)e == SMTP_OK);
159 
160 	/*
161 	 * from
162 	 */
163 
164 	if (original)
165 	{
166 		if (!(s = sfgetr(fp, '\n', 1)) || !strneq(s, "From ", 5))
167 			goto bad_mesg;
168 		for (s += 5; isspace(*s); s++);
169 		for (t = s; *t && !isspace(*t); t++);
170 		if (!(n = t - s))
171 			goto bad_mesg;
172 		z = sfvalue(fp);
173 		if (sfprintf(sp, "MAIL FROM:<%*.*s>\r\n", n, n, s) < 0)
174 			goto bad_send;
175 	}
176 	else
177 	{
178 		z = 0;
179 		if ((state.var.domain ?
180 		     sfprintf(sp, "MAIL FROM:<%s@%s>\r\n", state.var.user, state.var.domain) :
181 		     sfprintf(sp, "MAIL FROM:<%s>\r\n", state.var.user)) < 0)
182 			goto bad_send;
183 	}
184 	do
185 	{
186 		if (!(s = sfgetr(rp, '\n', 1)))
187 			goto bad_recv;
188 		if (strtol(s, &e, 10) != SMTP_OK)
189 			goto bad_prot;
190 	} while (*e == '-');
191 
192 	/*
193 	 * to
194 	 */
195 
196 	while (s = *argv++)
197 	{
198 		if ((state.var.domain && !strchr(s, '@') ?
199 		     sfprintf(sp, "RCPT TO:<%s@%s>\r\n", s, state.var.domain) :
200 		     sfprintf(sp, "RCPT TO:<%s>\r\n", s)) < 0)
201 			goto bad_send;
202 		do
203 		{
204 			if (!(s = sfgetr(rp, '\n', 1)))
205 				goto bad_recv;
206 			if (strtol(s, &e, 10) != SMTP_OK)
207 				goto bad_prot;
208 		} while (*e == '-');
209 	}
210 
211 	/*
212 	 * body
213 	 */
214 
215 	if (sfprintf(sp, "DATA\r\n") < 0)
216 		goto bad_send;
217 	do
218 	{
219 		if (!(s = sfgetr(rp, '\n', 1)))
220 			goto bad_recv;
221 		if (strtol(s, &e, 10) != SMTP_START)
222 			goto bad_prot;
223 	} while (*e == '-');
224 	tmfmt(buf, sizeof(buf), "%+uDate: %a, %d %b %Y %H:%M:%S UT", NiL);
225 	if (sfputr(sp, buf, '\n') < 0)
226 		goto bad_send;
227 	if (sfprintf(sp, "From: <%s@%s>\n", state.var.user, host) < 0)
228 		goto bad_send;
229 	while (s = sfgetr(fp, '\n', 1))
230 	{
231 		if (sfprintf(sp, "%s%s\r\n", *s == '.' ? "." : "", s) < 0)
232 			goto bad_send;
233 		if (original && (z += sfvalue(fp)) >= original)
234 			break;
235 	}
236 	if (sfprintf(sp, ".\r\n") < 0)
237 		goto bad_send;
238 	do
239 	{
240 		if (!(s = sfgetr(rp, '\n', 1)))
241 			goto bad_recv;
242 		if (strtol(s, &e, 10) != SMTP_OK)
243 			goto bad_prot;
244 	} while (*e == '-');
245 
246 	/*
247 	 * quit
248 	 */
249 
250 	if (sfprintf(sp, "QUIT\r\n") < 0)
251 		goto bad_send;
252 	do
253 	{
254 		if (!(s = sfgetr(rp, '\n', 1)))
255 			goto bad_recv;
256 		if (strtol(s, &e, 10) != SMTP_CLOSE)
257 			goto bad_prot;
258 	} while (*e == '-');
259 	r = 0;
260 	goto done;
261  bad_mesg:
262 	note(0, "smtp: bad message -- no From header");
263 	goto bad;
264  bad_prot:
265 	if ((n = strlen(e)) > 0 && e[n - 1] == '\r')
266 		e[n - 1] = 0;
267 	note(0, "smtp: %s: service error:%s", svc, e);
268 	goto bad;
269  bad_send:
270 	note(SYSTEM, "smtp: %s: service write error", svc);
271 	goto bad;
272  bad_recv:
273 	note(SYSTEM, "smtp: %s: service read error", svc);
274  bad:
275 	r = -1;
276  done:
277 	sfclose(sp);
278 	sfclose(rp);
279 	return r;
280 }
281 
282 #else
283 
284 int
sendsmtp(FILE * fp,char ** argv)285 sendsmtp(FILE* fp, char** argv)
286 {
287 	note(0, "smtp: support not enabled");
288 	return -1;
289 }
290 
291 #endif
292