use media_type::{MULTIPART, ALTERNATIVE, RELATED, MIXED};
use vec1::Vec1;
use headers::{
HeaderKind,
headers,
header_components::{
Disposition,
DispositionKind,
MediaType
}
};
use crate::{
mail::Mail,
resource::Resource
};
#[derive(Debug)]
pub struct BodyPart {
pub resource: Resource,
pub inline_embeddings: Vec<Resource>,
pub attachments: Vec<Resource>
}
pub struct MailParts {
pub alternative_bodies: Vec1<BodyPart>,
pub inline_embeddings: Vec<Resource>,
pub attachments: Vec<Resource>
}
impl MailParts {
pub fn compose(self)
-> Mail
{
let MailParts {
alternative_bodies,
inline_embeddings,
attachments
} = self;
let mut attachments = attachments.into_iter()
.map(|atta| atta.create_mail_with_disposition(DispositionKind::Attachment))
.collect::<Vec<_>>();
let mut alternatives = alternative_bodies.into_iter()
.map(|body| body.create_mail(&mut attachments))
.collect::<Vec<_>>();
let mail = alternatives.pop().unwrap();
let mail =
if alternatives.is_empty() {
mail
} else {
mail.wrap_with_alternatives(alternatives)
};
let mail =
if inline_embeddings.is_empty() {
mail
} else {
let related = inline_embeddings.into_iter()
.map(|embedding| {
embedding.create_mail_with_disposition(DispositionKind::Inline)
})
.collect::<Vec<_>>();
mail.wrap_with_related(related)
};
let mail =
if attachments.is_empty() {
mail
} else {
mail.wrap_with_mixed(attachments)
};
mail
}
}
impl BodyPart {
pub fn create_mail(
self,
attachments_out: &mut Vec<Mail>,
) -> Mail {
let BodyPart {
resource,
inline_embeddings,
attachments
} = self;
let body = resource.create_mail();
for attachment in attachments.into_iter() {
let mail = attachment.create_mail_with_disposition(DispositionKind::Attachment);
attachments_out.push(mail)
}
if inline_embeddings.is_empty() {
body
} else {
let related = inline_embeddings.into_iter()
.map(|embedding| {
embedding.create_mail_with_disposition(DispositionKind::Inline)
})
.collect::<Vec<_>>();
body.wrap_with_related(related)
}
}
}
impl Resource {
pub fn create_mail(self) -> Mail {
Mail::new_singlepart_mail(self)
}
pub fn create_mail_with_disposition(self, disposition_kind: DispositionKind) -> Mail {
let mut mail = self.create_mail();
let disposition = Disposition::new(disposition_kind, Default::default());
mail.insert_header(headers::ContentDisposition::body(disposition));
mail
}
}
impl Mail {
pub fn wrap_with_mixed(self, other_bodies: Vec<Mail>)
-> Mail
{
let mut bodies = other_bodies;
bodies.push(self);
new_multipart(&MIXED, bodies)
}
pub fn wrap_with_alternatives(self, alternates: Vec<Mail>)
-> Mail
{
let mut bodies = alternates;
bodies.insert(0, self);
new_multipart(&ALTERNATIVE, bodies)
}
pub fn wrap_with_related(self, related: Vec<Mail>)
-> Mail
{
let mut bodies = related;
bodies.insert(0, self);
new_multipart(&RELATED, bodies)
}
}
fn new_multipart(sub_type: &'static str, bodies: Vec<Mail>)
-> Mail
{
let content_type = MediaType::new(MULTIPART, sub_type)
.unwrap();
Mail::new_multipart_mail(content_type, bodies)
}