Coverage Report

Created: 2026-10-28 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/testsuite/testsuite-smtp.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "ostream.h"
6
#include "unlink-directory.h"
7
8
#include "sieve-common.h"
9
#include "sieve-error.h"
10
#include "sieve-interpreter.h"
11
12
#include "testsuite-message.h"
13
#include "testsuite-common.h"
14
#include "testsuite-smtp.h"
15
16
#include <unistd.h>
17
#include <fcntl.h>
18
#include <sys/stat.h>
19
#include <sys/types.h>
20
21
struct testsuite_smtp_message {
22
  const struct smtp_address *envelope_from, *envelope_to;
23
  const char *file;
24
};
25
26
static pool_t testsuite_smtp_pool;
27
static const char *testsuite_smtp_tmp;
28
static ARRAY(struct testsuite_smtp_message) testsuite_smtp_messages;
29
30
/*
31
 * Initialize
32
 */
33
34
void testsuite_smtp_init(void)
35
0
{
36
0
  pool_t pool;
37
38
0
  testsuite_smtp_pool = pool =
39
0
    pool_alloconly_create("testsuite_smtp", 8192);
40
41
0
  testsuite_smtp_tmp = p_strconcat(
42
0
    pool, testsuite_tmp_dir_get(), "/smtp", NULL);
43
44
0
  if (mkdir(testsuite_smtp_tmp, 0700) < 0) {
45
0
    i_fatal("failed to create temporary directory '%s': %m.",
46
0
      testsuite_smtp_tmp);
47
0
  }
48
49
0
  p_array_init(&testsuite_smtp_messages, pool, 16);
50
0
}
51
52
void testsuite_smtp_deinit(void)
53
0
{
54
0
  const char *error;
55
56
0
  if (unlink_directory(testsuite_smtp_tmp, UNLINK_DIRECTORY_FLAG_RMDIR,
57
0
           &error) < 0) {
58
0
    i_warning("failed to remove temporary directory '%s': %s.",
59
0
      testsuite_smtp_tmp, error);
60
0
  }
61
0
  pool_unref(&testsuite_smtp_pool);
62
0
}
63
64
void testsuite_smtp_reset(void)
65
0
{
66
0
  testsuite_smtp_deinit();
67
0
  testsuite_smtp_init();
68
0
}
69
70
/*
71
 * Simulated SMTP out
72
 */
73
74
struct testsuite_smtp {
75
  char *msg_file;
76
  struct smtp_address *mail_from;
77
  struct ostream *output;
78
};
79
80
void *testsuite_smtp_start(const struct sieve_script_env *senv ATTR_UNUSED,
81
         const struct smtp_address *mail_from)
82
0
{
83
0
  struct testsuite_smtp *smtp;
84
0
  unsigned int smtp_count = array_count(&testsuite_smtp_messages);
85
0
  int fd;
86
87
0
  smtp = i_new(struct testsuite_smtp, 1);
88
89
0
  smtp->msg_file = i_strdup_printf("%s/%d.eml", testsuite_smtp_tmp,
90
0
           smtp_count);
91
0
  smtp->mail_from = smtp_address_clone(default_pool, mail_from);
92
93
0
  fd = open(smtp->msg_file, O_WRONLY | O_CREAT, 0600);
94
0
  if (fd < 0) {
95
0
    i_fatal("failed create tmp file for SMTP simulation: "
96
0
      "open(%s) failed: %m", smtp->msg_file);
97
0
  }
98
99
0
  smtp->output = o_stream_create_fd_autoclose(&fd, (size_t)-1);
100
101
0
  return smtp;
102
0
}
103
104
void testsuite_smtp_add_rcpt(const struct sieve_script_env *senv ATTR_UNUSED,
105
           void *handle, const struct smtp_address *rcpt_to)
106
0
{
107
0
  struct testsuite_smtp *smtp = (struct testsuite_smtp *)handle;
108
0
  struct testsuite_smtp_message *msg;
109
110
0
  msg = array_append_space(&testsuite_smtp_messages);
111
112
0
  msg->file = p_strdup(testsuite_smtp_pool, smtp->msg_file);
113
0
  msg->envelope_from = smtp_address_clone(testsuite_smtp_pool,
114
0
            smtp->mail_from);
115
0
  msg->envelope_to = smtp_address_clone(testsuite_smtp_pool, rcpt_to);
116
0
}
117
118
struct ostream *
119
testsuite_smtp_send(const struct sieve_script_env *senv ATTR_UNUSED,
120
        void *handle)
121
0
{
122
0
  struct testsuite_smtp *smtp = (struct testsuite_smtp *)handle;
123
124
0
  return smtp->output;
125
0
}
126
127
void testsuite_smtp_abort(const struct sieve_script_env *senv ATTR_UNUSED,
128
        void *handle)
129
0
{
130
0
  struct testsuite_smtp *smtp = (struct testsuite_smtp *)handle;
131
132
0
  o_stream_ignore_last_errors(smtp->output);
133
0
  o_stream_unref(&smtp->output);
134
0
  i_unlink(smtp->msg_file);
135
0
  i_free(smtp->msg_file);
136
0
  i_free(smtp->mail_from);
137
0
  i_free(smtp);
138
0
}
139
140
int testsuite_smtp_finish(const struct sieve_script_env *senv ATTR_UNUSED,
141
        void *handle, const char **error_r ATTR_UNUSED)
142
0
{
143
0
  struct testsuite_smtp *smtp = (struct testsuite_smtp *)handle;
144
0
  int ret = 1;
145
146
0
  if (o_stream_finish(smtp->output) < 0) {
147
0
    i_error("write(%s) failed: %s", smtp->msg_file,
148
0
      o_stream_get_error(smtp->output));
149
0
    ret = -1;
150
0
  }
151
0
  o_stream_unref(&smtp->output);
152
0
  i_free(smtp->msg_file);
153
0
  i_free(smtp->mail_from);
154
0
  i_free(smtp);
155
0
  return ret;
156
0
}
157
158
/*
159
 * Access
160
 */
161
162
bool testsuite_smtp_get(const struct sieve_runtime_env *renv,
163
      unsigned int index)
164
0
{
165
0
  const struct testsuite_smtp_message *smtp_msg;
166
167
0
  if (index >= array_count(&testsuite_smtp_messages))
168
0
    return FALSE;
169
170
0
  smtp_msg = array_idx(&testsuite_smtp_messages, index);
171
172
0
  testsuite_message_set_file(renv, smtp_msg->file);
173
0
  testsuite_envelope_set_sender_address(renv, smtp_msg->envelope_from);
174
0
  testsuite_envelope_set_recipient_address(renv, smtp_msg->envelope_to);
175
0
  return TRUE;
176
0
}