/* nsresult displayReport (in nsIPrompt prompt, in boolean showErrorOnly, in boolean dontShowReportTwice); */
NS_IMETHODIMP nsMsgSendReport::DisplayReport(nsIPrompt *prompt, PRBool showErrorOnly, PRBool dontShowReportTwice, nsresult *_retval)
{
  NS_ENSURE_ARG_POINTER(_retval);

  nsresult currError = NS_OK;
  mProcessReport[mCurrentProcess]->GetError(&currError);
  *_retval = currError;
  
  if (dontShowReportTwice && mAlreadyDisplayReport)
    return NS_OK;
  
  if (showErrorOnly && NS_SUCCEEDED(currError))
    return NS_OK;
  
  nsXPIDLString currMessage;
  mProcessReport[mCurrentProcess]->GetMessage(getter_Copies(currMessage));


  nsCOMPtr<nsIMsgStringService> composebundle (do_GetService(NS_MSG_COMPOSESTRINGSERVICE_CONTRACTID));
  if (!composebundle)
  {
    //TODO need to display a generic hardcoded message
    mAlreadyDisplayReport = PR_TRUE;
    return NS_OK;
  }

  nsXPIDLString dialogTitle;
  nsXPIDLString dialogMessage;

  if (NS_SUCCEEDED(currError))
  {
    //TODO display a success error message
    return NS_OK;
  }
  
  //Do we have an explanation of the error? if no, try to build one...
  if (currMessage.IsEmpty())
  {
      switch (currError)
      {
        case NS_BINDING_ABORTED:
        case NS_ERROR_SEND_FAILED:
        case NS_ERROR_SEND_FAILED_BUT_NNTP_OK:
        case NS_MSG_FAILED_COPY_OPERATION:
        case NS_MSG_UNABLE_TO_SEND_LATER:
        case NS_MSG_UNABLE_TO_SAVE_DRAFT:
        case NS_MSG_UNABLE_TO_SAVE_TEMPLATE:
          //Ignore, don't need to repeat ourself.
          break;
        case NS_ERROR_MSG_MULTILINGUAL_SEND:
          // already displayed an alert, no additional message is needed
          // return to the compose window
          mAlreadyDisplayReport = PR_TRUE;
          return NS_OK;
        default:
          nsAutoString errorMsg;
          nsMsgBuildErrorMessageByID(currError, errorMsg);

          if (! errorMsg.IsEmpty())
            currMessage.Assign(errorMsg);
          break;
      }
  }
  
  if (mDeliveryMode == nsIMsgCompDeliverMode::Now || mDeliveryMode == nsIMsgCompDeliverMode::SendUnsent)
  {
    // SMTP is taking care of it's own error message and will return NS_ERROR_BUT_DONT_SHOW_ALERT as error code.
    // In that case, we must not show an alert ourself.
    if (currError == NS_ERROR_BUT_DONT_SHOW_ALERT)
    {
      mAlreadyDisplayReport = PR_TRUE;
      return NS_OK;
    }
  
    composebundle->GetStringByID(NS_MSG_SEND_ERROR_TITLE, getter_Copies(dialogTitle));

    PRInt32 preStrId = NS_ERROR_SEND_FAILED;
    PRBool askToGoBackToCompose = PR_FALSE;
    switch (mCurrentProcess)
    {
      case process_BuildMessage :
        preStrId = NS_ERROR_SEND_FAILED;
        askToGoBackToCompose = PR_FALSE;
        break;
      case process_NNTP :
        preStrId = NS_ERROR_SEND_FAILED;
        askToGoBackToCompose = PR_FALSE;
        break;
      case process_SMTP :
        PRBool nntpProceeded;
        mProcessReport[process_NNTP]->GetProceeded(&nntpProceeded);
        if (nntpProceeded)
          preStrId = NS_ERROR_SEND_FAILED_BUT_NNTP_OK;
        else
          preStrId = NS_ERROR_SEND_FAILED;
        askToGoBackToCompose = PR_FALSE;
        break;
      case process_Copy:
        preStrId = NS_MSG_FAILED_COPY_OPERATION;
        askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
        break;
      case process_FCC:
        preStrId = NS_MSG_FAILED_COPY_OPERATION;
        askToGoBackToCompose = (mDeliveryMode == nsIMsgCompDeliverMode::Now);
        break;
    }
    composebundle->GetStringByID(preStrId, getter_Copies(dialogMessage));

    //Do we already have an error message?
    if (!askToGoBackToCompose && currMessage.IsEmpty())
    {
      //we don't have an error description but we can put a generic explanation
      composebundle->GetStringByID(NS_MSG_GENERIC_FAILURE_EXPLANATION, getter_Copies(currMessage));
    }
    
    if (!currMessage.IsEmpty())
    {
      nsAutoString temp((const PRUnichar *)dialogMessage);  // Because of bug 74726, we cannot use directly an XPIDLString

      //Don't need to repeat ourself!
      if (! currMessage.Equals(temp))
      {
        if (! dialogMessage.IsEmpty())
          temp.AppendLiteral("\n");
        temp.Append(currMessage);
        dialogMessage.Assign(temp);
      }
    }
      
    if (askToGoBackToCompose)
    {
      PRBool oopsGiveMeBackTheComposeWindow = PR_TRUE;
      nsXPIDLString text1;
      composebundle->GetStringByID(NS_MSG_ASK_TO_COMEBACK_TO_COMPOSE, getter_Copies(text1));
      nsAutoString temp((const PRUnichar *)dialogMessage);  // Because of bug 74726, we cannot use directly an XPIDLString
      if (! dialogMessage.IsEmpty())
        temp.AppendLiteral("\n");
      temp.Append(text1);
      dialogMessage.Assign(temp);
      nsMsgAskBooleanQuestionByString(prompt, dialogMessage, &oopsGiveMeBackTheComposeWindow, dialogTitle);
      if (!oopsGiveMeBackTheComposeWindow)
        *_retval = NS_OK;
    }
    else
      nsMsgDisplayMessageByString(prompt, dialogMessage, dialogTitle);
  }
  else
  {
    PRInt32 titleID;
    PRInt32 preStrId;

    switch (mDeliveryMode)
    {
      case nsIMsgCompDeliverMode::Later:
        titleID = NS_MSG_SENDLATER_ERROR_TITLE;
        preStrId = NS_MSG_UNABLE_TO_SEND_LATER;
        break;

      case nsIMsgCompDeliverMode::AutoSaveAsDraft:
      case nsIMsgCompDeliverMode::SaveAsDraft:
        titleID = NS_MSG_SAVE_DRAFT_TITLE;
        preStrId = NS_MSG_UNABLE_TO_SAVE_DRAFT;
        break;

      case nsIMsgCompDeliverMode::SaveAsTemplate:
        titleID = NS_MSG_SAVE_TEMPLATE_TITLE;
        preStrId = NS_MSG_UNABLE_TO_SAVE_TEMPLATE;
        break;

      default:
        /* This should never happend! */
        titleID = NS_MSG_SEND_ERROR_TITLE;
        preStrId = NS_ERROR_SEND_FAILED;
        break;
    }

    composebundle->GetStringByID(titleID, getter_Copies(dialogTitle));
    composebundle->GetStringByID(preStrId, getter_Copies(dialogMessage));

    //Do we have an error message...
    if (currMessage.IsEmpty())
    {
      //we don't have an error description but we can put a generic explanation
      composebundle->GetStringByID(NS_MSG_GENERIC_FAILURE_EXPLANATION, getter_Copies(currMessage));
    }

    if (!currMessage.IsEmpty())
    {
      nsAutoString temp((const PRUnichar *)dialogMessage);  // Because of bug 74726, we cannot use directly an XPIDLString
      if (! dialogMessage.IsEmpty())
        temp.AppendLiteral("\n");
      temp.Append(currMessage);
      dialogMessage.Assign(temp);
    }

    nsMsgDisplayMessageByString(prompt, dialogMessage, dialogTitle);
  }
  
  mAlreadyDisplayReport = PR_TRUE;
  return NS_OK;
}
Exemple #2
0
nsresult
nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields)
{
    nsresult rv = NS_ERROR_INVALID_ARG;
    nsCOMPtr <nsIMsgMessageService> messageService;

    if (PL_strcasestr(m_uri, "-message:"))
    {
        nsCOMPtr <nsIFile> tmpFile;
        rv = nsMsgCreateTempFile("nsmail.tmp", getter_AddRefs(tmpFile));
        NS_ENSURE_SUCCESS(rv, rv);
        mTmpFile = do_QueryInterface(tmpFile);
        mDeleteFile = PR_TRUE;
        mCompFields = compFields;
        PR_Free(m_type);
        m_type = PL_strdup(MESSAGE_RFC822);
        PR_Free(m_override_type);
        m_override_type = PL_strdup(MESSAGE_RFC822);
        if (!mTmpFile)
        {
            rv = NS_ERROR_FAILURE;
            goto done;
        }

        nsCOMPtr<nsIOutputStream> outputStream;
        rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, -1, 00600);
        if (NS_FAILED(rv) || !outputStream)
        {
            if (m_mime_delivery_state)
            {
                nsCOMPtr<nsIMsgSendReport> sendReport;
                m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport));
                if (sendReport)
                {
                    nsAutoString error_msg;
                    nsAutoString path;
                    mTmpFile->GetPath(path);
                    nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_TMP_FILE, error_msg, &path, nsnull);
                    sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
                }
            }
            rv =  NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
            goto done;
        }
        mOutFile = do_QueryInterface(outputStream);

        nsCOMPtr<nsIURLFetcher> fetcher = do_CreateInstance(NS_URLFETCHER_CONTRACTID, &rv);
        if (NS_FAILED(rv) || !fetcher)
        {
            if (NS_SUCCEEDED(rv))
                rv =  NS_ERROR_UNEXPECTED;
            goto done;
        }

        rv = fetcher->Initialize(mTmpFile, mOutFile, FetcherURLDoneCallback, this);
        rv = GetMessageServiceFromURI(nsDependentCString(m_uri), getter_AddRefs(messageService));
        if (NS_SUCCEEDED(rv) && messageService)
        {
            nsCAutoString uri(m_uri);
            uri += (uri.FindChar('?') == kNotFound) ? "?" : "&";
            uri.Append("fetchCompleteMessage=true");
            nsCOMPtr<nsIStreamListener> strListener;
            fetcher->QueryInterface(NS_GET_IID(nsIStreamListener), getter_AddRefs(strListener));

            // initialize a new stream converter, that uses the strListener as its input
            // obtain the input stream listener from the new converter,
            // and pass the converter's input stream listener to DisplayMessage

            m_mime_parser = do_CreateInstance(NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID, &rv);
            if (NS_FAILED(rv))
                goto done;

            // Set us as the output stream for HTML data from libmime...
            nsCOMPtr<nsIMimeStreamConverter> mimeConverter = do_QueryInterface(m_mime_parser);
            if (mimeConverter)
            {
                mimeConverter->SetMimeOutputType(nsMimeOutput::nsMimeMessageDecrypt);
                mimeConverter->SetForwardInline(PR_FALSE);
                mimeConverter->SetIdentity(nsnull);
                mimeConverter->SetOriginalMsgURI(nsnull);
            }

            nsCOMPtr<nsIStreamListener> convertedListener = do_QueryInterface(m_mime_parser, &rv);
            if (NS_FAILED(rv))
                goto done;

            nsCOMPtr<nsIURI> aURL;
            rv = messageService->GetUrlForUri(uri.get(), getter_AddRefs(aURL), nsnull);
            if (aURL)
                aURL->SetSpec(nsDependentCString(uri.get()));

            rv = NS_NewInputStreamChannel(getter_AddRefs(m_converter_channel), aURL, nsnull);
            if (NS_FAILED(rv))
                goto done;

            rv = m_mime_parser->AsyncConvertData(
                     "message/rfc822",
                     "message/rfc822",
                     strListener, m_converter_channel);
            if (NS_FAILED(rv))
                goto done;

            rv = messageService->DisplayMessage(uri.get(), convertedListener, nsnull, nsnull, nsnull, nsnull);
        }
    }
