1 #ifndef SMTP_SERVER_H 2 #define SMTP_SERVER_H 3 4 #include "smtp-common.h" 5 #include "smtp-command.h" 6 #include "smtp-params.h" 7 8 struct smtp_address; 9 struct smtp_reply; 10 struct smtp_command; 11 12 struct smtp_server_helo_data; 13 14 struct smtp_server_esmtp_param; 15 struct smtp_server_cmd_ehlo; 16 struct smtp_server_cmd_mail; 17 struct smtp_server_cmd_ctx; 18 struct smtp_server_command; 19 struct smtp_server_reply; 20 struct smtp_server_recipient; 21 struct smtp_server_transaction; 22 23 struct smtp_server; 24 25 /* 26 * Types 27 */ 28 29 enum smtp_server_state { 30 SMTP_SERVER_STATE_GREETING = 0, 31 SMTP_SERVER_STATE_XCLIENT, 32 SMTP_SERVER_STATE_HELO, 33 SMTP_SERVER_STATE_STARTTLS, 34 SMTP_SERVER_STATE_AUTH, 35 SMTP_SERVER_STATE_READY, 36 SMTP_SERVER_STATE_MAIL_FROM, 37 SMTP_SERVER_STATE_RCPT_TO, 38 SMTP_SERVER_STATE_DATA, 39 }; 40 extern const char *const smtp_server_state_names[]; 41 42 struct smtp_server_helo_data { 43 const char *domain; 44 45 bool domain_valid:1; /* Valid domain/literal specified */ 46 bool old_smtp:1; /* Client sent HELO rather than EHLO */ 47 }; 48 49 /* 50 * Recipient 51 */ 52 53 enum smtp_server_recipient_hook_type { 54 /* approved: the server is about to approve this recipient by sending 55 a success reply to the RCPT command. */ 56 SMTP_SERVER_RECIPIENT_HOOK_APPROVED, 57 /* data_replied: the DATA command is replied for this recipient */ 58 SMTP_SERVER_RECIPIENT_HOOK_DATA_REPLIED, 59 /* destroy: recipient is about to be destroyed. */ 60 SMTP_SERVER_RECIPIENT_HOOK_DESTROY 61 }; 62 63 typedef void smtp_server_rcpt_func_t(struct smtp_server_recipient *rcpt, 64 void *context); 65 66 struct smtp_server_recipient { 67 pool_t pool; 68 struct smtp_server_connection *conn; 69 struct smtp_server_transaction *trans; 70 struct event *event; 71 72 struct smtp_address *path; 73 struct smtp_params_rcpt params; 74 75 /* The associated RCPT or DATA command (whichever applies). This is NULL 76 when no command is active. */ 77 struct smtp_server_cmd_ctx *cmd; 78 79 /* The index in the list of approved recipients */ 80 unsigned int index; 81 82 void *context; 83 84 bool replied:1; 85 bool finished:1; 86 }; 87 ARRAY_DEFINE_TYPE(smtp_server_recipient, struct smtp_server_recipient *); 88 89 /* Returns the original recipient path if available. Otherwise, it returns the 90 final path. */ 91 const struct smtp_address * 92 smtp_server_recipient_get_original(struct smtp_server_recipient *rcpt); 93 94 struct smtp_server_reply * 95 smtp_server_recipient_get_reply(struct smtp_server_recipient *rcpt); 96 bool smtp_server_recipient_is_replied(struct smtp_server_recipient *rcpt); 97 void smtp_server_recipient_replyv(struct smtp_server_recipient *rcpt, 98 unsigned int status, const char *enh_code, 99 const char *fmt, va_list args) 100 ATTR_FORMAT(4, 0); 101 void smtp_server_recipient_reply(struct smtp_server_recipient *rcpt, 102 unsigned int status, const char *enh_code, 103 const char *fmt, ...) ATTR_FORMAT(4, 5); 104 void smtp_server_recipient_reply_forward(struct smtp_server_recipient *rcpt, 105 const struct smtp_reply *from); 106 107 /* Hooks */ 108 109 void smtp_server_recipient_add_hook(struct smtp_server_recipient *rcpt, 110 enum smtp_server_recipient_hook_type type, 111 smtp_server_rcpt_func_t func, 112 void *context); 113 #define smtp_server_recipient_add_hook(_rcpt, _type, _func, _context) \ 114 smtp_server_recipient_add_hook((_rcpt), (_type) - \ 115 CALLBACK_TYPECHECK(_func, void (*)( \ 116 struct smtp_server_recipient *, typeof(_context))), \ 117 (smtp_server_rcpt_func_t *)(_func), (_context)) 118 void smtp_server_recipient_remove_hook( 119 struct smtp_server_recipient *rcpt, 120 enum smtp_server_recipient_hook_type type, 121 smtp_server_rcpt_func_t *func); 122 #define smtp_server_recipient_remove_hook(_rcpt, _type, _func) \ 123 smtp_server_recipient_remove_hook((_rcpt), (_type), \ 124 (smtp_server_rcpt_func_t *)(_func)); 125 126 /* 127 * Transaction 128 */ 129 130 enum smtp_server_trace_rcpt_to_address { 131 /* Don't add recipient address to trace header. */ 132 SMTP_SERVER_TRACE_RCPT_TO_ADDRESS_NONE, 133 /* Add final recipient address to trace header. */ 134 SMTP_SERVER_TRACE_RCPT_TO_ADDRESS_FINAL, 135 /* Add original recipient address to trace header. */ 136 SMTP_SERVER_TRACE_RCPT_TO_ADDRESS_ORIGINAL, 137 }; 138 139 enum smtp_server_transaction_flags { 140 SMTP_SERVER_TRANSACTION_FLAG_REPLY_PER_RCPT = BIT(0), 141 }; 142 143 struct smtp_server_transaction { 144 pool_t pool; 145 struct smtp_server_connection *conn; 146 struct event *event; 147 const char *id; 148 struct timeval timestamp; 149 150 enum smtp_server_transaction_flags flags; 151 152 struct smtp_address *mail_from; 153 struct smtp_params_mail params; 154 ARRAY_TYPE(smtp_server_recipient) rcpt_to; 155 156 /* The associated DATA command. This is NULL until the last DATA/BDAT 157 command is issued. 158 */ 159 struct smtp_server_cmd_ctx *cmd; 160 161 void *context; 162 163 bool finished:1; 164 }; 165 166 struct smtp_server_recipient * 167 smtp_server_transaction_find_rcpt_duplicate( 168 struct smtp_server_transaction *trans, 169 struct smtp_server_recipient *rcpt); 170 171 void smtp_server_transaction_fail_data(struct smtp_server_transaction *trans, 172 struct smtp_server_cmd_ctx *data_cmd, 173 unsigned int status, 174 const char *enh_code, 175 const char *fmt, va_list args) 176 ATTR_FORMAT(5, 0); 177 178 void smtp_server_transaction_write_trace_record( 179 string_t *str, struct smtp_server_transaction *trans, 180 enum smtp_server_trace_rcpt_to_address rcpt_to_address); 181 182 /* 183 * Callbacks 184 */ 185 186 struct smtp_server_cmd_helo { 187 struct smtp_server_helo_data helo; 188 189 bool first:1; /* This is the first */ 190 bool changed:1; /* This EHLO/HELO/LHLO is the first or different 191 from a previous one */ 192 }; 193 194 struct smtp_server_cmd_mail { 195 struct smtp_address *path; 196 struct smtp_params_mail params; 197 198 struct timeval timestamp; 199 200 enum smtp_server_transaction_flags flags; 201 }; 202 203 struct smtp_server_cmd_auth { 204 const char *sasl_mech; 205 const char *initial_response; 206 }; 207 208 struct smtp_server_callbacks { 209 /* Command callbacks: 210 211 These are used to override/implement the behavior of the various core 212 SMTP commands. Commands are handled asynchronously, which means that 213 the command is not necessarily finished when the callback ends. A 214 command is finished either when 1 is returned or a reply is submitted 215 for it. When a callback returns 0, the command implementation is 216 waiting for an external event and when it returns -1 an error 217 occurred. When 1 is returned, a default success reply is set if no 218 reply was submitted. Not submitting an error reply when -1 is 219 returned causes an assert fail. Except for RCPT and DATA, all these 220 callbacks are optional to implement; appropriate default behavior is 221 provided. 222 223 The SMTP server API takes care of transaction state checking. 224 However, until all previous commands are handled, a transaction 225 command cannot rely on the transaction state being final. Use 226 cmd->hook_next to get notified when all previous commands are 227 finished and the current command is next in line to reply. 228 229 If the implementation does not need asynchronous behavior, set 230 max_pipelined_commands=1 and don't return 0 from any command handler. 231 */ 232 233 /* HELO/EHLO/LHLO */ 234 int (*conn_cmd_helo)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, 235 struct smtp_server_cmd_helo *data); 236 /* STARTTLS */ 237 int (*conn_cmd_starttls)(void *conn_ctx, 238 struct smtp_server_cmd_ctx *cmd); 239 /* AUTH */ 240 int (*conn_cmd_auth)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, 241 struct smtp_server_cmd_auth *data); 242 int (*conn_cmd_auth_continue)(void *conn_ctx, 243 struct smtp_server_cmd_ctx *cmd, 244 const char *response); 245 /* MAIL */ 246 int (*conn_cmd_mail)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, 247 struct smtp_server_cmd_mail *data); 248 /* RCPT */ 249 int (*conn_cmd_rcpt)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, 250 struct smtp_server_recipient *rcpt); 251 /* RSET */ 252 int (*conn_cmd_rset)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd); 253 /* DATA */ 254 int (*conn_cmd_data_begin)(void *conn_ctx, 255 struct smtp_server_cmd_ctx *cmd, 256 struct smtp_server_transaction *trans, 257 struct istream *data_input); 258 int (*conn_cmd_data_continue)(void *conn_ctx, 259 struct smtp_server_cmd_ctx *cmd, 260 struct smtp_server_transaction *trans); 261 /* VRFY */ 262 int (*conn_cmd_vrfy)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, 263 const char *param); 264 /* NOOP */ 265 int (*conn_cmd_noop)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd); 266 /* QUIT */ 267 int (*conn_cmd_quit)(void *conn_ctx, struct smtp_server_cmd_ctx *cmd); 268 /* XCLIENT */ 269 void (*conn_cmd_xclient)(void *conn_ctx, 270 struct smtp_server_cmd_ctx *cmd, 271 struct smtp_proxy_data *data); 272 273 /* Command input callbacks: 274 275 These can be used to do stuff before and after a pipelined group of 276 commands is read. 277 */ 278 void (*conn_cmd_input_pre)(void *context); 279 void (*conn_cmd_input_post)(void *context); 280 281 /* Transaction events */ 282 void (*conn_trans_start)(void *context, 283 struct smtp_server_transaction *trans); 284 void (*conn_trans_free)(void *context, 285 struct smtp_server_transaction *trans); 286 287 /* Protocol state events */ 288 void (*conn_state_changed)(void *context, 289 enum smtp_server_state new_state, 290 const char *new_args) ATTR_NULL(3); 291 292 /* Proxy data */ 293 void (*conn_proxy_data_updated)(void *conn_ctx, 294 const struct smtp_proxy_data *data); 295 296 /* Connection */ 297 int (*conn_start_tls)(void *conn_ctx, 298 struct istream **input, struct ostream **output); 299 /* Connection is disconnected. This is always called before 300 conn_free(). */ 301 void (*conn_disconnect)(void *context, const char *reason); 302 /* The last reference to connection is dropped, causing the connection 303 to be freed. */ 304 void (*conn_free)(void *context); 305 306 /* Security */ 307 bool (*conn_is_trusted)(void *context); 308 }; 309 310 /* 311 * Server 312 */ 313 314 enum smtp_server_workarounds { 315 SMTP_SERVER_WORKAROUND_WHITESPACE_BEFORE_PATH = BIT(0), 316 SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH = BIT(1) 317 }; 318 319 struct smtp_server_settings { 320 /* The protocol we are serving */ 321 enum smtp_protocol protocol; 322 /* Standard capabilities supported by the server */ 323 enum smtp_capability capabilities; 324 /* Enabled workarounds for client protocol deviations */ 325 enum smtp_server_workarounds workarounds; 326 327 /* Our hostname as presented to the client */ 328 const char *hostname; 329 /* The message sent in the SMTP server greeting */ 330 const char *login_greeting; 331 /* The directory that - if it exists and is accessible - is used to 332 write raw protocol logs for debugging */ 333 const char *rawlog_dir; 334 335 /* SSL settings; if NULL, master_service_ssl_init() is used instead */ 336 const struct ssl_iostream_settings *ssl; 337 338 /* The maximum time in milliseconds a client is allowed to be idle 339 before it is disconnected. */ 340 unsigned int max_client_idle_time_msecs; 341 342 /* Maximum number of commands in pipeline per connection (default = 1) 343 */ 344 unsigned int max_pipelined_commands; 345 346 /* Maximum number of sequential bad commands */ 347 unsigned int max_bad_commands; 348 349 /* Maximum number of recipients in a transaction 350 (0 means unlimited, which is the default) */ 351 unsigned int max_recipients; 352 353 /* Command limits */ 354 struct smtp_command_limits command_limits; 355 356 /* Message size limit */ 357 uoff_t max_message_size; 358 359 /* Accept these additional custom MAIL parameters */ 360 const char *const *mail_param_extensions; 361 /* Accept these additional custom RCPT parameters */ 362 const char *const *rcpt_param_extensions; 363 /* Accept these additional custom XCLIENT fields */ 364 const char *const *xclient_extensions; 365 366 /* The kernel send/receive buffer sizes used for the connection sockets. 367 Configuring this is mainly useful for the test suite. The kernel 368 defaults are used when these settings are 0. */ 369 size_t socket_send_buffer_size; 370 size_t socket_recv_buffer_size; 371 372 /* Event to use for the smtp server. */ 373 struct event *event_parent; 374 375 /* Enable logging debug messages */ 376 bool debug:1; 377 /* Authentication is not required for this service */ 378 bool auth_optional:1; 379 /* TLS security is required for this service */ 380 bool tls_required:1; 381 /* The path provided to the MAIL command does not need to be valid. A 382 completely invalid path will parse as <>. Paths that can still be 383 fixed by splitting it on the last `@' yielding a usable localpart and 384 domain, will be parsed as such. There are limits though; when the 385 path is badly delimited or contains control characters, the MAIL 386 command will still fail. The unparsed broken address will be 387 available in the `raw' field of struct smtp_address for logging etc. 388 */ 389 bool mail_path_allow_broken:1; 390 /* The path provided to the RCPT command does not need to have the 391 domain part. */ 392 bool rcpt_domain_optional:1; 393 /* Don't include "(state=%s)" in the disconnection reason string. */ 394 bool no_state_in_reason:1; 395 }; 396 397 struct smtp_server_stats { 398 unsigned int command_count, reply_count; 399 uoff_t input, output; 400 }; 401 402 /* 403 * Server 404 */ 405 406 struct smtp_server *smtp_server_init(const struct smtp_server_settings *set); 407 void smtp_server_deinit(struct smtp_server **_server); 408 409 void smtp_server_switch_ioloop(struct smtp_server *server); 410 411 /* 412 * Connection 413 */ 414 415 /* Create connection. It is still inactive and needs to be started with 416 one of the functions below. */ 417 struct smtp_server_connection * 418 smtp_server_connection_create( 419 struct smtp_server *server, int fd_in, int fd_out, 420 const struct ip_addr *remote_ip, in_port_t remote_port, bool ssl_start, 421 const struct smtp_server_settings *set, 422 const struct smtp_server_callbacks *callbacks, void *context) 423 ATTR_NULL(4, 6, 8); 424 struct smtp_server_connection * 425 smtp_server_connection_create_from_streams( 426 struct smtp_server *server, 427 struct istream *input, struct ostream *output, 428 const struct ip_addr *remote_ip, in_port_t remote_port, 429 const struct smtp_server_settings *set, 430 const struct smtp_server_callbacks *callbacks, void *context) 431 ATTR_NULL(4, 6, 8); 432 433 void smtp_server_connection_ref(struct smtp_server_connection *conn); 434 bool smtp_server_connection_unref(struct smtp_server_connection **_conn); 435 436 /* Initialize the connection with state and data from login service */ 437 void smtp_server_connection_login(struct smtp_server_connection *conn, 438 const char *username, const char *helo, 439 const unsigned char *pdata, 440 unsigned int pdata_len, bool ssl_secured); 441 442 /* Start the connection. Establishes SSL layer immediately if instructed, 443 and sends the greeting once the connection is ready for commands. */ 444 void smtp_server_connection_start(struct smtp_server_connection *conn); 445 /* Start the connection, but only establish SSL layer and send greeting; 446 handling command input is held off until smtp_server_connection_resume() is 447 called. */ 448 void smtp_server_connection_start_pending(struct smtp_server_connection *conn); 449 /* Abort the connection prematurely (before it is started). */ 450 void smtp_server_connection_abort(struct smtp_server_connection **_conn, 451 unsigned int status, const char *enh_code, 452 const char *reason); 453 454 /* Halt connection command input and idle timeout entirely. */ 455 void smtp_server_connection_halt(struct smtp_server_connection *conn); 456 /* Resume connection command input and idle timeout. */ 457 void smtp_server_connection_resume(struct smtp_server_connection *conn); 458 459 void smtp_server_connection_input_lock(struct smtp_server_connection *conn); 460 void smtp_server_connection_input_unlock(struct smtp_server_connection *conn); 461 462 void smtp_server_connection_set_streams(struct smtp_server_connection *conn, 463 struct istream *input, 464 struct ostream *output); 465 void smtp_server_connection_set_ssl_streams(struct smtp_server_connection *conn, 466 struct istream *input, 467 struct ostream *output); 468 469 void smtp_server_connection_close(struct smtp_server_connection **_conn, 470 const char *reason) ATTR_NULL(2); 471 void smtp_server_connection_terminate(struct smtp_server_connection **_conn, 472 const char *enh_code, const char *reason) 473 ATTR_NULL(3); 474 475 bool smtp_server_connection_data_check_state(struct smtp_server_cmd_ctx *cmd); 476 void smtp_server_connection_data_chunk_init(struct smtp_server_cmd_ctx *cmd); 477 int smtp_server_connection_data_chunk_add(struct smtp_server_cmd_ctx *cmd, 478 struct istream *chunk, 479 uoff_t chunk_size, bool chunk_last, 480 bool client_input); 481 482 enum smtp_server_state 483 smtp_server_connection_get_state(struct smtp_server_connection *conn, 484 const char **args_r) ATTR_NULL(2); 485 const char * 486 smtp_server_connection_get_security_string(struct smtp_server_connection *conn); 487 struct smtp_server_transaction * 488 smtp_server_connection_get_transaction(struct smtp_server_connection *conn); 489 const char * 490 smtp_server_connection_get_transaction_id(struct smtp_server_connection *conn); 491 const struct smtp_server_stats * 492 smtp_server_connection_get_stats(struct smtp_server_connection *conn); 493 void *smtp_server_connection_get_context(struct smtp_server_connection *conn) 494 ATTR_PURE; 495 enum smtp_protocol 496 smtp_server_connection_get_protocol(struct smtp_server_connection *conn) 497 ATTR_PURE; 498 const char * 499 smtp_server_connection_get_protocol_name(struct smtp_server_connection *conn); 500 struct smtp_server_helo_data * 501 smtp_server_connection_get_helo_data(struct smtp_server_connection *conn); 502 503 void smtp_server_connection_get_proxy_data(struct smtp_server_connection *conn, 504 struct smtp_proxy_data *proxy_data); 505 void smtp_server_connection_set_proxy_data( 506 struct smtp_server_connection *conn, 507 const struct smtp_proxy_data *proxy_data); 508 509 void smtp_server_connection_set_capabilities( 510 struct smtp_server_connection *conn, enum smtp_capability capabilities); 511 void smtp_server_connection_add_extra_capability( 512 struct smtp_server_connection *conn, 513 const struct smtp_capability_extra *cap); 514 515 void smtp_server_connection_register_mail_param( 516 struct smtp_server_connection *conn, const char *param); 517 void smtp_server_connection_register_rcpt_param( 518 struct smtp_server_connection *conn, const char *param); 519 520 bool smtp_server_connection_is_ssl_secured(struct smtp_server_connection *conn); 521 bool smtp_server_connection_is_trusted(struct smtp_server_connection *conn); 522 523 /* 524 * Command 525 */ 526 527 enum smtp_server_command_flags { 528 SMTP_SERVER_CMD_FLAG_PRETLS = BIT(0), 529 SMTP_SERVER_CMD_FLAG_PREAUTH = BIT(1) 530 }; 531 532 enum smtp_server_command_hook_type { 533 /* next: command is next to reply but has not submittted all replies 534 yet. */ 535 SMTP_SERVER_COMMAND_HOOK_NEXT, 536 /* replied_one: command has submitted one reply. */ 537 SMTP_SERVER_COMMAND_HOOK_REPLIED_ONE, 538 /* replied: command has submitted all replies. */ 539 SMTP_SERVER_COMMAND_HOOK_REPLIED, 540 /* completed: server is about to send last replies for this command. */ 541 SMTP_SERVER_COMMAND_HOOK_COMPLETED, 542 /* destroy: command is about to be destroyed. */ 543 SMTP_SERVER_COMMAND_HOOK_DESTROY 544 }; 545 546 /* Commands are handled asynchronously, which means that the command is not 547 necessary finished when the start function ends. A command is finished 548 when a reply is submitted for it. Several command hooks are available to 549 get notified about events in the command's life cycle. 550 */ 551 552 typedef void smtp_server_cmd_input_callback_t(struct smtp_server_cmd_ctx *cmd); 553 typedef void smtp_server_cmd_start_func_t(struct smtp_server_cmd_ctx *cmd, 554 const char *params); 555 typedef void smtp_server_cmd_func_t(struct smtp_server_cmd_ctx *cmd, 556 void *context); 557 558 struct smtp_server_cmd_ctx { 559 pool_t pool; 560 struct event *event; 561 const char *name; 562 563 struct smtp_server *server; 564 struct smtp_server_connection *conn; 565 struct smtp_server_command *cmd; 566 }; 567 568 /* Hooks: 569 570 */ 571 572 void smtp_server_command_add_hook(struct smtp_server_command *cmd, 573 enum smtp_server_command_hook_type type, 574 smtp_server_cmd_func_t func, 575 void *context); 576 #define smtp_server_command_add_hook(_cmd, _type, _func, _context) \ 577 smtp_server_command_add_hook((_cmd), (_type) - \ 578 CALLBACK_TYPECHECK(_func, void (*)( \ 579 struct smtp_server_cmd_ctx *, typeof(_context))), \ 580 (smtp_server_cmd_func_t *)(_func), (_context)) 581 void smtp_server_command_remove_hook(struct smtp_server_command *cmd, 582 enum smtp_server_command_hook_type type, 583 smtp_server_cmd_func_t *func); 584 #define smtp_server_command_remove_hook(_cmd, _type, _func) \ 585 smtp_server_command_remove_hook((_cmd), (_type), \ 586 (smtp_server_cmd_func_t *)(_func)); 587 588 /* The core SMTP commands are pre-registered. Special connection callbacks are 589 provided for the core SMTP commands. Only use this command registration API 590 when custom/extension SMTP commands are required. 591 */ 592 void smtp_server_command_register(struct smtp_server *server, const char *name, 593 smtp_server_cmd_start_func_t *func, 594 enum smtp_server_command_flags); 595 void smtp_server_command_unregister(struct smtp_server *server, 596 const char *name); 597 598 void smtp_server_command_set_reply_count(struct smtp_server_command *cmd, 599 unsigned int count); 600 unsigned int 601 smtp_server_command_get_reply_count(struct smtp_server_command *cmd); 602 603 void smtp_server_command_fail(struct smtp_server_command *cmd, 604 unsigned int status, const char *enh_code, 605 const char *fmt, ...) ATTR_FORMAT(4, 5); 606 607 struct smtp_server_reply * 608 smtp_server_command_get_reply(struct smtp_server_command *cmd, 609 unsigned int idx); 610 bool smtp_server_command_reply_status_equals(struct smtp_server_command *cmd, 611 unsigned int status); 612 bool smtp_server_command_is_replied(struct smtp_server_command *cmd); 613 bool smtp_server_command_reply_is_forwarded(struct smtp_server_command *cmd); 614 bool smtp_server_command_replied_success(struct smtp_server_command *cmd); 615 616 void smtp_server_command_input_lock(struct smtp_server_cmd_ctx *cmd); 617 void smtp_server_command_input_unlock(struct smtp_server_cmd_ctx *cmd); 618 void smtp_server_command_input_capture( 619 struct smtp_server_cmd_ctx *cmd, 620 smtp_server_cmd_input_callback_t *callback); 621 622 /* EHLO */ 623 624 struct smtp_server_reply * 625 smtp_server_cmd_ehlo_reply_create(struct smtp_server_cmd_ctx *cmd); 626 void smtp_server_cmd_ehlo_reply_default(struct smtp_server_cmd_ctx *cmd); 627 628 /* AUTH */ 629 630 void smtp_server_cmd_auth_send_challenge(struct smtp_server_cmd_ctx *cmd, 631 const char *challenge); 632 void smtp_server_cmd_auth_success(struct smtp_server_cmd_ctx *cmd, 633 const char *username, const char *success_msg) 634 ATTR_NULL(3); 635 636 /* MAIL */ 637 638 void smtp_server_cmd_mail_reply_success(struct smtp_server_cmd_ctx *cmd); 639 640 /* RCPT */ 641 642 bool smtp_server_command_is_rcpt(struct smtp_server_cmd_ctx *cmd); 643 void smtp_server_cmd_rcpt_reply_success(struct smtp_server_cmd_ctx *cmd); 644 645 /* RSET */ 646 647 void smtp_server_cmd_rset_reply_success(struct smtp_server_cmd_ctx *cmd); 648 649 /* DATA */ 650 651 bool smtp_server_cmd_data_check_size(struct smtp_server_cmd_ctx *cmd); 652 653 /* VRFY */ 654 655 void smtp_server_cmd_vrfy_reply_default(struct smtp_server_cmd_ctx *cmd); 656 657 /* NOOP */ 658 659 void smtp_server_cmd_noop_reply_success(struct smtp_server_cmd_ctx *cmd); 660 661 /* 662 * Reply 663 */ 664 665 struct smtp_server_reply * 666 smtp_server_reply_create_index(struct smtp_server_command *cmd, 667 unsigned int index, unsigned int status, 668 const char *enh_code) ATTR_NULL(3); 669 struct smtp_server_reply * 670 smtp_server_reply_create(struct smtp_server_command *cmd, unsigned int status, 671 const char *enh_code) ATTR_NULL(3); 672 struct smtp_server_reply * 673 smtp_server_reply_create_forward(struct smtp_server_command *cmd, 674 unsigned int index, 675 const struct smtp_reply *from); 676 677 void smtp_server_reply_set_status(struct smtp_server_reply *reply, 678 unsigned int status, const char *enh_code) 679 ATTR_NULL(3); 680 unsigned int smtp_server_reply_get_status(struct smtp_server_reply *reply, 681 const char **enh_code_r) ATTR_NULL(3); 682 683 void smtp_server_reply_add_text(struct smtp_server_reply *reply, 684 const char *line); 685 void smtp_server_reply_prepend_text(struct smtp_server_reply *reply, 686 const char *text_prefix); 687 void smtp_server_reply_replace_path(struct smtp_server_reply *reply, 688 struct smtp_address *path, bool add); 689 690 void smtp_server_reply_submit(struct smtp_server_reply *reply); 691 void smtp_server_reply_submit_duplicate(struct smtp_server_cmd_ctx *_cmd, 692 unsigned int index, 693 unsigned int from_index); 694 695 /* Submit a reply for the command at the specified index (> 0 only if more than 696 a single reply is expected). */ 697 void smtp_server_reply_indexv(struct smtp_server_cmd_ctx *_cmd, 698 unsigned int index, unsigned int status, 699 const char *enh_code, 700 const char *fmt, va_list args) ATTR_FORMAT(5, 0); 701 void smtp_server_reply_index(struct smtp_server_cmd_ctx *_cmd, 702 unsigned int index, unsigned int status, 703 const char *enh_code, const char *fmt, ...) 704 ATTR_FORMAT(5, 6); 705 /* Submit the reply for the specified command. */ 706 void smtp_server_reply(struct smtp_server_cmd_ctx *_cmd, unsigned int status, 707 const char *enh_code, const char *fmt, ...) 708 ATTR_FORMAT(4, 5); 709 /* Forward a reply for the command at the specified index (> 0 only if more 710 than a single reply is expected). */ 711 void smtp_server_reply_index_forward(struct smtp_server_cmd_ctx *cmd, 712 unsigned int index, 713 const struct smtp_reply *from); 714 /* Forward the reply for the specified command. */ 715 void smtp_server_reply_forward(struct smtp_server_cmd_ctx *cmd, 716 const struct smtp_reply *from); 717 /* Submit the same message for all expected replies for this command. */ 718 void smtp_server_reply_all(struct smtp_server_cmd_ctx *_cmd, 719 unsigned int status, const char *enh_code, 720 const char *fmt, ...) ATTR_FORMAT(4, 5); 721 /* Submit and send the same message for all expected replies for this command 722 early; i.e., no matter whether all command data is received completely. */ 723 void smtp_server_reply_early(struct smtp_server_cmd_ctx *_cmd, 724 unsigned int status, const char *enh_code, 725 const char *fmt, ...) ATTR_FORMAT(4, 5); 726 727 /* Reply the command with a 221 bye message */ 728 void smtp_server_reply_quit(struct smtp_server_cmd_ctx *_cmd); 729 730 bool smtp_server_reply_is_success(const struct smtp_server_reply *reply); 731 732 /* EHLO */ 733 734 struct smtp_server_reply * 735 smtp_server_reply_create_ehlo(struct smtp_server_command *cmd); 736 void smtp_server_reply_ehlo_add(struct smtp_server_reply *reply, 737 const char *keyword); 738 void smtp_server_reply_ehlo_add_param(struct smtp_server_reply *reply, 739 const char *keyword, 740 const char *param_fmt, ...) 741 ATTR_FORMAT(3, 4); 742 void smtp_server_reply_ehlo_add_params(struct smtp_server_reply *reply, 743 const char *keyword, 744 const char *const *params) ATTR_NULL(3); 745 746 void smtp_server_reply_ehlo_add_8bitmime(struct smtp_server_reply *reply); 747 void smtp_server_reply_ehlo_add_binarymime(struct smtp_server_reply *reply); 748 void smtp_server_reply_ehlo_add_chunking(struct smtp_server_reply *reply); 749 void smtp_server_reply_ehlo_add_dsn(struct smtp_server_reply *reply); 750 void smtp_server_reply_ehlo_add_enhancedstatuscodes( 751 struct smtp_server_reply *reply); 752 void smtp_server_reply_ehlo_add_pipelining(struct smtp_server_reply *reply); 753 void smtp_server_reply_ehlo_add_size(struct smtp_server_reply *reply); 754 void smtp_server_reply_ehlo_add_starttls(struct smtp_server_reply *reply); 755 void smtp_server_reply_ehlo_add_vrfy(struct smtp_server_reply *reply); 756 void smtp_server_reply_ehlo_add_xclient(struct smtp_server_reply *reply); 757 758 #endif 759