1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * Abstract SMTP support for libwebsockets - SMTP sequencer
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2016-2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker *
24*1c60b9acSAndroid Build Coastguard Worker * This sequencer sits above the abstract protocol, and manages queueing,
25*1c60b9acSAndroid Build Coastguard Worker * retrying mail transmission, and retry limits.
26*1c60b9acSAndroid Build Coastguard Worker *
27*1c60b9acSAndroid Build Coastguard Worker * Having the sequencer means that, eg, we can manage retries after complete
28*1c60b9acSAndroid Build Coastguard Worker * connection failure.
29*1c60b9acSAndroid Build Coastguard Worker *
30*1c60b9acSAndroid Build Coastguard Worker * Connections to the smtp server are serialized
31*1c60b9acSAndroid Build Coastguard Worker */
32*1c60b9acSAndroid Build Coastguard Worker
33*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
34*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-abstract-protocols-smtp.h"
35*1c60b9acSAndroid Build Coastguard Worker
36*1c60b9acSAndroid Build Coastguard Worker typedef enum {
37*1c60b9acSAndroid Build Coastguard Worker LSMTPSS_DISCONNECTED,
38*1c60b9acSAndroid Build Coastguard Worker LSMTPSS_CONNECTING,
39*1c60b9acSAndroid Build Coastguard Worker LSMTPSS_CONNECTED,
40*1c60b9acSAndroid Build Coastguard Worker LSMTPSS_BUSY,
41*1c60b9acSAndroid Build Coastguard Worker } smtpss_connstate_t;
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker typedef struct lws_smtp_sequencer {
44*1c60b9acSAndroid Build Coastguard Worker struct lws_dll2_owner emails_owner; /* email queue */
45*1c60b9acSAndroid Build Coastguard Worker
46*1c60b9acSAndroid Build Coastguard Worker lws_abs_t *abs, *instance;
47*1c60b9acSAndroid Build Coastguard Worker lws_smtp_sequencer_args_t args;
48*1c60b9acSAndroid Build Coastguard Worker struct lws_sequencer *seq;
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard Worker smtpss_connstate_t connstate;
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker time_t email_connect_started;
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker /* holds the HELO for the smtp protocol to consume */
55*1c60b9acSAndroid Build Coastguard Worker lws_token_map_t apt[3];
56*1c60b9acSAndroid Build Coastguard Worker } lws_smtp_sequencer_t;
57*1c60b9acSAndroid Build Coastguard Worker
58*1c60b9acSAndroid Build Coastguard Worker /* sequencer messages specific to this sequencer */
59*1c60b9acSAndroid Build Coastguard Worker
60*1c60b9acSAndroid Build Coastguard Worker enum {
61*1c60b9acSAndroid Build Coastguard Worker SEQ_MSG_CLIENT_FAILED = LWSSEQ_USER_BASE,
62*1c60b9acSAndroid Build Coastguard Worker SEQ_MSG_CLIENT_DONE,
63*1c60b9acSAndroid Build Coastguard Worker };
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker /*
66*1c60b9acSAndroid Build Coastguard Worker * We're going to bind to the raw-skt transport, so tell that what we want it
67*1c60b9acSAndroid Build Coastguard Worker * to connect to
68*1c60b9acSAndroid Build Coastguard Worker */
69*1c60b9acSAndroid Build Coastguard Worker
70*1c60b9acSAndroid Build Coastguard Worker static const lws_token_map_t smtp_rs_transport_tokens[] = {
71*1c60b9acSAndroid Build Coastguard Worker {
72*1c60b9acSAndroid Build Coastguard Worker .u = { .value = "127.0.0.1" },
73*1c60b9acSAndroid Build Coastguard Worker .name_index = LTMI_PEER_V_DNS_ADDRESS,
74*1c60b9acSAndroid Build Coastguard Worker }, {
75*1c60b9acSAndroid Build Coastguard Worker .u = { .lvalue = 25 },
76*1c60b9acSAndroid Build Coastguard Worker .name_index = LTMI_PEER_LV_PORT,
77*1c60b9acSAndroid Build Coastguard Worker }, {
78*1c60b9acSAndroid Build Coastguard Worker }
79*1c60b9acSAndroid Build Coastguard Worker };
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker static void
lws_smtpc_kick_internal(lws_smtp_sequencer_t * s)82*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_kick_internal(lws_smtp_sequencer_t *s)
83*1c60b9acSAndroid Build Coastguard Worker {
84*1c60b9acSAndroid Build Coastguard Worker lws_smtp_email_t *e;
85*1c60b9acSAndroid Build Coastguard Worker lws_dll2_t *d;
86*1c60b9acSAndroid Build Coastguard Worker char buf[64];
87*1c60b9acSAndroid Build Coastguard Worker int n;
88*1c60b9acSAndroid Build Coastguard Worker lws_dll2_t *pd2;
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker pd2 = lws_dll2_get_head(&s->emails_owner);
91*1c60b9acSAndroid Build Coastguard Worker if (!pd2)
92*1c60b9acSAndroid Build Coastguard Worker return;
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker e = lws_container_of(pd2, lws_smtp_email_t, list);
95*1c60b9acSAndroid Build Coastguard Worker if (!e)
96*1c60b9acSAndroid Build Coastguard Worker return;
97*1c60b9acSAndroid Build Coastguard Worker
98*1c60b9acSAndroid Build Coastguard Worker /* Is there something to do? If so, we need a connection... */
99*1c60b9acSAndroid Build Coastguard Worker
100*1c60b9acSAndroid Build Coastguard Worker if (s->connstate == LSMTPSS_DISCONNECTED) {
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker s->apt[0].u.value = s->args.helo;
103*1c60b9acSAndroid Build Coastguard Worker s->apt[0].name_index = LTMI_PSMTP_V_HELO;
104*1c60b9acSAndroid Build Coastguard Worker s->apt[1].u.value = (void *)e;
105*1c60b9acSAndroid Build Coastguard Worker s->apt[1].name_index = LTMI_PSMTP_V_LWS_SMTP_EMAIL_T;
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker /*
108*1c60b9acSAndroid Build Coastguard Worker * create and connect the smtp protocol + transport
109*1c60b9acSAndroid Build Coastguard Worker */
110*1c60b9acSAndroid Build Coastguard Worker
111*1c60b9acSAndroid Build Coastguard Worker s->abs = lws_abstract_alloc(s->args.vhost, NULL, "smtp.raw_skt",
112*1c60b9acSAndroid Build Coastguard Worker s->apt, smtp_rs_transport_tokens,
113*1c60b9acSAndroid Build Coastguard Worker s->seq, NULL);
114*1c60b9acSAndroid Build Coastguard Worker if (!s->abs)
115*1c60b9acSAndroid Build Coastguard Worker return;
116*1c60b9acSAndroid Build Coastguard Worker
117*1c60b9acSAndroid Build Coastguard Worker s->instance = lws_abs_bind_and_create_instance(s->abs);
118*1c60b9acSAndroid Build Coastguard Worker if (!s->instance) {
119*1c60b9acSAndroid Build Coastguard Worker lws_abstract_free(&s->abs);
120*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to create SMTP client\n", __func__);
121*1c60b9acSAndroid Build Coastguard Worker
122*1c60b9acSAndroid Build Coastguard Worker goto bail1;
123*1c60b9acSAndroid Build Coastguard Worker }
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker s->connstate = LSMTPSS_CONNECTING;
126*1c60b9acSAndroid Build Coastguard Worker lws_seq_timeout_us(s->seq, 10 * LWS_USEC_PER_SEC);
127*1c60b9acSAndroid Build Coastguard Worker return;
128*1c60b9acSAndroid Build Coastguard Worker }
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker /* ask the transport if we have a connection to the server ongoing */
131*1c60b9acSAndroid Build Coastguard Worker
132*1c60b9acSAndroid Build Coastguard Worker if (s->abs->at->state(s->abs->ati)) {
133*1c60b9acSAndroid Build Coastguard Worker /*
134*1c60b9acSAndroid Build Coastguard Worker * there's a connection, it could be still trying to connect
135*1c60b9acSAndroid Build Coastguard Worker * or established
136*1c60b9acSAndroid Build Coastguard Worker */
137*1c60b9acSAndroid Build Coastguard Worker s->abs->at->ask_for_writeable(s->abs->ati);
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker return;
140*1c60b9acSAndroid Build Coastguard Worker }
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker /* there's no existing connection */
143*1c60b9acSAndroid Build Coastguard Worker
144*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_state_transition(c, LGSSMTP_CONNECTING);
145*1c60b9acSAndroid Build Coastguard Worker
146*1c60b9acSAndroid Build Coastguard Worker if (s->abs->at->client_conn(s->abs)) {
147*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to connect\n", __func__);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker return;
150*1c60b9acSAndroid Build Coastguard Worker }
151*1c60b9acSAndroid Build Coastguard Worker
152*1c60b9acSAndroid Build Coastguard Worker e->tries++;
153*1c60b9acSAndroid Build Coastguard Worker e->last_try = lws_now_secs();
154*1c60b9acSAndroid Build Coastguard Worker }
155*1c60b9acSAndroid Build Coastguard Worker
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker /*
158*1c60b9acSAndroid Build Coastguard Worker * The callback we get from the smtp protocol... we use this to drive
159*1c60b9acSAndroid Build Coastguard Worker * decisions about destroy email, retry and fail.
160*1c60b9acSAndroid Build Coastguard Worker *
161*1c60b9acSAndroid Build Coastguard Worker * Sequencer will handle it via the event loop.
162*1c60b9acSAndroid Build Coastguard Worker */
163*1c60b9acSAndroid Build Coastguard Worker
164*1c60b9acSAndroid Build Coastguard Worker static int
email_result(void * e,void * d,int disp,void * b,size_t l)165*1c60b9acSAndroid Build Coastguard Worker email_result(void *e, void *d, int disp, void *b, size_t l)
166*1c60b9acSAndroid Build Coastguard Worker {
167*1c60b9acSAndroid Build Coastguard Worker lws_smtp_sequencer_t *s = (lws_smtp_sequencer_t *)d;
168*1c60b9acSAndroid Build Coastguard Worker
169*1c60b9acSAndroid Build Coastguard Worker lws_sequencer_event(s->seq, LWSSEQ_USER_BASE + disp, e);
170*1c60b9acSAndroid Build Coastguard Worker
171*1c60b9acSAndroid Build Coastguard Worker return 0;
172*1c60b9acSAndroid Build Coastguard Worker }
173*1c60b9acSAndroid Build Coastguard Worker
174*1c60b9acSAndroid Build Coastguard Worker static int
cleanup(struct lws_dll2 * d,void * user)175*1c60b9acSAndroid Build Coastguard Worker cleanup(struct lws_dll2 *d, void *user)
176*1c60b9acSAndroid Build Coastguard Worker {
177*1c60b9acSAndroid Build Coastguard Worker lws_smtp_email_t *e;
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker e = lws_container_of(d, lws_smtp_email_t, list);
180*1c60b9acSAndroid Build Coastguard Worker if (e->done)
181*1c60b9acSAndroid Build Coastguard Worker e->done(e, "destroying", 10);
182*1c60b9acSAndroid Build Coastguard Worker
183*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(d);
184*1c60b9acSAndroid Build Coastguard Worker lws_free(e);
185*1c60b9acSAndroid Build Coastguard Worker
186*1c60b9acSAndroid Build Coastguard Worker return 0;
187*1c60b9acSAndroid Build Coastguard Worker }
188*1c60b9acSAndroid Build Coastguard Worker
189*1c60b9acSAndroid Build Coastguard Worker static lws_seq_cb_return_t
smtp_sequencer_cb(struct lws_sequencer * seq,void * user,int event,void * data)190*1c60b9acSAndroid Build Coastguard Worker smtp_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data)
191*1c60b9acSAndroid Build Coastguard Worker {
192*1c60b9acSAndroid Build Coastguard Worker struct lws_smtp_sequencer_t *s = (struct lws_smtp_sequencer_t *)user;
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker switch ((int)event) {
195*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_CREATED: /* our sequencer just got started */
196*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: %s: created\n", __func__,
197*1c60b9acSAndroid Build Coastguard Worker lws_sequencer_name(seq));
198*1c60b9acSAndroid Build Coastguard Worker s->connstate = LSMTPSS_DISCONNECTED;
199*1c60b9acSAndroid Build Coastguard Worker s->state = 0; /* first thing we'll do is the first url */
200*1c60b9acSAndroid Build Coastguard Worker goto step;
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_DESTROYED:
203*1c60b9acSAndroid Build Coastguard Worker lws_dll2_foreach_safe(&s->pending_owner, NULL, cleanup);
204*1c60b9acSAndroid Build Coastguard Worker break;
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_TIMED_OUT:
207*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: LWSSEQ_TIMED_OUT\n", __func__);
208*1c60b9acSAndroid Build Coastguard Worker break;
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_USER_BASE + LWS_SMTP_DISPOSITION_SENT:
211*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_free_email(data);
212*1c60b9acSAndroid Build Coastguard Worker break;
213*1c60b9acSAndroid Build Coastguard Worker
214*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_WSI_CONNECTED:
215*1c60b9acSAndroid Build Coastguard Worker s->connstate = LSMTPSS_CONNECTED;
216*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_kick_internal(s);
217*1c60b9acSAndroid Build Coastguard Worker break;
218*1c60b9acSAndroid Build Coastguard Worker
219*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_WSI_CONN_FAIL:
220*1c60b9acSAndroid Build Coastguard Worker case LWSSEQ_WSI_CONN_CLOSE:
221*1c60b9acSAndroid Build Coastguard Worker s->connstate = LSMTPSS_DISCONNECTED;
222*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_kick_internal(s);
223*1c60b9acSAndroid Build Coastguard Worker break;
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker case SEQ_MSG_SENT:
226*1c60b9acSAndroid Build Coastguard Worker break;
227*1c60b9acSAndroid Build Coastguard Worker
228*1c60b9acSAndroid Build Coastguard Worker default:
229*1c60b9acSAndroid Build Coastguard Worker break;
230*1c60b9acSAndroid Build Coastguard Worker }
231*1c60b9acSAndroid Build Coastguard Worker
232*1c60b9acSAndroid Build Coastguard Worker return LWSSEQ_RET_CONTINUE;
233*1c60b9acSAndroid Build Coastguard Worker }
234*1c60b9acSAndroid Build Coastguard Worker
235*1c60b9acSAndroid Build Coastguard Worker /*
236*1c60b9acSAndroid Build Coastguard Worker * Creates an lws_sequencer to manage the test sequence
237*1c60b9acSAndroid Build Coastguard Worker */
238*1c60b9acSAndroid Build Coastguard Worker
239*1c60b9acSAndroid Build Coastguard Worker lws_smtp_sequencer_t *
lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t * args)240*1c60b9acSAndroid Build Coastguard Worker lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t *args)
241*1c60b9acSAndroid Build Coastguard Worker {
242*1c60b9acSAndroid Build Coastguard Worker lws_smtp_sequencer_t *s;
243*1c60b9acSAndroid Build Coastguard Worker struct lws_sequencer *seq;
244*1c60b9acSAndroid Build Coastguard Worker
245*1c60b9acSAndroid Build Coastguard Worker /*
246*1c60b9acSAndroid Build Coastguard Worker * Create a sequencer in the event loop to manage the SMTP queue
247*1c60b9acSAndroid Build Coastguard Worker */
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker seq = lws_sequencer_create(args->vhost->context, 0,
250*1c60b9acSAndroid Build Coastguard Worker sizeof(lws_smtp_sequencer_t), (void **)&s,
251*1c60b9acSAndroid Build Coastguard Worker smtp_sequencer_cb, "smtp-seq");
252*1c60b9acSAndroid Build Coastguard Worker if (!seq) {
253*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: unable to create sequencer\n", __func__);
254*1c60b9acSAndroid Build Coastguard Worker return NULL;
255*1c60b9acSAndroid Build Coastguard Worker }
256*1c60b9acSAndroid Build Coastguard Worker
257*1c60b9acSAndroid Build Coastguard Worker s->abs = *args->abs;
258*1c60b9acSAndroid Build Coastguard Worker s->args = *args;
259*1c60b9acSAndroid Build Coastguard Worker s->seq = seq;
260*1c60b9acSAndroid Build Coastguard Worker
261*1c60b9acSAndroid Build Coastguard Worker /* set defaults in our copy of the args */
262*1c60b9acSAndroid Build Coastguard Worker
263*1c60b9acSAndroid Build Coastguard Worker if (!s->args.helo[0])
264*1c60b9acSAndroid Build Coastguard Worker strcpy(s->args.helo, "default-helo");
265*1c60b9acSAndroid Build Coastguard Worker if (!s->args.email_queue_max)
266*1c60b9acSAndroid Build Coastguard Worker s->args.email_queue_max = 8;
267*1c60b9acSAndroid Build Coastguard Worker if (!s->args.retry_interval)
268*1c60b9acSAndroid Build Coastguard Worker s->args.retry_interval = 15 * 60;
269*1c60b9acSAndroid Build Coastguard Worker if (!s->args.delivery_timeout)
270*1c60b9acSAndroid Build Coastguard Worker s->args.delivery_timeout = 12 * 60 * 60;
271*1c60b9acSAndroid Build Coastguard Worker
272*1c60b9acSAndroid Build Coastguard Worker return s;
273*1c60b9acSAndroid Build Coastguard Worker }
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker void
lws_smtp_sequencer_destroy(lws_smtp_sequencer_t * s)276*1c60b9acSAndroid Build Coastguard Worker lws_smtp_sequencer_destroy(lws_smtp_sequencer_t *s)
277*1c60b9acSAndroid Build Coastguard Worker {
278*1c60b9acSAndroid Build Coastguard Worker /* sequencer destruction destroys all assets */
279*1c60b9acSAndroid Build Coastguard Worker lws_sequencer_destroy(&s->seq);
280*1c60b9acSAndroid Build Coastguard Worker }
281*1c60b9acSAndroid Build Coastguard Worker
282*1c60b9acSAndroid Build Coastguard Worker int
lws_smtpc_add_email(lws_smtp_sequencer_t * s,const char * payload,size_t payload_len,const char * sender,const char * recipient,void * data,lws_smtp_cb_t done)283*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_add_email(lws_smtp_sequencer_t *s, const char *payload,
284*1c60b9acSAndroid Build Coastguard Worker size_t payload_len, const char *sender,
285*1c60b9acSAndroid Build Coastguard Worker const char *recipient, void *data, lws_smtp_cb_t done)
286*1c60b9acSAndroid Build Coastguard Worker {
287*1c60b9acSAndroid Build Coastguard Worker lws_smtp_email_t *e;
288*1c60b9acSAndroid Build Coastguard Worker
289*1c60b9acSAndroid Build Coastguard Worker if (s->emails_owner.count > s->args.email_queue_max) {
290*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: email queue at limit of %d\n", __func__,
291*1c60b9acSAndroid Build Coastguard Worker (int)s->args.email_queue_max);
292*1c60b9acSAndroid Build Coastguard Worker
293*1c60b9acSAndroid Build Coastguard Worker return 1;
294*1c60b9acSAndroid Build Coastguard Worker }
295*1c60b9acSAndroid Build Coastguard Worker
296*1c60b9acSAndroid Build Coastguard Worker if (!done)
297*1c60b9acSAndroid Build Coastguard Worker return 1;
298*1c60b9acSAndroid Build Coastguard Worker
299*1c60b9acSAndroid Build Coastguard Worker e = malloc(sizeof(*e) + payload_len + 1);
300*1c60b9acSAndroid Build Coastguard Worker if (!e)
301*1c60b9acSAndroid Build Coastguard Worker return 1;
302*1c60b9acSAndroid Build Coastguard Worker
303*1c60b9acSAndroid Build Coastguard Worker memset(e, 0, sizeof(*e));
304*1c60b9acSAndroid Build Coastguard Worker
305*1c60b9acSAndroid Build Coastguard Worker e->data = data;
306*1c60b9acSAndroid Build Coastguard Worker e->done = done;
307*1c60b9acSAndroid Build Coastguard Worker
308*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(e->from, sender, sizeof(e->from));
309*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(e->to, recipient, sizeof(e->to));
310*1c60b9acSAndroid Build Coastguard Worker
311*1c60b9acSAndroid Build Coastguard Worker memcpy((char *)&e[1], payload, payload_len + 1);
312*1c60b9acSAndroid Build Coastguard Worker
313*1c60b9acSAndroid Build Coastguard Worker e->added = lws_now_secs();
314*1c60b9acSAndroid Build Coastguard Worker e->last_try = 0;
315*1c60b9acSAndroid Build Coastguard Worker e->tries = 0;
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker lws_dll2_clear(&e->list);
318*1c60b9acSAndroid Build Coastguard Worker lws_dll2_add_tail(&e->list, &s->emails_owner);
319*1c60b9acSAndroid Build Coastguard Worker
320*1c60b9acSAndroid Build Coastguard Worker lws_smtpc_kick_internal(s);
321*1c60b9acSAndroid Build Coastguard Worker
322*1c60b9acSAndroid Build Coastguard Worker return 0;
323*1c60b9acSAndroid Build Coastguard Worker }
324