summaryrefslogtreecommitdiffstats
path: root/src/lib-smtp/smtp-client-private.h
blob: 40f50f9de55f7ef9e8a92cd95b5c63a4d8795c2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
#ifndef SMTP_CLIENT_PRIVATE_H
#define SMTP_CLIENT_PRIVATE_H

#include "connection.h"

#include "smtp-common.h"
#include "smtp-params.h"
#include "smtp-client.h"
#include "smtp-client-command.h"
#include "smtp-client-transaction.h"
#include "smtp-client-connection.h"

#define SMTP_CLIENT_DATA_CHUNK_SIZE IO_BLOCK_SIZE

struct smtp_client_command {
	pool_t pool;
	int refcount;
	struct event *event;

	struct smtp_client_command *prev, *next;

	buffer_t *data;
	unsigned int send_pos;
	const char *name;

	enum smtp_client_command_flags flags;

	struct smtp_client_connection *conn;
	enum smtp_client_command_state state;
	unsigned int replies_expected;
	unsigned int replies_seen;

	struct istream *stream;
	uoff_t stream_size;

	struct smtp_reply *delayed_failure;

	smtp_client_command_callback_t *callback;
	void *context;

	void (*abort_callback)(void *context);
	void *abort_context;

	void (*sent_callback)(void *context);
	void *sent_context;

	bool has_stream:1;
	bool stream_dot:1;
	bool stream_finished:1;
	bool ehlo:1;
	bool locked:1;
	bool plug:1;
	bool failed:1;
	bool aborting:1;
	bool delay_failure:1;
	bool delaying_failure:1;
	bool event_finished:1;
};

struct smtp_client_transaction_mail {
	pool_t pool;
	struct smtp_client_transaction *trans;

	struct smtp_client_transaction_mail *prev, *next;

	struct smtp_address *mail_from;
	struct smtp_params_mail mail_params;

	smtp_client_command_callback_t *mail_callback;
	void *context;

	struct smtp_client_command *cmd_mail_from;
};

struct smtp_client_transaction_rcpt {
	pool_t pool;
	struct smtp_client_transaction *trans;
	struct event *event;

	struct smtp_client_transaction_rcpt *prev, *next;

	struct smtp_address *rcpt_to;
	struct smtp_params_rcpt rcpt_params;

	smtp_client_command_callback_t *rcpt_callback;
	void *context;

	smtp_client_command_callback_t *data_callback;
	void *data_context;

	struct smtp_client_command *cmd_rcpt_to;

	bool external_pool:1;
	bool queued:1;
	bool finished:1;
};

struct smtp_client_transaction {
	pool_t pool;
	int refcount;
	struct event *event;

	struct smtp_client_transaction *prev, *next;

	struct smtp_client_connection *conn;
	enum smtp_client_transaction_flags flags;

	enum smtp_client_transaction_state state;
	struct smtp_client_command *cmd_data, *cmd_rset;
	struct smtp_client_command *cmd_plug, *cmd_last;
	struct smtp_reply *failure, *mail_failure, *data_failure;

	struct smtp_client_transaction_mail *mail_head, *mail_tail;
	struct smtp_client_transaction_mail *mail_send;

	struct smtp_client_transaction_rcpt *rcpts_queue_head, *rcpts_queue_tail;
	struct smtp_client_transaction_rcpt *rcpts_send;
	struct smtp_client_transaction_rcpt *rcpts_head, *rcpts_tail;
	struct smtp_client_transaction_rcpt *rcpts_data;
	unsigned int rcpts_queue_count;
	unsigned int rcpts_count;

	unsigned int rcpts_total;
	unsigned int rcpts_aborted;
	unsigned int rcpts_denied;
	unsigned int rcpts_failed;
	unsigned int rcpts_succeeded;

	struct istream *data_input;
	smtp_client_command_callback_t *data_callback;
	void *data_context;

	smtp_client_command_callback_t *reset_callback;
	void *reset_context;

	smtp_client_transaction_callback_t *callback;
	void *context;

	struct smtp_client_transaction_times times;

	unsigned int finish_timeout_msecs;
	struct timeout *to_finish, *to_send;

	bool immediate:1;
	bool sender_accepted:1;
	bool data_provided:1;
	bool reset:1;
	bool finished:1;
	bool submitting:1;
	bool failing:1;
	bool submitted_data:1;
};

struct smtp_client_login_callback {
	smtp_client_command_callback_t *callback;
	void *context;
};

struct smtp_client_connection {
	struct connection conn;
	pool_t pool;
	int refcount;
	struct event *event;

	struct smtp_client *client;

	enum smtp_protocol protocol;
	const char *path, *host;
	in_port_t port;
	enum smtp_client_connection_ssl_mode ssl_mode;

	int connect_errno;

	struct smtp_client_settings set;
	char *password;
	ARRAY(struct smtp_client_capability_extra) extra_capabilities;

	pool_t cap_pool;
	struct {
		enum smtp_capability standard;
		ARRAY(struct smtp_capability_extra) extra;
		const char **auth_mechanisms;
		const char **xclient_args;
		uoff_t size;

