Browse Source

change handling of Content-Type: multipart/*

MIME-10
Roker 2 years ago
parent
commit
8c8809eebf
1 changed files with 29 additions and 76 deletions
  1. +29
    -76
      src/bodyparser.cc

+ 29
- 76
src/bodyparser.cc View File

@ -146,98 +146,51 @@ void set_longmsg(message* msg, const Message& m)
}
}
// handle multipart/alternative
void handle_multipart_alternative(message* msg, MultipartMessage& vm)
void handle_multipart(message* msg, const MimeHeaders& mh, const MultipartMessage& mm, unsigned level = 1)
{
// only add to msg->longmsg if not already set
auto first_text = msg->longmsg ? vm.cend() : std::find_if(vm.cbegin(), vm.cend(), has_mimetype("text/plain") );
if(first_text != vm.end())
LOG << "MM.size=" << mm.size() << ", level=" << level << ":\n";
for(const auto& m : mm)
{
LOG << "ALT-TEXT: MH" << first_text->mh << "\n";
set_longmsg(msg, *first_text);
LOG << "°°M: " << m << "\n";
}
// only add to msg->longmsg_formatted if not already set
auto first_html = msg->longmsg_formatted ? vm.cend() : std::find_if(vm.cbegin(), vm.cend(), has_mimetype("text/html") );
if(first_html != vm.end())
{
LOG << "ALT-HTML: MH" << first_html->mh << "\n";
const sv html_charset = header_value( first_html->mh.tparams, "charset" );
msg->longmsg_formatted = create_string(first_html->body, html_charset, first_html->mh.decoder );
}else
// All "multipart" MimeTypes: handle as "multipart/mixed":
for(const Message& m : mm)
{
auto mrel = std::find_if(vm.cbegin(), vm.cend(), has_mimetype("multipart/related") );
if(mrel != vm.end())
if(m.mh.type == "multipart")
{
MultipartMessage vmr = parse_multipart( mrel->body, mrel->boundary() );
first_html = msg->longmsg_formatted ? vmr.cend() : std::find_if(vmr.cbegin(), vmr.cend(), has_mimetype("text/html") );
if(first_html != vmr.cend())
if(level < MaxMultipartNestingLevel)
{
LOG << "ALT-RELATED-HTML: MH" << first_html->mh << "\n";
const sv html_charset = header_value( first_html->mh.tparams, "charset" );
msg->longmsg_formatted = create_string(first_html->body, html_charset, first_html->mh.decoder );
}
// move the remaining parts to the topmost MIME tree
for(auto m = vmr.cbegin(); m != vmr.cend(); ++m)
{
if(m != first_html)
{
add_attachment(msg, m->body, m->mh);
}
const sv boundary = header_value(m.mh.tparams, "boundary");
MultipartMessage mm_nested = parse_multipart( m.body, boundary );
LOG << "MULTIPART/" << m.mh.subtype << ": " << mm.size() << " parts. Boundary = “" << boundary << "” :\n";
handle_multipart(msg, m.mh, mm_nested, level+1);
}else{
add_attachment(msg, m.body, m.mh);
}
vm.erase(mrel); // don't handle that part as a remaining attachment
first_html = vm.end(); // to avoid to add it to msg->longmsg_formatted again
continue;
}
}
for(auto m = vm.cbegin(); m != vm.cend(); ++m)
{
if(m != first_html && m!=first_text)
if(m.mh.dispo_type == PEP_CONTENT_DISP_INLINE)
{
add_attachment(msg, m->body, m->mh);
}
}
}
void handle_multipart(message* msg, const MimeHeaders& mh, MultipartMessage& mm)
{
LOG << "MM.size=" << mm.size() << '\n';
for(const auto& m : mm)
{
LOG << "°°M: " << m << "\n";
}
if(mh.subtype == "alternative" || mh.subtype == "related" )
{
handle_multipart_alternative(msg, mm);
}else // All other "multipart" MimeTypes: handle as "multipart/mixed":
{
for(auto q=mm.cbegin(); q!=mm.cend(); ++q)
{
const auto mime_type = q->mh.mime_type();
if(mime_type=="multipart/alternative" || mime_type=="multipart/related" )
{
const sv boundary = header_value(q->mh.tparams, "boundary");
MultipartMessage mmm = parse_multipart(q->body, boundary );
LOG << "Alternative in MM: " << mmm.size() << " parts. Boundary = “" << boundary << "” :\n";
handle_multipart_alternative(msg, mmm);
}else if(mime_type=="text/plain" && msg->longmsg==nullptr)
const auto mime_type = m.mh.mime_type();
if(mime_type=="text/plain" && msg->longmsg==nullptr)
{
// the first "text/plain" part is handeld specially:
const sv mc_charset = header_value( q->mh.tparams, "charset" );
msg->longmsg = create_string(q->body, mc_charset, q->mh.decoder );
const sv mc_charset = header_value( m.mh.tparams, "charset" );
msg->longmsg = create_string(m.body, mc_charset, m.mh.decoder );
continue;
}else if(mime_type=="text/html" && msg->longmsg_formatted==nullptr)
{
// stange mailer that send HTML body, no plaintext body:
const sv mc_charset = header_value( q->mh.tparams, "charset" );
msg->longmsg_formatted = create_string(q->body, mc_charset, q->mh.decoder );
}else
{
add_attachment(msg, q->body, q->mh);
// first inline "text/html" part goes to longmsg_formatted
const sv mc_charset = header_value( m.mh.tparams, "charset" );
msg->longmsg_formatted = create_string(m.body, mc_charset, m.mh.decoder );
continue;
}
}
add_attachment(msg, m.body, m.mh);
}
}
@ -265,7 +218,7 @@ void handle_mime(message* msg, const MimeHeaders& mh, const BodyLines& body)
const sv boundary = header_value(mh.tparams, "boundary");
MultipartMessage mm = parse_multipart( body, boundary );
LOG << "MULTIPART/" << mh.subtype << ": " << mm.size() << " parts. Boundary = “" << boundary << "” :\n";
handle_multipart(msg, mh, mm);
handle_multipart(msg, mh, mm, 1);
}else if(mh.type == "message")
{
// TODO: What shall I do with this MimeType?


Loading…
Cancel
Save