1 #ifndef SMTP_REPLY_H
2 #define SMTP_REPLY_H
3 
4 struct smtp_reply_enhanced_code {
5 	/* x:class, y:subject, z:detail;
6 	   x==0 means no enhanced code present
7 	   x==9 means invalid/missing enhanced code in reply
8 	 */
9 	unsigned int x, y, z;
10 };
11 
12 struct smtp_reply {
13 	unsigned int status;
14 
15 	struct smtp_reply_enhanced_code enhanced_code;
16 
17 	const char *const *text_lines;
18 };
19 
20 #define SMTP_REPLY_ENH_CODE(x, y, z) \
21 	(const struct smtp_reply_enhanced_code){(x), (y), (z)}
22 #define SMTP_REPLY_ENH_CODE_NONE SMTP_REPLY_ENH_CODE(0, 0, 0)
23 
24 static inline bool
smtp_reply_has_enhanced_code(const struct smtp_reply * reply)25 smtp_reply_has_enhanced_code(const struct smtp_reply *reply)
26 {
27 	return reply->enhanced_code.x > 1 && reply->enhanced_code.x < 6;
28 }
29 
30 static inline bool
smtp_reply_is_success(const struct smtp_reply * reply)31 smtp_reply_is_success(const struct smtp_reply *reply)
32 {
33 	return ((reply->status / 100) == 2);
34 }
35 
36 static inline bool
smtp_reply_is_remote(const struct smtp_reply * reply)37 smtp_reply_is_remote(const struct smtp_reply *reply)
38 {
39 	return (reply->status >= 200 && reply->status < 560);
40 }
41 
42 static inline bool
smtp_reply_is_temp_fail(const struct smtp_reply * reply)43 smtp_reply_is_temp_fail(const struct smtp_reply *reply)
44 {
45 	return ((reply->status / 100) == 4);
46 }
47 
48 void smtp_reply_init(struct smtp_reply *reply, unsigned int status,
49 	const char *text);
50 void smtp_reply_printf(struct smtp_reply *reply, unsigned int status,
51 	const char *format, ...) ATTR_FORMAT(3, 4);
52 
53 const char *
54 smtp_reply_get_enh_code(const struct smtp_reply *reply);
55 const char *const *
56 smtp_reply_get_text_lines_omit_prefix(const struct smtp_reply *reply);
57 
58 /* Write the SMTP reply as a sequence of lines according to the SMTP syntax,
59    each terminated by CRLF. */
60 void smtp_reply_write(string_t *out, const struct smtp_reply *reply);
61 /* Write the SMTP reply as a single line without CRLF, even when it consists
62    of multiple lines. This function cannot be used with internal client error
63    replies (status code >= 560). */
64 void smtp_reply_write_one_line(string_t *out, const struct smtp_reply *reply);
65 /* Create a log line from the SMTP reply. This also properly handles internal
66    client error replies (status_code >= 560). */
67 const char *smtp_reply_log(const struct smtp_reply *reply);
68 /* Returns the message of the reply as a single line without status codes and
69    without CRLF.
70  */
71 const char *smtp_reply_get_message(const struct smtp_reply *reply);
72 
73 void smtp_reply_copy(pool_t pool, struct smtp_reply *dst,
74 	const struct smtp_reply *src);
75 struct smtp_reply *smtp_reply_clone(pool_t pool,
76 	const struct smtp_reply *src);
77 
78 /* Set standard reply fields in provided pass-through event */
79 void smtp_reply_add_to_event(const struct smtp_reply *reply,
80 			     struct event_passthrough *e);
81 
82 #endif
83