///|
pub struct DeliveryStatus {
final_recipient : String
action : String
status : String
diagnostic_code : String
remote_mta : String
} derive(Eq, Debug)
///|
pub fn delivery_statuses(message : MailMessage) -> Array[DeliveryStatus] {
let out : Array[DeliveryStatus] = []
for part in flatten_parts(message) {
if part.content_type.media_type == "message" &&
part.content_type.subtype == "delivery-status" {
for item in parse_delivery_status_body(part_body_text(part)) {
out.push(item)
}
}
}
out
}
///|
pub fn parse_delivery_status_body(body : String) -> Array[DeliveryStatus] {
let blocks = split_status_blocks(body)
let out : Array[DeliveryStatus] = []
for block in blocks {
let headers = parse_header_block(block)
let final_recipient = header_value(headers, "Final-Recipient")
if final_recipient != "" {
out.push({
final_recipient,
action: header_value(headers, "Action"),
status: header_value(headers, "Status"),
diagnostic_code: header_value(headers, "Diagnostic-Code"),
remote_mta: header_value(headers, "Remote-MTA"),
})
}
}
out
}
///|
fn split_status_blocks(body : String) -> Array[String] {
let lines = split_lines(body)
let blocks : Array[String] = []
let mut current = ""
for line in lines {
if line == "" {
if current != "" {
blocks.push(current)
current = ""
}
} else {
current = current + line + "\n"
}
}
if current != "" {
blocks.push(current)
}
blocks
}
///|
pub fn is_bounce(message : MailMessage) -> Bool {
lower_ascii(header_value(message.headers, "Auto-Submitted")) == "auto-replied" ||
delivery_statuses(message).length() > 0 ||
content_summary(message).contains("delivery")
}
///|
pub fn failed_recipient_count(message : MailMessage) -> Int {
let mut count = 0
for status in delivery_statuses(message) {
if lower_ascii(status.action) == "failed" {
count = count + 1
}
}
count
}
///|
pub fn dsn_summary(message : MailMessage) -> String {
let mut out = ""
for status in delivery_statuses(message) {
if out != "" {
out = out + "\n"
}
out = out +
status.final_recipient +
" " +
status.action +
" " +
status.status
}
out
}
///|
fn part_body_text(part : MailPart) -> String {
if part.decoded_body != "" {
part.decoded_body
} else {
part.raw_body
}
}
///|
fn content_summary(message : MailMessage) -> String {
lower_ascii(
message.subject +
" " +
plain_text(message) +
" " +
strip_html(html_text(message)),
)
}