		/* Lists of custom MAIL/RCPT parameters supported by peer. These
		   arrays always end in NULL pointer once created. */
		ARRAY_TYPE(const_string) mail_param_extensions;
		ARRAY_TYPE(const_string) rcpt_param_extensions;
	} caps;

	struct smtp_reply_parser *reply_parser;
	struct smtp_reply reply;
	unsigned int xclient_replies_expected;

	struct dns_lookup *dns_lookup;

	struct dsasl_client *sasl_client;
	char *sasl_ir;
	struct smtp_client_command *cmd_auth;

	struct timeout *to_connect, *to_trans, *to_commands, *to_cmd_fail;
	struct io *io_cmd_payload;

	struct istream *raw_input;
	struct ostream *raw_output, *dot_output;

	struct ssl_iostream_context *ssl_ctx;
	struct ssl_iostream *ssl_iostream;

	enum smtp_client_connection_state state;
	pool_t state_pool;
	struct {
		struct smtp_reply *login_reply;
	} state_data;

	ARRAY(struct smtp_client_login_callback) login_callbacks;

	/* commands pending in queue to be sent */
	struct smtp_client_command *cmd_send_queue_head, *cmd_send_queue_tail;
	unsigned int cmd_send_queue_count;
	/* commands that have been (mostly) sent, waiting for response */
	struct smtp_client_command *cmd_wait_list_head, *cmd_wait_list_tail;
	unsigned int cmd_wait_list_count;
	/* commands that have failed before submission */
	struct smtp_client_command *cmd_fail_list;
	/* command sending data stream */
	struct smtp_client_command *cmd_streaming;

	/* active transactions */
	struct smtp_client_transaction *transactions_head, *transactions_tail;

	unsigned int ips_count, prev_connect_idx;
	struct ip_addr *ips;

	bool host_is_ip:1;
	bool old_smtp:1;
	bool authenticated:1;
	bool xclient_sent:1;
	bool connect_failed:1;
	bool connect_succeeded:1;
	bool handshake_failed:1;
	bool corked:1;
	bool sent_quit:1;
	bool sending_command:1;
	bool reset_needed:1;
	bool failing:1;
	bool destroying:1;
	bool closed:1;
};

struct smtp_client {
	pool_t pool;

	struct smtp_client_settings set;

	struct event *event;
	struct ioloop *ioloop;
	struct ssl_iostream_context *ssl_ctx;

	struct connection_list *conn_list;
};

/*
 * Command
 */

void smtp_client_command_free(struct smtp_client_command *cmd);
int smtp_client_command_send_more(struct smtp_client_connection *conn);
int smtp_client_command_input_reply(struct smtp_client_command *cmd,
				    const struct smtp_reply *reply);

void smtp_client_command_drop_callback(struct smtp_client_command *cmd);

void smtp_client_command_fail(struct smtp_client_command **_cmd,
			      unsigned int status, const char *error);
void smtp_client_command_fail_reply(struct smtp_client_command **_cmd,
				    const struct smtp_reply *reply);

void smtp_client_commands_list_abort(struct smtp_client_command *cmds_list,
				     unsigned int cmds_list_count);
void smtp_client_commands_list_fail_reply(
	struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
	const struct smtp_reply *reply);

void smtp_client_commands_abort_delayed(struct smtp_client_connection *conn);
void smtp_client_commands_fail_delayed(struct smtp_client_connection *conn);

/*
 * Transaction
 */

void smtp_client_transaction_connection_result(
	struct smtp_client_transaction *trans,
	const struct smtp_reply *reply);
void smtp_client_transaction_connection_destroyed(
	struct smtp_client_transaction *trans);

void smtp_client_transaction_switch_ioloop(
	struct smtp_client_transaction *trans);

/*
 * Connection
 */

struct connection_list *smtp_client_connection_list_init(void);

void smtp_client_connection_send_xclient(struct smtp_client_connection *conn);

void smtp_client_connection_fail(struct smtp_client_connection *conn,
				 unsigned int status, const char *error,
				 const char *user_error) ATTR_NULL(3);

void smtp_client_connection_handle_output_error(
	struct smtp_client_connection *conn);
void smtp_client_connection_trigger_output(
	struct smtp_client_connection *conn);

void smtp_client_connection_start_cmd_timeout(
	struct smtp_client_connection *conn);
void smtp_client_connection_update_cmd_timeout(
	struct smtp_client_connection *conn);

void smtp_client_connection_add_transaction(
	struct smtp_client_connection *conn,
	struct smtp_client_transaction *trans);
void smtp_client_connection_abort_transaction(
	struct smtp_client_connection *conn,
	struct smtp_client_transaction *trans);
void smtp_client_connection_next_transaction(
	struct smtp_client_connection *conn,
	struct smtp_client_transaction *trans);

/*
 * Client
 */

int smtp_client_init_ssl_ctx(struct smtp_client *client, const char **error_r);

#endif