///|
pub struct MessageDraft {
from : Address
to : Array[Address]
cc : Array[Address]
subject : String
date : String
message_id : String
text_body : String
html_body : String
attachments : Array[DraftAttachment]
} derive(Eq, Debug)
///|
pub struct DraftAttachment {
filename : String
content_type : String
body : String
encoding : TransferEncoding
} derive(Eq, Debug)
///|
pub fn draft(
from : Address,
to : Array[Address],
subject : String,
) -> MessageDraft {
{
from,
to,
cc: [],
subject,
date: "",
message_id: "",
text_body: "",
html_body: "",
attachments: [],
}
}
///|
pub fn with_cc(input : MessageDraft, cc : Array[Address]) -> MessageDraft {
{
from: input.from,
to: input.to,
cc,
subject: input.subject,
date: input.date,
message_id: input.message_id,
text_body: input.text_body,
html_body: input.html_body,
attachments: input.attachments,
}
}
///|
pub fn with_text(input : MessageDraft, text : String) -> MessageDraft {
{
from: input.from,
to: input.to,
cc: input.cc,
subject: input.subject,
date: input.date,
message_id: input.message_id,
text_body: text,
html_body: input.html_body,
attachments: input.attachments,
}
}
///|
pub fn with_html(input : MessageDraft, html : String) -> MessageDraft {
{
from: input.from,
to: input.to,
cc: input.cc,
subject: input.subject,
date: input.date,
message_id: input.message_id,
text_body: input.text_body,
html_body: html,
attachments: input.attachments,
}
}
///|
pub fn with_date(input : MessageDraft, date : String) -> MessageDraft {
{
from: input.from,
to: input.to,
cc: input.cc,
subject: input.subject,
date,
message_id: input.message_id,
text_body: input.text_body,
html_body: input.html_body,
attachments: input.attachments,
}
}
///|
pub fn with_message_id(
input : MessageDraft,
message_id : String,
) -> MessageDraft {
{
from: input.from,
to: input.to,
cc: input.cc,
subject: input.subject,
date: input.date,
message_id,
text_body: input.text_body,
html_body: input.html_body,
attachments: input.attachments,
}
}
///|
pub fn draft_attachment(
filename : String,
content_type : String,
body : String,
) -> DraftAttachment {
{ filename, content_type, body, encoding: SevenBit }
}
///|
pub fn draft_attachment_encoded(
filename : String,
content_type : String,
body : String,
encoding : TransferEncoding,
) -> DraftAttachment {
{ filename, content_type, body, encoding }
}
///|
pub fn with_attachment(
input : MessageDraft,
attachment : DraftAttachment,
) -> MessageDraft {
let out : Array[DraftAttachment] = []
for item in input.attachments {
out.push(item)
}
out.push(attachment)
{
from: input.from,
to: input.to,
cc: input.cc,
subject: input.subject,
date: input.date,
message_id: input.message_id,
text_body: input.text_body,
html_body: input.html_body,
attachments: out,
}
}
///|
pub fn render_message(input : MessageDraft) -> String {
let headers = render_common_headers(input)
if input.attachments.length() > 0 {
render_mixed(headers, input)
} else if input.html_body != "" && input.text_body != "" {
render_alternative(headers, input)
} else if input.html_body != "" {
headers +
"Content-Type: text/html; charset=utf-8\r\n\r\n" +
input.html_body +
"\r\n"
} else {
headers +
"Content-Type: text/plain; charset=utf-8\r\n\r\n" +
input.text_body +
"\r\n"
}
}
///|
fn render_common_headers(input : MessageDraft) -> String {
let mut out = ""
out = out + "From: " + format_address(input.from) + "\r\n"
out = out + "To: " + join_address_header(input.to) + "\r\n"
if input.cc.length() > 0 {
out = out + "Cc: " + join_address_header(input.cc) + "\r\n"
}
out = out + "Subject: " + input.subject + "\r\n"
if input.date != "" {
out = out + "Date: " + input.date + "\r\n"
}
if input.message_id != "" {
out = out + "Message-ID: " + input.message_id + "\r\n"
}
out
}
///|
fn render_alternative(headers : String, input : MessageDraft) -> String {
let boundary = "mailkit-alt-boundary"
headers +
"Content-Type: multipart/alternative; boundary=\"" +
boundary +
"\"\r\n\r\n" +
"--" +
boundary +
"\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n\r\n" +
input.text_body +
"\r\n" +
"--" +
boundary +
"\r\n" +
"Content-Type: text/html; charset=utf-8\r\n\r\n" +
input.html_body +
"\r\n" +
"--" +
boundary +
"--\r\n"
}
///|
fn render_mixed(headers : String, input : MessageDraft) -> String {
let boundary = "mailkit-mixed-boundary"
let mut out = headers +
"Content-Type: multipart/mixed; boundary=\"" +
boundary +
"\"\r\n\r\n"
out = out + "--" + boundary + "\r\n"
if input.html_body != "" && input.text_body != "" {
out = out +
"Content-Type: multipart/alternative; boundary=\"mailkit-inner-alt\"\r\n\r\n"
out = out +
"--mailkit-inner-alt\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n"
out = out + input.text_body + "\r\n"
out = out +
"--mailkit-inner-alt\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"
out = out + input.html_body + "\r\n--mailkit-inner-alt--\r\n"
} else if input.html_body != "" {
out = out +
"Content-Type: text/html; charset=utf-8\r\n\r\n" +
input.html_body +
"\r\n"
} else {
out = out +
"Content-Type: text/plain; charset=utf-8\r\n\r\n" +
input.text_body +
"\r\n"
}
for item in input.attachments {
out = out + "--" + boundary + "\r\n"
out = out +
"Content-Type: " +
item.content_type +
"; name=\"" +
item.filename +
"\"\r\n"
out = out +
"Content-Disposition: attachment; filename=\"" +
item.filename +
"\"\r\n"
out = out +
"Content-Transfer-Encoding: " +
render_encoding(item.encoding) +
"\r\n\r\n"
out = out + item.body + "\r\n"
}
out + "--" + boundary + "--\r\n"
}
///|
fn render_encoding(encoding : TransferEncoding) -> String {
match encoding {
SevenBit => "7bit"
EightBit => "8bit"
Binary => "binary"
Base64 => "base64"
QuotedPrintable => "quoted-printable"
UnknownEncoding(value) => value
}
}
///|
fn join_address_header(items : Array[Address]) -> String {
let mut out = ""
let mut i = 0
for item in items {
if i > 0 {
out = out + ", "
}
out = out + format_address(item)
i = i + 1
}
out
}