add MIME headers to get rewrite to append footer
[ghsmtp.git] / Session.hpp
blob37269505a762f25382637c96288837f822afb98c
1 #ifndef SESSION_DOT_HPP
2 #define SESSION_DOT_HPP
4 #include <random>
5 #include <string>
6 #include <string_view>
7 #include <unordered_map>
8 #include <vector>
10 #include "CDB.hpp"
11 #include "DNS-fcrdns.hpp"
12 #include "Domain.hpp"
13 #include "Mailbox.hpp"
14 #include "Message.hpp"
15 #include "SPF.hpp"
16 #include "Send.hpp"
17 #include "Sock.hpp"
18 #include "TLD.hpp"
20 namespace Config {
21 constexpr size_t kibibyte = 1024;
22 constexpr size_t mebibyte = kibibyte * kibibyte;
23 constexpr size_t max_msg_size_initial = 15 * mebibyte;
24 constexpr size_t max_msg_size_bro = 150 * mebibyte;
25 } // namespace Config
27 class Session {
28 public:
29 using parameters_t = std::unordered_map<std::string, std::string>;
31 Session(Session const&) = delete;
32 Session& operator=(Session const&) = delete;
34 explicit Session(
35 fs::path config_path,
36 std::function<void(void)> read_hook = []() {},
37 int fd_in = STDIN_FILENO,
38 int fd_out = STDOUT_FILENO);
40 void greeting();
41 void ehlo(std::string_view client_identity) { lo_("EHLO", client_identity); }
42 void helo(std::string_view client_identity) { lo_("HELO", client_identity); }
43 void mail_from(Mailbox&& reverse_path, parameters_t const& parameters);
44 void rcpt_to(Mailbox&& forward_path, parameters_t const& parameters);
46 bool msg_new();
47 bool msg_write(char const* s, std::streamsize count);
49 bool data_start();
50 void data_done();
51 void data_size_error();
52 void data_error();
54 bool bdat_start(size_t n);
55 void bdat_done(size_t n, bool last);
56 void bdat_size_error();
57 void bdat_seq_error();
58 void bdat_io_error();
60 void rset();
61 void noop(std::string_view str);
62 void vrfy(std::string_view str);
63 void help(std::string_view str);
64 void quit() __attribute__((noreturn));
65 void auth() __attribute__((noreturn));
66 void error(std::string_view log_msg);
67 void cmd_unrecognized(std::string_view log_msg);
68 void bare_lf() __attribute__((noreturn));
70 void max_out() __attribute__((noreturn));
71 void time_out() __attribute__((noreturn));
72 void starttls();
74 bool maxed_out() { return sock_.maxed_out(); }
75 bool timed_out() { return sock_.timed_out(); }
76 std::istream& in() { return sock_.in(); }
78 void flush();
79 void last_in_group_(std::string_view verb);
81 size_t max_msg_size() const { return max_msg_size_; }
82 void max_msg_size(size_t max);
84 void log_stats() { sock_.log_stats(); }
86 enum class SpamStatus : bool { ham, spam };
88 private:
89 friend struct Session_test;
91 std::tuple<SpamStatus, std::string> spam_status_();
93 std::string added_headers_(Message const& msg);
95 std::ostream& out_() { return sock_.out(); }
96 void lo_(char const* verb, std::string_view client_identity);
98 void bad_host_(char const* msg) const __attribute__((noreturn));
100 std::string const& server_id_() const { return server_identity_.ascii(); }
102 void deliver_();
104 // clear per transaction data, preserve per connection data
105 void reset_();
107 bool verify_ip_address_(std::string& error_msg);
108 bool verify_ip_address_dnsbl_(std::string& error_msg);
109 bool verify_client_(Domain const& client_identity, std::string& error_msg);
110 bool verify_recipient_(Mailbox const& recipient);
111 bool verify_sender_(Mailbox const& sender, std::string& error_msg);
112 bool verify_sender_domain_(Domain const& sender, std::string& error_msg);
113 bool verify_sender_domain_uribl_(std::string_view sender,
114 std::string& error_msg);
115 bool verify_sender_spf_(Mailbox const& sender);
116 bool verify_from_params_(parameters_t const& parameters);
117 bool verify_rcpt_params_(parameters_t const& parameters);
119 bool is_forwarding_() const
121 return forward_path_.empty() && !fwd_path_.empty();
124 void exit_() __attribute__((noreturn));
126 private:
127 fs::path config_path_;
128 DNS::Resolver res_;
129 Sock sock_;
131 // forwarding
132 Send send_;
133 std::vector<Mailbox> fwd_path_; // for each "rcpt to"
135 // per connection/session
136 Domain server_identity_; // who we identify as
137 std::vector<Domain> client_fcrdns_; // who they look-up as
138 std::vector<Domain> server_fcrdns_; // who we look-up as
139 std::string client_; // (fcrdns_ [sock_.them_c_str()])
141 // per transaction
142 Domain client_identity_; // from ehlo/helo
143 Mailbox reverse_path_; // "mail from"
144 std::vector<Mailbox> forward_path_; // for each "rcpt to"
145 std::string spf_received_;
146 std::unique_ptr<Message> msg_;
148 TLD tld_db_;
150 std::random_device random_device_;
152 // White and black lists for domains.
153 CDB white_;
154 CDB black_;
155 CDB forward_;
157 // Domains we receive mail for.
158 CDB accept_domains_;
160 size_t max_msg_size_;
162 int n_unrecognized_cmds_{0};
164 SPF::Result spf_result_;
165 Domain spf_sender_domain_;
167 // RFC 5321 section 3.3. Mail Transactions
168 enum class xact_step : int8_t {
169 helo,
170 mail,
171 rcpt,
172 data,
173 bdat, // RFC 3030
174 rset, // must now send RSET
177 // per transaction
178 xact_step state_ = xact_step::helo;
180 bool binarymime_{false};
181 bool extensions_{false};
182 bool smtputf8_{false};
183 bool prdr_{false};
185 // per connection
186 bool fcrdns_whitelisted_{false};
187 bool ip_whitelisted_{false};
190 #endif // SESSION_DOT_HPP