2 * SMTP support for libwebsockets
4 * Copyright (C) 2016 Andy Green <andy@warmcat.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-libwebsockets.h"
29 gettimeofday(&tv, NULL);
35 ccb(uv_handle_t* handle)
41 alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
43 struct lws_email *email = (struct lws_email *)handle->data;
45 *buf = uv_buf_init(email->email_buf, sizeof(email->email_buf) - 1);
49 on_write_end(uv_write_t *req, int status) {
50 lwsl_notice("%s\n", __func__);
52 fprintf(stderr, "error on_write_end");
58 lwsgs_email_read(struct uv_stream_s *s, ssize_t nread, const uv_buf_t *buf)
60 struct lws_email *email = (struct lws_email *)s->data;
61 static const short retcodes[] = {
77 email->email_buf[nread] = '\0';
78 lwsl_notice("%s: %s\n", __func__, buf->base);
80 lwsl_err("%s: failed\n", __func__);
85 if (n != retcodes[email->estate]) {
86 lwsl_err("%s: bad response from server\n", __func__);
90 switch (email->estate) {
91 case LGSSMTP_CONNECTED:
92 n = sprintf(email->content, "HELO %s\n", email->email_helo);
93 email->estate = LGSSMTP_SENT_HELO;
95 case LGSSMTP_SENT_HELO:
96 n = sprintf(email->content, "MAIL FROM: <%s>\n", email->email_from);
97 email->estate = LGSSMTP_SENT_FROM;
99 case LGSSMTP_SENT_FROM:
100 n = sprintf(email->content, "RCPT TO: <%s>\n", email->email_to);
101 email->estate = LGSSMTP_SENT_TO;
103 case LGSSMTP_SENT_TO:
104 n = sprintf(email->content, "DATA\n");
105 email->estate = LGSSMTP_SENT_DATA;
107 case LGSSMTP_SENT_DATA:
108 if (email->on_get_body(email, email->content, email->max_content_size))
110 n = strlen(email->content);
111 email->estate = LGSSMTP_SENT_BODY;
113 case LGSSMTP_SENT_BODY:
114 n = sprintf(email->content, "quit\n");
115 email->estate = LGSSMTP_SENT_QUIT;
117 case LGSSMTP_SENT_QUIT:
118 lwsl_notice("%s: done\n", __func__);
119 email->on_sent(email);
120 email->estate = LGSSMTP_IDLE;
126 puts(email->content);
127 wbuf = uv_buf_init(email->content, n);
128 uv_write(&write_req, s, &wbuf, 1, on_write_end);
134 uv_close((uv_handle_t *)s, ccb);
138 lwsgs_email_on_connect(uv_connect_t *req, int status)
140 struct lws_email *email = (struct lws_email *)req->data;
142 lwsl_notice("%s\n", __func__);
145 lwsl_err("%s: failed\n", __func__);
149 uv_read_start(req->handle, alloc_buffer, lwsgs_email_read);
150 email->estate = LGSSMTP_CONNECTED;
155 uv_timeout_cb_email(uv_timer_t *w
156 #if UV_VERSION_MAJOR == 0
161 struct lws_email *email = lws_container_of(w, struct lws_email,
163 time_t now = lwsgs_now_secs();
164 struct sockaddr_in req_addr;
166 switch (email->estate) {
169 if (email->on_next(email))
172 email->estate = LGSSMTP_CONNECTING;
174 uv_tcp_init(email->loop, &email->email_client);
175 if (uv_ip4_addr(email->email_smtp_ip, 25, &req_addr)) {
176 lwsl_err("Unable to convert mailserver ads\n");
180 lwsl_notice("LGSSMTP_IDLE: connecting\n");
182 email->email_connect_started = now;
183 email->email_connect_req.data = email;
184 email->email_client.data = email;
185 uv_tcp_connect(&email->email_connect_req, &email->email_client,
186 (struct sockaddr *)&req_addr,
187 lwsgs_email_on_connect);
189 uv_timer_start(&email->timeout_email,
190 uv_timeout_cb_email, 5000, 0);
194 case LGSSMTP_CONNECTING:
195 if (email->email_connect_started - now > 5) {
196 lwsl_err("mail session timed out\n");
197 /* !!! kill the connection */
198 uv_close((uv_handle_t *) &email->email_connect_req, ccb);
199 email->estate = LGSSMTP_IDLE;
208 LWS_VISIBLE LWS_EXTERN int
209 lws_email_init(struct lws_email *email, uv_loop_t *loop, int max_content)
211 email->content = lws_malloc(max_content);
214 email->max_content_size = max_content;
215 uv_timer_init(loop, &email->timeout_email);
219 /* trigger him one time in a bit */
220 uv_timer_start(&email->timeout_email, uv_timeout_cb_email, 2000, 0);
225 LWS_VISIBLE LWS_EXTERN void
226 lws_email_check(struct lws_email *email)
228 uv_timer_start(&email->timeout_email, uv_timeout_cb_email, 1000, 0);
231 LWS_VISIBLE LWS_EXTERN void
232 lws_email_destroy(struct lws_email *email)
235 lws_free_set_NULL(email->content);
237 uv_timer_stop(&email->timeout_email);