Show contents of the CP payload in message_t stringification
[strongswan.git] / src / libfast / smtp.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "smtp.h"
17
18 #include <unistd.h>
19 #include <errno.h>
20
21 #include <debug.h>
22
23 typedef struct private_smtp_t private_smtp_t;
24
25 /**
26 * Private data of an smtp_t object.
27 */
28 struct private_smtp_t {
29
30 /**
31 * Public smtp_t interface.
32 */
33 smtp_t public;
34
35 /**
36 * file stream to SMTP server
37 */
38 FILE *f;
39 };
40
41 /**
42 * Read the response code from an SMTP server
43 */
44 static int read_response(private_smtp_t *this)
45 {
46 char buf[256], *end;
47 int res = 0;
48
49 while (TRUE)
50 {
51 if (!fgets(buf, sizeof(buf), this->f))
52 {
53 return 0;
54 }
55 res = strtol(buf, &end, 10);
56 switch (*end)
57 {
58 case '-':
59 continue;
60 case ' ':
61 case '\0':
62 case '\n':
63 break;
64 default:
65 return 0;
66 }
67 break;
68 }
69 return res;
70 }
71
72 /**
73 * write a SMTP command to the server, read response code
74 */
75 static int write_cmd(private_smtp_t *this, char *fmt, ...)
76 {
77 char buf[256];
78 va_list args;
79
80 va_start(args, fmt);
81 vsnprintf(buf, sizeof(buf), fmt, args);
82 va_end(args);
83
84 if (fprintf(this->f, "%s\n", buf) < 1)
85 {
86 DBG1(DBG_LIB, "sending SMTP command failed");
87 return 0;
88 }
89 return read_response(this);
90 }
91
92 METHOD(smtp_t, send_mail, bool,
93 private_smtp_t *this, char *from, char *to, char *subject, char *fmt, ...)
94 {
95 va_list args;
96
97 if (write_cmd(this, "MAIL FROM:<%s>", from) != 250)
98 {
99 DBG1(DBG_LIB, "SMTP MAIL FROM failed");
100 return FALSE;
101 }
102 if (write_cmd(this, "RCPT TO:<%s>", to) != 250)
103 {
104 DBG1(DBG_LIB, "SMTP RCPT TO failed");
105 return FALSE;
106 }
107 if (write_cmd(this, "DATA") != 354)
108 {
109 DBG1(DBG_LIB, "SMTP DATA failed");
110 return FALSE;
111 }
112
113 fprintf(this->f, "From: %s\n", from);
114 fprintf(this->f, "To: %s\n", to);
115 fprintf(this->f, "Subject: %s\n", subject);
116 fprintf(this->f, "\n");
117 va_start(args, fmt);
118 vfprintf(this->f, fmt, args);
119 va_end(args);
120 fprintf(this->f, "\n.\n");
121 return read_response(this) == 250;
122 }
123
124
125 METHOD(smtp_t, destroy, void,
126 private_smtp_t *this)
127 {
128 write_cmd(this, "QUIT");
129 fclose(this->f);
130 free(this);
131 }
132
133 /**
134 * See header
135 */
136 smtp_t *smtp_create()
137 {
138 private_smtp_t *this;
139 struct sockaddr_in addr;
140 int s;
141
142 INIT(this,
143 .public = {
144 .send_mail = _send_mail,
145 .destroy = _destroy,
146 },
147 );
148
149 s = socket(AF_INET, SOCK_STREAM, 0);
150 if (s < 0)
151 {
152 DBG1(DBG_LIB, "opening SMTP socket failed: %s", strerror(errno));
153 free(this);
154 return NULL;
155 }
156 addr.sin_family = AF_INET;
157 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
158 addr.sin_port = htons(25);
159 if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
160 {
161 DBG1(DBG_LIB, "connecting to SMTP server failed: %s", strerror(errno));
162 close(s);
163 free(this);
164 return NULL;
165 }
166 this->f = fdopen(s, "a+");
167 if (!this->f)
168 {
169 DBG1(DBG_LIB, "opening stream to SMTP server failed: %s",
170 strerror(errno));
171 close(s);
172 free(this);
173 return NULL;
174 }
175 if (read_response(this) != 220 ||
176 write_cmd(this, "EHLO localhost") != 250)
177 {
178 DBG1(DBG_LIB, "SMTP EHLO failed");
179 fclose(this->f);
180 free(this);
181 return NULL;
182 }
183 return &this->public;
184 }
185