smtp-server-cmd-mail.c revision 8c2d916c7cd0c7c85fba4eb41bcc031d1424cb2d
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "lib.h"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#include "array.h"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include "ioloop.h"
6c1a5346febccc35b8d5eb4f26e62748ca640529Timo Sirainen#include "smtp-parser.h"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include "smtp-syntax.h"
d172c364637944d667aa98eb5de0d4a3a97ab92aTimo Sirainen#include "smtp-address.h"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen#include "smtp-server-private.h"
7370fb9ff75b674f99059adf24502ee9ae7a47bcTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen/* MAIL command */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainenstatic bool
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainencmd_mail_check_state(struct smtp_server_cmd_ctx *cmd)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct smtp_server_command *command = cmd->cmd;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (conn->state.trans != NULL) {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (command->hook_replied != NULL) {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen conn->state.pending_mail_cmds--;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen command->hook_replied = NULL;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen }
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen smtp_server_reply(cmd, 503, "5.5.0", "MAIL already given");
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return FALSE;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return TRUE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void cmd_mail_replied(struct smtp_server_cmd_ctx *cmd)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct smtp_server_command *command = cmd->cmd;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct smtp_server_cmd_mail *data =
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen (struct smtp_server_cmd_mail *)command->data;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen conn->state.pending_mail_cmds--;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_assert(smtp_server_command_is_replied(command));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (!smtp_server_command_replied_success(command)) {
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen /* failure; substitute our own error if predictable */
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen (void)cmd_mail_check_state(cmd);
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen return;
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen }
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen /* success */
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen conn->state.trans = smtp_server_transaction_create(conn,
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen data->path, &data->params, &data->timestamp);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void cmd_mail_recheck(struct smtp_server_cmd_ctx *cmd)
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen{
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen /* all preceeding commands have finished and now the transaction state
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen is clear. This provides the opportunity to re-check the transaction
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen state */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (!cmd_mail_check_state(cmd))
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen /* Advance state */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_MAIL_FROM);
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen}
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainenvoid smtp_server_cmd_mail(struct smtp_server_cmd_ctx *cmd,
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen const char *params)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct smtp_server_connection *conn = cmd->conn;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen const struct smtp_server_settings *set = &conn->set;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen enum smtp_capability caps = set->capabilities;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen const struct smtp_server_callbacks *callbacks = conn->callbacks;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct smtp_server_command *command = cmd->cmd;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct smtp_server_cmd_mail *mail_data;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen struct smtp_address *path;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen enum smtp_param_parse_error pperror;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen const char *error;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen int ret;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* mail = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen Reverse-path = Path / "<>"
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* check transaction state as far as possible */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (!cmd_mail_check_state(cmd))
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen /* Reverse-path */
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (params == NULL || strncasecmp(params, "FROM:", 5) != 0) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4", "Invalid parameters");
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen }
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen if (smtp_address_parse_path_full(pool_datastack_create(), params + 5,
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY,
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen &path, &error, &params) < 0) {
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen smtp_server_reply(cmd, 501, "5.5.4", "Invalid FROM: %s", error);
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen return;
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen }
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen if (*params == ' ')
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen params++;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else if (*params != '\0') {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4",
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen "Invalid FROM: Invalid character in path");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen if (conn->pending_helo == NULL && conn->helo.domain == NULL) {
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen /* no EHLO executed post-login, use pre-login value instead */
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen conn->helo_domain = conn->helo_login;
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen conn->helo_login = NULL;
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen conn->helo.domain = conn->helo_domain;
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen }
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen
c0225f7f6b43d34dc58c17d3304f0fd60ab89894Timo Sirainen mail_data = p_new(cmd->pool, struct smtp_server_cmd_mail, 1);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* [SP Mail-parameters] */
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen if (smtp_params_mail_parse(cmd->pool, params, caps,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen set->param_extensions, &mail_data->params,
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen &pperror, &error) < 0) {
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen switch (pperror) {
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen case SMTP_PARAM_PARSE_ERROR_BAD_SYNTAX:
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen smtp_server_reply(cmd, 501, "5.5.4", "%s", error);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen break;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case SMTP_PARAM_PARSE_ERROR_NOT_SUPPORTED:
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen smtp_server_reply(cmd, 555, "5.5.4", "%s", error);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen break;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen default:
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen i_unreached();
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen return;
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen }
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen mail_data->path = smtp_address_clone(cmd->pool, path);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mail_data->timestamp = ioloop_timeval;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen command->data = mail_data;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen command->hook_next = cmd_mail_recheck;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen command->hook_replied = cmd_mail_replied;
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_MAIL_FROM);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen conn->state.pending_mail_cmds++;
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen smtp_server_command_ref(command);
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen if (callbacks != NULL && callbacks->conn_cmd_mail != NULL) {
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen /* specific implementation of MAIL command */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if ((ret=callbacks->conn_cmd_mail(conn->context,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen cmd, mail_data)) <= 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen i_assert(ret == 0 ||
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen smtp_server_command_is_replied(command));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* command is waiting for external event or it failed */
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen smtp_server_command_unref(&command);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen }
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen }
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen if (!smtp_server_command_is_replied(command)) {
8dccbdbe38f0e9342caf752d9d980a64125fa4d1Timo Sirainen /* set generic MAIL success reply if none is provided */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen smtp_server_reply(cmd, 250, "2.1.0", "OK");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen smtp_server_command_unref(&command);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen