void Multipart::simplifyMimeStructure() { // If we're looking at a multipart with just a single part, change // the mime type to avoid the middle multipart. This affects // Kaiten Mail. if ( header()->contentType() && header()->contentType()->type() == "multipart" && parts->count() == 1 && ( !parts->firstElement()->header()->contentType() || parts->firstElement()->header()->contentType()->type() != "multipart" ) ) { Header * me = header(); Header * sub = parts->firstElement()->header(); me->removeField( HeaderField::ContentType ); ContentType * ct = sub->contentType(); if ( ct ) me->add( ct ); me->removeField( HeaderField::ContentTransferEncoding ); ContentTransferEncoding * cte = sub->contentTransferEncoding(); if ( cte ) me->add( cte ); me->removeField( HeaderField::ContentDisposition ); ContentDisposition * cd = sub->contentDisposition(); if ( cd ) me->add( cd ); if ( !ct && !cte && !cd ) me->removeField( HeaderField::MimeVersion ); } }
Header * Message::parseHeader( uint & i, uint end, const EString & rfc2822, Header::Mode m ) { Header * h = new Header( m ); bool done = false; while ( !done ) { if ( i >= end ) done = true; if ( rfc2822[i] == 0xEF && rfc2822[i+1] == 0xBB && rfc2822[i+2] == 0xBF ) i += 3; uint j = i; while ( rfc2822[j] >= 33 && rfc2822[j] <= 127 && rfc2822[j] != ':' ) j++; if ( j == i + 4 && m == Header::Rfc2822 && rfc2822.mid( i, j-i+1 ).lower() == "from " ) { while ( i < end && rfc2822[i] != '\r' && rfc2822[i] != '\n' ) i++; while ( rfc2822[i] == '\r' ) i++; if ( rfc2822[i] == '\n' ) i++; } else if ( j > i && rfc2822[j] == ':' ) { EString name = rfc2822.mid( i, j-i ); i = j; i++; while ( rfc2822[i] == ' ' || rfc2822[i] == '\t' ) i++; j = i; // this isn't at all pretty, is it... while ( j < rfc2822.length() && ( rfc2822[j] != '\n' || ( rfc2822[j] == '\n' && ( rfc2822[j+1] == ' ' || rfc2822[j+1] == '\t' ) ) ) ) j++; if ( j && rfc2822[j-1] == '\r' ) j--; EString value = rfc2822.mid( i, j-i ); if ( !value.simplified().isEmpty() || name.lower().startsWith( "x-" ) ) { HeaderField * f = HeaderField::create( name, value ); h->add( f ); } i = j; if ( rfc2822[i] == '\r' && rfc2822[i+1] == '\n' ) i++; i++; } else { done = true; } } return h; }
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; }