#include "istream.h"
#include "istream-concat.h"
#include "ostream.h"
-#include "safe-mkstemp.h"
-#include "index/raw/raw-storage.h"
+#include "iostream-temp.h"
#include "master-service.h"
#include "settings-parser.h"
#include "lda-settings.h"
+#include "mail-user.h"
#include "lmtp-settings.h"
#include "smtp-address.h"
#include "smtp-server.h"
* DATA command
*/
-static struct istream *cmd_data_get_input(struct client *client)
-{
- struct client_state *state = &client->state;
- struct istream *input;
-
- if (state->mail_data_output != NULL) {
- o_stream_unref(&state->mail_data_output);
- input = i_stream_create_fd(state->mail_data_fd,
- MAIL_READ_FULL_BLOCK_SIZE);
- i_stream_set_init_buffer_size(input,
- MAIL_READ_FULL_BLOCK_SIZE);
- } else {
- input = i_stream_create_from_data(state->mail_data->data,
- state->mail_data->used);
- }
- return input;
-}
-
static void
cmd_data_create_added_headers(struct client *client,
struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
client->state.added_headers_local + proxy_offset;
}
-static int
-cmd_data_input_add_file(struct client *client,
- const unsigned char *data, size_t size)
-{
- struct client_state *state = &client->state;
- string_t *path;
- int fd;
-
- if (state->mail_data_output != NULL) {
- /* continue writing to file */
- if (o_stream_send(state->mail_data_output,
- data, size) != (ssize_t)size)
- return -1;
- return 0;
- }
-
- /* move everything to a temporary file. */
- path = t_str_new(256);
- mail_user_set_get_temp_prefix(path, client->raw_mail_user->set);
- fd = safe_mkstemp_hostpid(path, 0600, (uid_t)-1, (gid_t)-1);
- if (fd == -1) {
- i_error("Temp file creation to %s failed: %m", str_c(path));
- return -1;
- }
-
- /* we just want the fd, unlink it */
- if (i_unlink(str_c(path)) < 0) {
- /* shouldn't happen.. */
- i_close_fd(&fd);
- return -1;
- }
-
- state->mail_data_fd = fd;
- state->mail_data_output = o_stream_create_fd_file(fd, 0, FALSE);
- o_stream_set_name(state->mail_data_output, str_c(path));
- o_stream_cork(state->mail_data_output);
-
- o_stream_nsend(state->mail_data_output,
- state->mail_data->data, state->mail_data->used);
- o_stream_nsend(client->state.mail_data_output, data, size);
- if (o_stream_flush(client->state.mail_data_output) < 0) {
- i_error("write(%s) failed: %s", str_c(path),
- o_stream_get_error(client->state.mail_data_output));
- return -1;
- }
- return 0;
-}
-
-static int
-cmd_data_input_add(struct client *client,
- const unsigned char *data, size_t size)
-{
- if (client->state.mail_data->used + size <=
- CLIENT_MAIL_DATA_MAX_INMEMORY_SIZE &&
- client->state.mail_data_output == NULL) {
- buffer_append(client->state.mail_data, data, size);
- return 0;
- } else {
- return cmd_data_input_add_file(client, data, size);
- }
-}
-
static int
cmd_data_finish(struct client *client,
struct smtp_server_cmd_ctx *cmd,
client->state.data_end_timeval = ioloop_timeval;
/* finish the message */
- input_msg = cmd_data_get_input(client);
+ input_msg = iostream_temp_finish(&state->mail_data_output,
+ IO_BLOCK_SIZE);
/* formulate prepended headers for both local and proxy delivery */
cmd_data_create_added_headers(client, cmd, trans);
struct smtp_server_transaction *trans)
{
struct client *client = (struct client *)conn_ctx;
+ struct client_state *state = &client->state;
struct istream *data_input = (struct istream *)trans->context;
const unsigned char *data;
size_t size;
ssize_t ret;
- i_assert(client->state.mail_data_output != NULL);
+ i_assert(state->mail_data_output != NULL);
while ((ret = i_stream_read(data_input)) > 0 || ret == -2) {
data = i_stream_get_data(data_input, &size);
- if (cmd_data_input_add(client, data, size) < 0) {
+ if (o_stream_send(state->mail_data_output,
+ data, size) != (ssize_t)size) {
+ i_error("write(%s) failed: %s",
+ o_stream_get_name(state->mail_data_output),
+ o_stream_get_error(state->mail_data_output));
smtp_server_reply(cmd, 451, "4.3.0",
"Temporary internal failure");
return -1;
struct istream *data_input)
{
struct client *client = (struct client *)conn_ctx;
+ string_t *path;
+
+ i_assert(client->state.mail_data_output == NULL);
- i_assert(client->state.mail_data == NULL);
- client->state.mail_data = buffer_create_dynamic(default_pool, 1024*64);
+ path = t_str_new(256);
+ mail_user_set_get_temp_prefix(path, client->raw_mail_user->set);
+ client->state.mail_data_output =
+ iostream_temp_create_named(str_c(path), 0, "(lmtp data)");
cmd->context = (void*)client;