done:
    if (NS_FAILED(rv))
    {
        if (mOutFile)
        {
            mOutFile->Close();
            mOutFile = nsnull;
        }

        if (mTmpFile)
        {
            mTmpFile->Remove(PR_FALSE);
            mTmpFile = nsnull;
        }
    }

    return rv;
}
Exemple #3
0
nsresult
nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
{
    NS_ASSERTION (! m_done, "Already done");

    if (!mURL)
        return SnarfMsgAttachment(compFields);

    mCompFields = compFields;

    // First, get as file spec and create the stream for the
    // temp file where we will save this data
    nsCOMPtr <nsIFile> tmpFile;
    nsresult rv = nsMsgCreateTempFile("nsmail.tmp", getter_AddRefs(tmpFile));
    NS_ENSURE_SUCCESS(rv, rv);
    mTmpFile = do_QueryInterface(tmpFile);
    mDeleteFile = PR_TRUE;

    nsCOMPtr<nsIOutputStream> outputStream;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile, -1, 00600);
    if (NS_FAILED(rv) || !outputStream)
    {
        if (m_mime_delivery_state)
        {
            nsCOMPtr<nsIMsgSendReport> sendReport;
            m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport));
            if (sendReport)
            {
                nsAutoString error_msg;
                nsAutoString path;
                mTmpFile->GetPath(path);
                nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_TMP_FILE, error_msg, &path, nsnull);
                sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
            }
        }
        mTmpFile->Remove(PR_FALSE);
        mTmpFile = nsnull;
        return NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
    }
    mOutFile = do_QueryInterface(outputStream);

    nsCString sourceURISpec;
    mURL->GetSpec(sourceURISpec);
