1use crate::events::error::{ErrorEvent, ErrorSeverity, ErrorType};
6use serde_json::{json, Value};
7
8pub struct ErrorJsonFormatter;
10
11impl ErrorJsonFormatter {
12 pub fn format_error_event(event: &ErrorEvent) -> Value {
14 match event {
15 ErrorEvent::DeliveryDeferred {
16 queue_id,
17 to,
18 relay,
19 delay,
20 delays,
21 dsn,
22 status,
23 reason,
24 error_type,
25 } => {
26 let severity = error_type.severity();
27 json!({
28 "event_type": "delivery_deferred",
29 "description": "邮件投递延迟错误",
30 "queue_id": queue_id,
31 "to": to,
32 "relay": relay,
33 "delay": delay,
34 "delays": delays,
35 "dsn": dsn,
36 "status": status,
37 "reason": reason,
38 "error_type": error_type,
39 "error_category": Self::format_error_type(error_type),
40 "severity": Self::format_severity(&severity),
41 "fields": {
42 "queue_id": {
43 "value": queue_id,
44 "type": "string",
45 "description": "队列标识符"
46 },
47 "to": {
48 "value": to,
49 "type": "string",
50 "description": "收件人地址"
51 },
52 "relay": {
53 "value": relay,
54 "type": "string",
55 "description": "中继服务器"
56 },
57 "delay": {
58 "value": delay,
59 "type": "number",
60 "description": "总延迟时间(秒)"
61 },
62 "delays": {
63 "value": delays,
64 "type": "string",
65 "description": "各阶段延迟时间"
66 },
67 "dsn": {
68 "value": dsn,
69 "type": "string",
70 "description": "投递状态通知代码"
71 },
72 "reason": {
73 "value": reason,
74 "type": "string",
75 "description": "错误原因"
76 }
77 }
78 })
79 }
80
81 ErrorEvent::DeliveryFailed {
82 queue_id,
83 to,
84 relay,
85 delay,
86 delays,
87 dsn,
88 status,
89 reason,
90 error_type,
91 } => {
92 let severity = error_type.severity();
93 json!({
94 "event_type": "delivery_failed",
95 "description": "邮件投递永久失败",
96 "queue_id": queue_id,
97 "to": to,
98 "relay": relay,
99 "delay": delay,
100 "delays": delays,
101 "dsn": dsn,
102 "status": status,
103 "reason": reason,
104 "error_type": error_type,
105 "error_category": Self::format_error_type(error_type),
106 "severity": Self::format_severity(&severity),
107 "fields": {
108 "queue_id": {
109 "value": queue_id,
110 "type": "string",
111 "description": "队列标识符"
112 },
113 "to": {
114 "value": to,
115 "type": "string",
116 "description": "收件人地址"
117 },
118 "relay": {
119 "value": relay,
120 "type": "string",
121 "description": "中继服务器"
122 },
123 "delay": {
124 "value": delay,
125 "type": "number",
126 "description": "总延迟时间(秒)"
127 },
128 "dsn": {
129 "value": dsn,
130 "type": "string",
131 "description": "投递状态通知代码"
132 },
133 "reason": {
134 "value": reason,
135 "type": "string",
136 "description": "失败原因"
137 }
138 }
139 })
140 }
141
142 ErrorEvent::SystemError {
143 queue_id,
144 error_type,
145 message,
146 } => {
147 let severity = error_type.severity();
148 json!({
149 "event_type": "system_error",
150 "description": "系统配置或运行错误",
151 "queue_id": queue_id,
152 "message": message,
153 "error_type": error_type,
154 "error_category": Self::format_error_type(error_type),
155 "severity": Self::format_severity(&severity),
156 "fields": {
157 "message": {
158 "value": message,
159 "type": "string",
160 "description": "错误消息内容"
161 },
162 "queue_id": {
163 "value": queue_id,
164 "type": "optional_string",
165 "description": "队列标识符(如果有)"
166 }
167 }
168 })
169 }
170
171 ErrorEvent::ConnectionError {
172 queue_id,
173 to,
174 relay,
175 delay,
176 delays,
177 dsn,
178 reason,
179 error_type,
180 } => {
181 let severity = error_type.severity();
182 json!({
183 "event_type": "connection_error",
184 "description": "网络连接错误",
185 "queue_id": queue_id,
186 "to": to,
187 "relay": relay,
188 "delay": delay,
189 "delays": delays,
190 "dsn": dsn,
191 "reason": reason,
192 "error_type": error_type,
193 "error_category": Self::format_error_type(error_type),
194 "severity": Self::format_severity(&severity),
195 "fields": {
196 "queue_id": {
197 "value": queue_id,
198 "type": "string",
199 "description": "队列标识符"
200 },
201 "reason": {
202 "value": reason,
203 "type": "string",
204 "description": "连接错误原因"
205 },
206 "to": {
207 "value": to,
208 "type": "string",
209 "description": "目标收件人(如果有)"
210 },
211 "relay": {
212 "value": relay,
213 "type": "string",
214 "description": "目标中继服务器(如果有)"
215 }
216 }
217 })
218 }
219
220 ErrorEvent::Other {
221 queue_id,
222 error_type,
223 message,
224 } => {
225 json!({
226 "event_type": "error_other",
227 "description": "其他未分类错误",
228 "queue_id": queue_id,
229 "error_type": error_type,
230 "message": message,
231 "severity": {
232 "level": 2,
233 "name": "unknown",
234 "description": "未知严重性"
235 },
236 "fields": {
237 "message": {
238 "value": message,
239 "type": "string",
240 "description": "原始错误消息"
241 },
242 "queue_id": {
243 "value": queue_id,
244 "type": "optional_string",
245 "description": "队列标识符(如果有)"
246 }
247 }
248 })
249 }
250 }
251 }
252
253 fn format_error_type(error_type: &ErrorType) -> Value {
255 json!({
256 "type": error_type,
257 "name": error_type,
258 "description": error_type.description(),
259 "severity": error_type.severity()
260 })
261 }
262
263 fn format_severity(severity: &ErrorSeverity) -> Value {
265 json!({
266 "level": severity.level(),
267 "name": severity,
268 "description": severity.description()
269 })
270 }
271
272 pub fn add_statistics(mut json: Value, event: &ErrorEvent) -> Value {
274 if let Some(obj) = json.as_object_mut() {
275 obj.insert(
277 "statistics".to_string(),
278 json!({
279 "retry_recommended": Self::is_retry_recommended(event),
280 "requires_admin_attention": Self::requires_admin_attention(event),
281 "affects_mail_flow": Self::affects_mail_flow(event),
282 "error_frequency": Self::get_error_frequency_hint(event)
283 }),
284 );
285
286 obj.insert(
288 "troubleshooting".to_string(),
289 json!({
290 "suggested_actions": Self::get_suggested_actions(event),
291 "related_components": Self::get_related_components(event),
292 "documentation_links": Self::get_documentation_links(event)
293 }),
294 );
295 }
296 json
297 }
298
299 fn is_retry_recommended(event: &ErrorEvent) -> bool {
301 match event {
302 ErrorEvent::DeliveryDeferred { error_type, .. } => {
303 matches!(
304 error_type.severity(),
305 ErrorSeverity::Temporary | ErrorSeverity::Network
306 )
307 }
308 ErrorEvent::ConnectionError { error_type, .. } => {
309 matches!(
310 error_type.severity(),
311 ErrorSeverity::Temporary | ErrorSeverity::Network
312 )
313 }
314 _ => false,
315 }
316 }
317
318 fn requires_admin_attention(event: &ErrorEvent) -> bool {
320 match event {
321 ErrorEvent::SystemError { .. } => true,
322 ErrorEvent::DeliveryFailed { error_type, .. } => {
323 matches!(
324 error_type.severity(),
325 ErrorSeverity::SystemIssue | ErrorSeverity::ProtocolIssue
326 )
327 }
328 _ => false,
329 }
330 }
331
332 fn affects_mail_flow(event: &ErrorEvent) -> bool {
334 match event {
335 ErrorEvent::SystemError { .. } => true,
336 ErrorEvent::DeliveryFailed { .. } => true,
337 ErrorEvent::DeliveryDeferred { .. } => true,
338 ErrorEvent::ConnectionError { .. } => true,
339 ErrorEvent::Other { .. } => false,
340 }
341 }
342
343 fn get_error_frequency_hint(event: &ErrorEvent) -> &'static str {
345 match event {
346 ErrorEvent::DeliveryDeferred { error_type, .. } => match error_type {
347 ErrorType::DnsResolution => "高频错误",
348 ErrorType::ConnectionRefused => "中频错误",
349 _ => "低频错误",
350 },
351 _ => "变动频率",
352 }
353 }
354
355 fn get_suggested_actions(event: &ErrorEvent) -> Vec<&'static str> {
357 match event {
358 ErrorEvent::DeliveryDeferred { error_type, .. }
359 | ErrorEvent::DeliveryFailed { error_type, .. }
360 | ErrorEvent::SystemError { error_type, .. }
361 | ErrorEvent::ConnectionError { error_type, .. } => match error_type {
362 ErrorType::DnsResolution => vec!["检查DNS配置", "验证域名解析", "检查网络连接"],
363 ErrorType::ConnectionRefused => {
364 vec!["检查目标服务器状态", "验证端口是否开放", "检查防火墙规则"]
365 }
366 ErrorType::ConnectionLost => {
367 vec!["检查网络稳定性", "验证服务器负载", "检查超时配置"]
368 }
369 ErrorType::SystemConfig => vec!["检查Postfix配置", "验证文件权限", "重新加载配置"],
370 _ => vec!["查看错误详情", "联系系统管理员"],
371 },
372 ErrorEvent::Other { .. } => vec!["分析原始日志", "联系技术支持"],
373 }
374 }
375
376 fn get_related_components(event: &ErrorEvent) -> Vec<&'static str> {
378 match event {
379 ErrorEvent::DeliveryDeferred { .. } | ErrorEvent::DeliveryFailed { .. } => {
380 vec!["smtp", "qmgr", "cleanup"]
381 }
382 ErrorEvent::ConnectionError { .. } => {
383 vec!["smtp", "network"]
384 }
385 ErrorEvent::SystemError { .. } => {
386 vec!["master", "postfix-config"]
387 }
388 ErrorEvent::Other { .. } => vec!["all"],
389 }
390 }
391
392 fn get_documentation_links(_event: &ErrorEvent) -> Vec<&'static str> {
394 vec![
395 "http://www.postfix.org/DEBUG_README.html",
396 "http://www.postfix.org/TROUBLE_SHOOTING_README.html",
397 ]
398 }
399}