Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/mailx/smtp.c
1808 views
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
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
285
sendsmtp(FILE* fp, char** argv)
286
{
287
note(0, "smtp: support not enabled");
288
return -1;
289
}
290
291
#endif
292
293