void Bodypart::parseMultipart( uint i, uint end, const EString & rfc2822, const EString & divider, bool digest, List< Bodypart > * children, Multipart * parent, bool pgpSigned ) { bool isPgpSigned = pgpSigned; uint start = 0; bool last = false; uint pn = 1; while ( !last && i <= end ) { if ( i >= end || ( rfc2822[i] == '-' && rfc2822[i+1] == '-' && ( i == 0 || rfc2822[i-1] == 13 || rfc2822[i-1] == 10 ) && rfc2822[i+2] == divider[0] && rfc2822.mid( i+2, divider.length() ) == divider ) ) { uint j = i; bool l = false; if ( i >= end ) { l = true; } else { j = i + 2 + divider.length(); if ( rfc2822[j] == '-' && rfc2822[j+1] == '-' ) { j += 2; l = true; } } while ( rfc2822[j] == ' ' || rfc2822[j] == '\t' ) j++; if ( rfc2822[j] == 13 || rfc2822[j] == 10 || j >= rfc2822.length() ) { // finally. we accept that as a boundary line. if ( rfc2822[j] == 13 ) j++; if ( rfc2822[j] == 10 ) j++; if ( start > 0 ) { uint sigstart = start; // remember original start Header * h = Message::parseHeader( start, j, rfc2822, Header::Mime ); if ( digest ) h->setDefaultType( Header::MessageRfc822 ); h->repair(); // Strip the [CR]LF that belongs to the boundary. if ( rfc2822[i-1] == 10 ) { i--; if ( rfc2822[i-1] == 13 ) i--; } if ( isPgpSigned ) { // store the complete to-be-signed part, incl. header(s), to keep the unchanged version Bodypart * bpt = new Bodypart( 0, parent ); bpt->setData( rfc2822.mid(sigstart, i - sigstart) ); bpt->setNumBytes( i - sigstart ); children->append( bpt ); isPgpSigned = false; } Bodypart * bp = parseBodypart( start, i, rfc2822, h, parent ); bp->d->number = pn; children->append( bp ); pn++; h->repair( bp, "" ); } last = l; start = j; i = j; } } while ( i < end && rfc2822[i] != 13 && rfc2822[i] != 10 ) i++; while ( i < end && ( rfc2822[i] == 13 || rfc2822[i] == 10 ) ) i++; } }
Injectee * DSN::result() const { Injectee * r = new Injectee; Bodypart * plainText = new Bodypart( 1, r ); Bodypart * dsn = new Bodypart( 2, r ); Bodypart * original = new Bodypart( 3, r ); plainText->setParent( r ); dsn->setParent( r ); original->setParent( r ); r->children()->append( plainText ); r->children()->append( dsn ); r->children()->append( original ); // set up the original message, either full or header-only if ( fullReport() ) { original->header()->add( "Content-Type", "text/rfc822-headers" ); original->setData( message()->header()->asText() ); // this is what we _should_ do, except that we don't. the body // of the message is lost, probably because original-> has a // null parent. //original->header()->add( "Content-Type", "message/rfc822" ); //original->setMessage( message() ); // and maybe we shouldn't anyway. sending a potentially big // body in a bounce is not necessarily a good idea. } else { // nasty mime name there original->header()->add( "Content-Type", "text/rfc822-headers" ); original->setData( message()->header()->asText() ); } // the from field has to contain... what? let's try this for now. Address * from = new Address( Configuration::hostname(), "postmaster", Configuration::hostname() ); // set up the top-level header Header * h = r->header(); if ( resultDate() ) { h->add( "Date", resultDate()->rfc822() ); } else { Date * now = new Date; now->setCurrentTime(); h->add( "Date", now->rfc822() ); } h->add( "From", from->toString() ); if ( sender() ) h->add( "To", sender()->toString() ); if ( allOk() ) h->add( "Subject", "Message delivered" ); else if ( allFailed() ) h->add( "Subject", "Message delivery failed" ); else h->add( "Subject", "Message delivery reports" ); h->add( "Mime-Version", "1.0" ); h->add( "Content-Type", "multipart/report; boundary=" + Message::acceptableBoundary( message()->rfc822() ) ); // set up the plaintext and DSN parts // what charset should we use for plainText? plainText->header()->add( "Content-Type", "text/plain; format=flowed" ); dsn->header()->add( "Content-Type", "message/delivery-status" ); plainText->setData( plainBody() ); dsn->setData( dsnBody() ); r->addMessageId(); return r; }