///|
pub struct ListMetadata {
list_id : String
unsubscribe : Array[String]
archive : String
post : String
help : String
} derive(Eq, Debug)
///|
pub fn list_metadata(message : MailMessage) -> ListMetadata {
{
list_id: header_value(message.headers, "List-ID"),
unsubscribe: parse_angle_uri_list(
header_value(message.headers, "List-Unsubscribe"),
),
archive: first_angle_uri(header_value(message.headers, "List-Archive")),
post: first_angle_uri(header_value(message.headers, "List-Post")),
help: first_angle_uri(header_value(message.headers, "List-Help")),
}
}
///|
pub fn has_list_unsubscribe(message : MailMessage) -> Bool {
list_metadata(message).unsubscribe.length() > 0
}
///|
pub fn preferred_unsubscribe_url(message : MailMessage) -> String {
for item in list_metadata(message).unsubscribe {
if starts_with(item, "https://") || starts_with(item, "http://") {
return item
}
}
""
}
///|
fn parse_angle_uri_list(value : String) -> Array[String] {
let out : Array[String] = []
let chars : Array[Char] = []
for ch in value {
chars.push(ch)
}
let mut i = 0
while i < chars.length() {
if chars[i] == '<' {
let end = find_uri_end(chars, i + 1)
if end > i {
out.push(chars_range(chars, i + 1, end))
i = end + 1
} else {
i = i + 1
}
} else {
i = i + 1
}
}
out
}
///|
fn first_angle_uri(value : String) -> String {
let values = parse_angle_uri_list(value)
if values.length() > 0 {
values[0]
} else {
""
}
}
///|
fn find_uri_end(chars : Array[Char], start : Int) -> Int {
let mut i = start
while i < chars.length() {
if chars[i] == '>' {
return i
}
i = i + 1
}
-1
}
///|
fn chars_range(chars : Array[Char], start : Int, end : Int) -> String {
let mut out = ""
let mut i = start
while i < end {
out = out + chars[i].to_string()
i = i + 1
}
out
}