#ifdef XP_MACOSX
    if (!m_bogus_attachment && StringBeginsWith(sourceURISpec, NS_LITERAL_CSTRING("file://")))
    {
        // Unescape the path (i.e. un-URLify it) before making a FSSpec
        nsCAutoString filePath;
        filePath.Adopt(nsMsgGetLocalFileFromURL(sourceURISpec.get()));
        nsUnescape(filePath.BeginWriting());

        nsCOMPtr<nsILocalFile> sourceFile;
        NS_NewNativeLocalFile(filePath, PR_TRUE, getter_AddRefs(sourceFile));
        if (!sourceFile)
            return NS_ERROR_FAILURE;

        // check if it is a bundle. if it is, we'll zip it.
        // if not, we'll apple encode it (applesingle or appledouble)
        nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(sourceFile));
        PRBool isPackage;
        macFile->IsPackage(&isPackage);
        if (isPackage)
            rv = ConvertToZipFile(macFile);
        else
            rv = ConvertToAppleEncoding(sourceURISpec, filePath, macFile);

        NS_ENSURE_SUCCESS(rv, rv);
    }
#endif /* XP_MACOSX */

    //
    // Ok, here we are, we need to fire the URL off and get the data
    // in the temp file
    //
    // Create a fetcher for the URL attachment...

    nsCOMPtr<nsIURLFetcher> fetcher = do_CreateInstance(NS_URLFETCHER_CONTRACTID, &rv);
    if (NS_FAILED(rv) || !fetcher)
    {
        if (NS_SUCCEEDED(rv))
            return NS_ERROR_UNEXPECTED;
        else
            return rv;
    }

    return fetcher->FireURLRequest(mURL, mTmpFile, mOutFile, FetcherURLDoneCallback, this);
}
Exemple #4
0
int 
nsMsgSendPart::Write()
{
  int     status = 0;
  char    *separator = nsnull;
  PRBool  needToWriteCRLFAfterEncodedBody  = PR_FALSE;

#define PUSHLEN(str, length)                  \
  do {                            \
    status = mime_write_message_body(m_state, str, length); \
    if (status < 0) goto FAIL;                \
  } while (0)                         \

#define PUSH(str) PUSHLEN(str, PL_strlen(str))

  // rhp: Suppress the output of parts that are empty!
  if ( (m_parent) &&
       (m_numchildren == 0) &&
       ( (!m_buffer) || (!*m_buffer) ) &&
       (!m_filespec) &&
       (!m_mainpart) )
    return SKIP_EMPTY_PART;

  if (m_mainpart && m_type && PL_strcmp(m_type, TEXT_HTML) == 0) 
  {     
    if (m_filespec) 
    {
      // The "insert HTML links" code requires a memory buffer,
      // so read the file into memory.
      NS_ASSERTION(m_buffer == nsnull, "not-null buffer");
      PRInt32           length = 0;
      
      if (m_filespec->Valid())
        length = m_filespec->GetFileSize();
      
      m_buffer = (char *) PR_Malloc(sizeof(char) * (length + 1));
      if (m_buffer) 
      {
        nsInputFileStream file(*m_filespec);
        if (file.is_open()) 
        {
          length = file.read(m_buffer, length);
          file.close();
          m_buffer[length] = '\0';
        }
        else 
          PR_Free(m_buffer);
      }
    }
  }
  
  if (m_parent && m_parent->m_type &&
        !PL_strcasecmp(m_parent->m_type, MULTIPART_DIGEST) &&
        m_type &&
        (!PL_strcasecmp(m_type, MESSAGE_RFC822) ||
        !PL_strcasecmp(m_type, MESSAGE_NEWS))) 
  {
    // If we're in a multipart/digest, and this document is of type
    // message/rfc822, then it's appropriate to emit no headers.
    //
  }
  else 
  {
    char *message_headers = 0;
    char *content_headers = 0;
    char *content_type_header = 0;
    status = divide_content_headers(m_other,
                                    &message_headers,
                                    &content_headers,
                                    &content_type_header);
    if (status < 0)
      goto FAIL;
    
      /* First, write out all of the headers that refer to the message
      itself (From, Subject, MIME-Version, etc.)
    */
    if (message_headers) 
    {
      PUSH(message_headers);
      PR_Free(message_headers);
      message_headers = 0;
    }

    /* Now allow the crypto library to (potentially) insert some text
       (it may want to wrap the body in an envelope.)           */
    if (!m_parent) {
      status = m_state->BeginCryptoEncapsulation();
      if (status < 0) goto FAIL;
    }
          
    /* Now make sure there's a Content-Type header.
    */
    if (!content_type_header) 
    {
      NS_ASSERTION(m_type && *m_type, "null ptr");
      PRBool needsCharset = mime_type_needs_charset(m_type ? m_type : TEXT_PLAIN);
      if (needsCharset) 
      {
        content_type_header = PR_smprintf("Content-Type: %s; charset=%s" CRLF,
                                          (m_type ? m_type : TEXT_PLAIN), m_charset_name);
      }
      else
        content_type_header = PR_smprintf("Content-Type: %s" CRLF,
                                          (m_type ? m_type : TEXT_PLAIN));
      if (!content_type_header) 
      {
        if (content_headers)
          PR_Free(content_headers);
        status = NS_ERROR_OUT_OF_MEMORY;
        goto FAIL;
      }
    }
    
    /* If this is a compound object, tack a boundary string onto the
    Content-Type header. this
    */
    if (m_numchildren > 0)
    {
      int L;
      char *ct2;
      NS_ASSERTION(m_type, "null ptr");

      if (!separator)
      {
        separator = mime_make_separator("");
        if (!separator)
        {
          status = NS_ERROR_OUT_OF_MEMORY;
          goto FAIL;
        }
      }

      L = PL_strlen(content_type_header);
      
      if (content_type_header[L-1] == nsCRT::LF)
        content_type_header[--L] = 0;
      if (content_type_header[L-1] == nsCRT::CR)
        content_type_header[--L] = 0;
      
      ct2 = PR_smprintf("%s;\r\n boundary=\"%s\"" CRLF, content_type_header, separator);
      PR_Free(content_type_header);
      if (!ct2) 
      {
        if (content_headers)
          PR_Free(content_headers);
        status = NS_ERROR_OUT_OF_MEMORY;
        goto FAIL;
      }
      
      content_type_header = ct2;
    }
    
    // Now write out the Content-Type header...
    NS_ASSERTION(content_type_header && *content_type_header, "null ptr");
    PUSH(content_type_header);
    PR_Free(content_type_header);
    content_type_header = 0;
    
    /* ...followed by all of the other headers that refer to the body of
    the message (Content-Transfer-Encoding, Content-Dispositon, etc.)
    */
    if (content_headers) 
    {
      PUSH(content_headers);
      PR_Free(content_headers);
      content_headers = 0;
    }
  }

  PUSH(CRLF);         // A blank line, to mark the end of headers.

  m_firstBlock = PR_TRUE;
  /* only convert if we need to tag charset */
  m_needIntlConversion = mime_type_needs_charset(m_type);
  
  if (m_buffer) 
  {
    status = PushBody(m_buffer, PL_strlen(m_buffer));
    if (status < 0)
      goto FAIL;
  }
  else if (m_filespec) 
  {
    nsInputFileStream   myStream(*m_filespec);

    if (!myStream.is_open())
    {
      // mysteriously disappearing?
      nsCOMPtr<nsIMsgSendReport> sendReport;
      m_state->GetSendReport(getter_AddRefs(sendReport));
      if (sendReport)
      {
        nsAutoString error_msg;
        nsAutoString path;
        NS_CopyNativeToUnicode(
          nsDependentCString(m_filespec->GetNativePathCString()), path);
        nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_TMP_FILE, error_msg, &path, nsnull);
        sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
      }
      status = NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
      goto FAIL;
    }
    /* Kludge to avoid having to allocate memory on the toy computers... */
    if (!mime_mailto_stream_read_buffer) 
    {
      mime_mailto_stream_read_buffer = (char *) PR_Malloc(MIME_BUFFER_SIZE);
      if (!mime_mailto_stream_read_buffer) 
      {
        status = NS_ERROR_OUT_OF_MEMORY;
        goto FAIL;
      }
    }

    char    *buffer = mime_mailto_stream_read_buffer;
    if (m_strip_sensitive_headers) 
    {
      // We are attaching a message, so we should be careful to
      // strip out certain sensitive internal header fields.
      PRBool skipping = PR_FALSE;

      while (1) 
      {
        char *line;

        if (myStream.eof())
          line = nsnull;
        else
        {
          buffer[0] = '\0';
          myStream.readline(buffer, MIME_BUFFER_SIZE-3);
          line = buffer;
        }
      
        if (!line)
          break;  /* EOF */
        
        if (skipping) {
          if (*line == ' ' || *line == '\t')
            continue;
          else
            skipping = PR_FALSE;
        }
        
        int hdrLen = PL_strlen(buffer);
        if ((hdrLen < 2) || (buffer[hdrLen-2] != nsCRT::CR)) { // if the line doesn't end with CRLF,
          // ... make it end with CRLF.
          if ( (hdrLen == 0) || ((buffer[hdrLen-1] != nsCRT::CR) && (buffer[hdrLen-1] != nsCRT::LF)) )
            hdrLen++;
          buffer[hdrLen-1] = '\015';
          buffer[hdrLen] = '\012';
          buffer[hdrLen+1] = '\0';
        }
        
        if (!PL_strncasecmp(line, "From -", 6) ||
            !PL_strncasecmp(line, "BCC:", 4) ||
            !PL_strncasecmp(line, "FCC:", 4) ||
            !PL_strncasecmp(line, CONTENT_LENGTH ":", CONTENT_LENGTH_LEN+1) ||
            !PL_strncasecmp(line, "Lines:", 6) ||
            !PL_strncasecmp(line, "Status:", 7) ||
            !PL_strncasecmp(line, X_MOZILLA_STATUS ":", X_MOZILLA_STATUS_LEN+1) ||
            !PL_strncasecmp(line, X_MOZILLA_STATUS2 ":", X_MOZILLA_STATUS2_LEN+1) ||
            !PL_strncasecmp(line, X_MOZILLA_DRAFT_INFO ":", X_MOZILLA_DRAFT_INFO_LEN+1) ||
            !PL_strncasecmp(line, X_MOZILLA_NEWSHOST ":", X_MOZILLA_NEWSHOST_LEN+1) ||
            !PL_strncasecmp(line, X_UIDL ":", X_UIDL_LEN+1) ||
            !PL_strncasecmp(line, "X-VM-", 5)) /* hi Kyle */
        {
          skipping = PR_TRUE;
          continue;
        }
        
        PUSH(line);
        
        if (*line == nsCRT::CR || *line == nsCRT::LF) {
          break;  // Now can do normal reads for the body.
        }
      }
    }
        
    while (!myStream.eof()) 
    {
      if ((status = myStream.read(buffer, MIME_BUFFER_SIZE)) < 0)
      {  
        nsCOMPtr<nsIMsgSendReport> sendReport;
        m_state->GetSendReport(getter_AddRefs(sendReport));
        if (sendReport)
        {
          nsAutoString error_msg;
          nsAutoString path;
          NS_CopyNativeToUnicode(nsDependentCString(m_filespec->GetNativePathCString()), path);
          nsMsgBuildErrorMessageByID(NS_MSG_UNABLE_TO_OPEN_FILE, error_msg, &path, nsnull);
          sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), PR_FALSE);
          status = NS_MSG_UNABLE_TO_OPEN_FILE;
          goto FAIL;
        }
      }
      status = PushBody(buffer, status);
      if (status < 0)
        goto FAIL;
    }
  }
  
  if (m_encoder_data) 
  {
    status = MIME_EncoderDestroy(m_encoder_data, PR_FALSE);
    m_encoder_data = nsnull;
    needToWriteCRLFAfterEncodedBody = !m_parent;
    if (status < 0)
      goto FAIL;
  }
  
  // 
  // Ok, from here we loop and drive the the output of all children 
  // for this message.
  //
  if (m_numchildren > 0) 
  {
    PRBool  writeSeparator = PR_TRUE;

    for (int i = 0 ; i < m_numchildren ; i ++) 
    {
      if (writeSeparator)
      {
        PUSH(CRLF);
        PUSH("--");

        PUSH(separator);
        PUSH(CRLF);
      }

      status = m_children[i]->Write();
      if (status < 0)
        goto FAIL;

      if (status == SKIP_EMPTY_PART)
        writeSeparator = PR_FALSE;
      else
        writeSeparator = PR_TRUE;
    }

    PUSH(CRLF);
    PUSH("--");
    PUSH(separator);
    PUSH("--");
    PUSH(CRLF);
  }
  else if (needToWriteCRLFAfterEncodedBody)
    PUSH(CRLF);
  
FAIL:
  PR_FREEIF(separator);
  return status;
}