Ejemplo n.º 1
0
nsresult
nsMsgAttachmentHandler::ConvertToZipFile(nsILocalFileMac *aSourceFile)
{
  // append ".zip" to the real file name
  nsCAutoString zippedName;
  nsresult rv = aSourceFile->GetNativeLeafName(zippedName);
  NS_ENSURE_SUCCESS(rv, rv);
  zippedName.AppendLiteral(".zip");

  // create a temporary file that we'll work on
  nsCOMPtr <nsIFile> tmpFile;
  rv = nsMsgCreateTempFile(zippedName.get(), getter_AddRefs(tmpFile));
  NS_ENSURE_SUCCESS(rv, rv);
  mEncodedWorkingFile = do_QueryInterface(tmpFile);

  // point our URL at the zipped temp file
  NS_NewFileURI(getter_AddRefs(mURL), mEncodedWorkingFile);

  // zip it!
  rv = nsSimpleZipper::Zip(aSourceFile, mEncodedWorkingFile);
  NS_ENSURE_SUCCESS(rv, rv);

  // set some metadata for this attachment, that will affect the MIME headers.
  m_type = APPLICATION_ZIP;
  m_realName = zippedName.get();

  return NS_OK;
}
Ejemplo n.º 2
0
nsresult
nsMsgAttachmentHandler::ConvertToAppleEncoding(const nsCString &aFileURI, 
                                               const nsCString &aFilePath, 
                                               nsILocalFileMac *aSourceFile)
{
  // convert the apple file to AppleDouble first, and then patch the
  // address in the url.
  
  //We need to retrieve the file type and creator...

  char fileInfo[32];
  OSType type, creator;

  nsresult rv = aSourceFile->GetFileType(&type);
  if (NS_FAILED(rv))
    return false;
  PR_snprintf(fileInfo, sizeof(fileInfo), "%X", type);
  m_xMacType = fileInfo;

  rv = aSourceFile->GetFileCreator(&creator);
  if (NS_FAILED(rv))
    return false;
  PR_snprintf(fileInfo, sizeof(fileInfo), "%X", creator);
  m_xMacCreator = fileInfo;

  FSRef fsRef;
  aSourceFile->GetFSRef(&fsRef);
  bool sendResourceFork = HasResourceFork(&fsRef);

  // if we have a resource fork, check the filename extension, maybe we don't need the resource fork!
  if (sendResourceFork)
  {
    nsCOMPtr<nsIURL> fileUrl(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
    if (fileUrl)
    {
      rv = fileUrl->SetSpec(aFileURI);
      if (NS_SUCCEEDED(rv))
      {
        nsCAutoString ext;
        rv = fileUrl->GetFileExtension(ext);
        if (NS_SUCCEEDED(rv) && !ext.IsEmpty())
        {
          sendResourceFork =
          PL_strcasecmp(ext.get(), "TXT") &&
          PL_strcasecmp(ext.get(), "JPG") &&
          PL_strcasecmp(ext.get(), "GIF") &&
          PL_strcasecmp(ext.get(), "TIF") &&
          PL_strcasecmp(ext.get(), "HTM") &&
          PL_strcasecmp(ext.get(), "HTML") &&
          PL_strcasecmp(ext.get(), "ART") &&
          PL_strcasecmp(ext.get(), "XUL") &&
          PL_strcasecmp(ext.get(), "XML") &&
          PL_strcasecmp(ext.get(), "CSS") &&
          PL_strcasecmp(ext.get(), "JS");
        }
      }
    }
  }

  // Only use appledouble if we aren't uuencoding.
  if( sendResourceFork )
  {
    char *separator;

    separator = mime_make_separator("ad");
    if (!separator)
      return NS_ERROR_OUT_OF_MEMORY;

    nsCOMPtr <nsIFile> tmpFile;
    nsresult rv = nsMsgCreateTempFile("appledouble", getter_AddRefs(tmpFile));
    if (NS_SUCCEEDED(rv))
      mEncodedWorkingFile = do_QueryInterface(tmpFile);
    if (!mEncodedWorkingFile)
    {
      PR_FREEIF(separator);
      return NS_ERROR_OUT_OF_MEMORY;
    }

    //
    // RICHIE_MAC - ok, here's the deal, we have a file that we need
    // to encode in appledouble encoding for the resource fork and put that
    // into the mEncodedWorkingFile location. Then, we need to patch the new file
    // spec into the array and send this as part of the 2 part appledouble/mime
    // encoded mime part.
    //
    AppleDoubleEncodeObject     *obj = new (AppleDoubleEncodeObject);
    if (obj == NULL)
    {
      mEncodedWorkingFile = nsnull;
      PR_FREEIF(separator);
      return NS_ERROR_OUT_OF_MEMORY;
    }

    rv = MsgGetFileStream(mEncodedWorkingFile, getter_AddRefs(obj->fileStream));
    if (NS_FAILED(rv) || !obj->fileStream)
    {
      PR_FREEIF(separator);
      delete obj;
      return NS_ERROR_OUT_OF_MEMORY;
    }

    PRInt32     bSize = AD_WORKING_BUFF_SIZE;

    char  *working_buff = nsnull;
    while (!working_buff && (bSize >= 512))
    {
      working_buff = (char *)PR_CALLOC(bSize);
      if (!working_buff)
        bSize /= 2;
    }

    if (!working_buff)
    {
      PR_FREEIF(separator);
      delete obj;
      return NS_ERROR_OUT_OF_MEMORY;
    }

    obj->buff = working_buff;
    obj->s_buff = bSize;

    //
    //  Setup all the need information on the apple double encoder.
    //
    ap_encode_init(&(obj->ap_encode_obj), aFilePath.get(), separator);

    PRInt32 count;

    nsresult status = noErr;
    m_size = 0;
    while (status == noErr)
    {
      status = ap_encode_next(&(obj->ap_encode_obj), obj->buff, bSize, &count);
      if (status == noErr || status == errDone)
      {
        //
        // we got the encode data, so call the next stream to write it to the disk.
        //
        PRUint32 bytesWritten;
        obj->fileStream->Write(obj->buff, count, &bytesWritten);
        if (bytesWritten != (PRUint32) count)
          status = NS_MSG_ERROR_WRITING_FILE;
      }
    }

    ap_encode_end(&(obj->ap_encode_obj), (status >= 0)); // if this is true, ok, false abort
    if (obj->fileStream)
      obj->fileStream->Close();

    PR_FREEIF(obj->buff);               /* free the working buff.   */
    PR_FREEIF(obj);

    nsCOMPtr <nsIURI> fileURI;
    NS_NewFileURI(getter_AddRefs(fileURI), mEncodedWorkingFile);

    nsCOMPtr<nsIFileURL> theFileURL = do_QueryInterface(fileURI, &rv);
    NS_ENSURE_SUCCESS(rv,rv);

    nsCString newURLSpec;
    NS_ENSURE_SUCCESS(rv, rv);
    fileURI->GetSpec(newURLSpec);

    if (newURLSpec.IsEmpty())
    {
      PR_FREEIF(separator);
      return NS_ERROR_OUT_OF_MEMORY;
    }

    if (NS_FAILED(nsMsgNewURL(getter_AddRefs(mURL), newURLSpec.get())))
    {
      PR_FREEIF(separator);
      return NS_ERROR_OUT_OF_MEMORY;
    }

    // Now after conversion, also patch the types.
    char        tmp[128];
    PR_snprintf(tmp, sizeof(tmp), MULTIPART_APPLEDOUBLE ";\r\n boundary=\"%s\"", separator);
    PR_FREEIF(separator);
    m_type = tmp;
  }
  else
  {
    if ( sendResourceFork )
    {
      // For now, just do the encoding, but in the old world we would ask the
      // user about doing this conversion
      printf("...we could ask the user about this conversion, but for now, nahh..\n");
    }

    bool      useDefault;
    char      *macType, *macEncoding;
    if (m_type.IsEmpty() || m_type.LowerCaseEqualsLiteral(TEXT_PLAIN))
    {
# define TEXT_TYPE  0x54455854  /* the characters 'T' 'E' 'X' 'T' */
# define text_TYPE  0x74657874  /* the characters 't' 'e' 'x' 't' */

      if (type != TEXT_TYPE && type != text_TYPE)
      {
        MacGetFileType(aSourceFile, &useDefault, &macType, &macEncoding);
        m_type = macType;
      }
    }
    // don't bother to set the types if we failed in getting the file info.
  }

  return NS_OK;
}
Ejemplo n.º 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 = true;

  rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mOutFile), mTmpFile, -1, 00600);
  if (NS_FAILED(rv) || !mOutFile)
  {
    if (m_mime_delivery_state)
    {
      nsCOMPtr<nsIMsgSendReport> sendReport;
      m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport));
      if (sendReport)
      {
        nsAutoString error_msg;
        nsMsgBuildMessageWithTmpFile(mTmpFile, error_msg);
        sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false);
      }
    }
    mTmpFile->Remove(false);
    mTmpFile = nsnull;
    return NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
  }

  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()));
    nsCAutoString unescapedFilePath;
    MsgUnescapeString(filePath, 0, unescapedFilePath);

    nsCOMPtr<nsILocalFile> sourceFile;
    NS_NewNativeLocalFile(unescapedFilePath, 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));
    bool isPackage;
    macFile->IsPackage(&isPackage);
    if (isPackage)
      rv = ConvertToZipFile(macFile);
    else
      rv = ConvertToAppleEncoding(sourceURISpec, unescapedFilePath, 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);
}
Ejemplo n.º 4
0
nsresult
nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields)
{
  nsresult rv = NS_ERROR_INVALID_ARG;
  nsCOMPtr <nsIMsgMessageService> messageService;

  if (m_uri.Find("-message:", CaseInsensitiveCompare) != -1)
  {
    nsCOMPtr <nsIFile> tmpFile;
    rv = nsMsgCreateTempFile("nsmail.tmp", getter_AddRefs(tmpFile));
    NS_ENSURE_SUCCESS(rv, rv);
    mTmpFile = do_QueryInterface(tmpFile);
    mDeleteFile = true;
    mCompFields = compFields;
    m_type = MESSAGE_RFC822;
    m_overrideType = MESSAGE_RFC822;
    if (!mTmpFile)
    {
      rv = NS_ERROR_FAILURE;
      goto done;
    }

    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mOutFile), mTmpFile, -1, 00600);
    if (NS_FAILED(rv) || !mOutFile)
    {
      if (m_mime_delivery_state)
      {
        nsCOMPtr<nsIMsgSendReport> sendReport;
        m_mime_delivery_state->GetSendReport(getter_AddRefs(sendReport));
        if (sendReport)
        {
          nsAutoString error_msg;
          nsMsgBuildMessageWithTmpFile(mTmpFile, error_msg);
          sendReport->SetMessage(nsIMsgSendReport::process_Current, error_msg.get(), false);
        }
      }
      rv =  NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
      goto done;
    }

    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(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(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(false);
        mTmpFile = nsnull;
      }
  }

  return rv;
}
Ejemplo n.º 5
0
int
MimePartBufferWrite (MimePartBufferData *data,
           const char *buf, PRInt32 size)
{
  NS_ASSERTION(data && buf && size > 0, "MimePartBufferWrite: Bad param");
  if (!data || !buf || size <= 0)
    return -1;

  /* If we don't yet have a buffer (either memory or file) try and make a
    memory buffer.
    */
  if (!data->part_buffer &&
      !data->file_buffer)
  {
    int target_size = TARGET_MEMORY_BUFFER_SIZE;
    while (target_size > 0)
    {
      data->part_buffer = (char *) PR_MALLOC(target_size);
      if (data->part_buffer) break;          /* got it! */
      target_size -= TARGET_MEMORY_BUFFER_QUANTUM;  /* decrease it and try
        again */
    }

    if (data->part_buffer)
      data->part_buffer_size = target_size;
    else
      data->part_buffer_size = 0;

    data->part_buffer_fp = 0;
  }

  /* Ok, if at this point we still don't have either kind of buffer, try and
    make a file buffer. */
  if (!data->part_buffer && !data->file_buffer)
  {
    nsCOMPtr <nsIFile> tmpFile;
    nsresult rv = nsMsgCreateTempFile("nsma", getter_AddRefs(tmpFile));
    NS_ENSURE_SUCCESS(rv, MIME_UNABLE_TO_OPEN_TMP_FILE);
    data->file_buffer = do_QueryInterface(tmpFile);

    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(data->output_file_stream), data->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  NS_ASSERTION(data->part_buffer || data->output_file_stream, "no part_buffer or file_stream");

  /* If this buf will fit in the memory buffer, put it there.
    */
  if (data->part_buffer &&
      data->part_buffer_fp + size < data->part_buffer_size)
  {
    memcpy(data->part_buffer + data->part_buffer_fp,
           buf, size);
    data->part_buffer_fp += size;
  }

  /* Otherwise it won't fit; write it to the file instead. */
  else
  {
    /* If the file isn't open yet, open it, and dump the memory buffer
    to it. */
    if (!data->output_file_stream)
    {
      nsresult rv;
      if (!data->file_buffer)
      {
        nsCOMPtr <nsIFile> tmpFile;
        rv = nsMsgCreateTempFile("nsma", getter_AddRefs(tmpFile));
        NS_ENSURE_SUCCESS(rv, MIME_UNABLE_TO_OPEN_TMP_FILE);
        data->file_buffer = do_QueryInterface(tmpFile);

      }

      rv = MsgNewBufferedFileOutputStream(getter_AddRefs(data->output_file_stream), data->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
      NS_ENSURE_SUCCESS(rv, MIME_UNABLE_TO_OPEN_TMP_FILE);

      if (data->part_buffer && data->part_buffer_fp)
      {
        PRUint32 bytesWritten;
        nsresult rv = data->output_file_stream->Write(data->part_buffer,
                                                 data->part_buffer_fp, &bytesWritten);
        NS_ENSURE_SUCCESS(rv, rv);
      }

      PR_FREEIF(data->part_buffer);
      data->part_buffer_fp = 0;
      data->part_buffer_size = 0;
    }

    /* Dump this buf to the file. */
    PRUint32 bytesWritten;
    nsresult rv = data->output_file_stream->Write (buf, size, &bytesWritten);
    if (NS_FAILED(rv) || (PRInt32) bytesWritten < size)
      return MIME_OUT_OF_MEMORY;
  }

  return 0;
}
Ejemplo n.º 6
0
static int
MimeMultipartRelated_parse_child_line (MimeObject *obj,
                     const char *line, int32_t length,
                     bool first_line_p)
{
  MimeContainer *cont = (MimeContainer *) obj;
  MimeMultipartRelated *relobj = (MimeMultipartRelated *) obj;
  int status;
  MimeObject *kid;

  if (obj->options && !obj->options->write_html_p
#ifdef MIME_DRAFTS
    && !obj->options->decompose_file_p
#endif /* MIME_DRAFTS */
    )
    {
    /* Oh, just go do the normal thing... */
    return ((MimeMultipartClass*)&MIME_SUPERCLASS)->
      parse_child_line(obj, line, length, first_line_p);
    }

  /* Throw it away if this isn't the head object.  (Someday, maybe we'll
     cache it instead.) */
  PR_ASSERT(cont->nchildren > 0);
  if (cont->nchildren <= 0)
    return -1;
  kid = cont->children[cont->nchildren-1];
  PR_ASSERT(kid);
  if (!kid) return -1;
  if (kid != relobj->headobj) return 0;

  /* Buffer this up (###tw much code duplication from mimemalt.c) */
  /* If we don't yet have a buffer (either memory or file) try and make a
     memory buffer. */
  if (!relobj->head_buffer && !relobj->file_buffer) {
    int target_size = 1024 * 50;       /* try for 50k */
    while (target_size > 0) {
      relobj->head_buffer = (char *) PR_MALLOC(target_size);
      if (relobj->head_buffer) break;  /* got it! */
      target_size -= (1024 * 5);     /* decrease it and try again */
    }

    if (relobj->head_buffer) {
      relobj->head_buffer_size = target_size;
    } else {
      relobj->head_buffer_size = 0;
    }

    relobj->head_buffer_fp = 0;
  }

  nsresult rv;
  /* Ok, if at this point we still don't have either kind of buffer, try and
     make a file buffer. */
  if (!relobj->head_buffer && !relobj->file_buffer)
  {
    nsCOMPtr <nsIFile> file;
    rv = nsMsgCreateTempFile("nsma", getter_AddRefs(file));
    NS_ENSURE_SUCCESS(rv, rv);
    relobj->file_buffer = do_QueryInterface(file);

    rv = MsgNewBufferedFileOutputStream(getter_AddRefs(relobj->output_file_stream), relobj->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  PR_ASSERT(relobj->head_buffer || relobj->output_file_stream);


  /* If this line will fit in the memory buffer, put it there.
   */
  if (relobj->head_buffer &&
      relobj->head_buffer_fp + length < relobj->head_buffer_size) {
    memcpy(relobj->head_buffer + relobj->head_buffer_fp, line, length);
    relobj->head_buffer_fp += length;
  } else {
    /* Otherwise it won't fit; write it to the file instead. */

    /* If the file isn't open yet, open it, and dump the memory buffer
       to it. */
    if (!relobj->output_file_stream)
    {
      if (!relobj->file_buffer)
      {
        nsCOMPtr <nsIFile> file;
        rv = nsMsgCreateTempFile("nsma", getter_AddRefs(file));
        NS_ENSURE_SUCCESS(rv, rv);
        relobj->file_buffer = do_QueryInterface(file);
      }

      nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(relobj->output_file_stream), relobj->file_buffer, PR_WRONLY | PR_CREATE_FILE, 00600);
      NS_ENSURE_SUCCESS(rv, rv);

      if (relobj->head_buffer && relobj->head_buffer_fp)
      {
        uint32_t bytesWritten;
        status = relobj->output_file_stream->Write(relobj->head_buffer,
                                                   relobj->head_buffer_fp,
                                                   &bytesWritten);
        if (bytesWritten < relobj->head_buffer_fp)
          return MIME_UNABLE_TO_OPEN_TMP_FILE;
      }

      PR_FREEIF(relobj->head_buffer);
      relobj->head_buffer_fp = 0;
      relobj->head_buffer_size = 0;
    }

    /* Dump this line to the file. */
    uint32_t bytesWritten;
    rv = relobj->output_file_stream->Write(line, length, &bytesWritten);
    if ((int32_t) bytesWritten < length || NS_FAILED(rv))
      return MIME_UNABLE_TO_OPEN_TMP_FILE;
  }

  return 0;
}
Ejemplo n.º 7
0
nsresult
nsMsgSendLater::StartNextMailFileSend(nsresult prevStatus)
{
  bool hasMoreElements = false;
  if ((!mEnumerator) ||
      NS_FAILED(mEnumerator->HasMoreElements(&hasMoreElements)) ||
      !hasMoreElements)
  {
    // Notify that this message has finished being sent.
    NotifyListenersOnProgress(mTotalSendCount, mMessagesToSend.Count(), 100, 100);

    // EndSendMessages resets everything for us
    EndSendMessages(prevStatus, nullptr, mTotalSendCount, mTotalSentSuccessfully);

    // XXX Should we be releasing references so that we don't hold onto items
    // unnecessarily.
    return NS_OK;
  }

  // If we've already sent a message, and are sending more, send out a progress
  // update with 100% for both send and copy as we must have finished by now.
  if (mTotalSendCount)
    NotifyListenersOnProgress(mTotalSendCount, mMessagesToSend.Count(), 100, 100);

  nsCOMPtr<nsISupports> currentItem;
  nsresult rv = mEnumerator->GetNext(getter_AddRefs(currentItem));
  NS_ENSURE_SUCCESS(rv, rv);

  mMessage = do_QueryInterface(currentItem); 
  if (!mMessage)
    return NS_ERROR_NOT_AVAILABLE;

  if (!mMessageFolder)
    return NS_ERROR_UNEXPECTED;

  nsCString messageURI;
  mMessageFolder->GetUriForMsg(mMessage, messageURI);

  rv = nsMsgCreateTempFile("nsqmail.tmp", getter_AddRefs(mTempFile)); 
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIMsgMessageService> messageService;
  rv = GetMessageServiceFromURI(messageURI, getter_AddRefs(messageService));
  if (NS_FAILED(rv) && !messageService)
    return NS_ERROR_FACTORY_NOT_LOADED;

  ++mTotalSendCount;

  nsCString identityKey;
  rv = mMessage->GetStringProperty(HEADER_X_MOZILLA_IDENTITY_KEY,
                                   getter_Copies(identityKey));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIMsgIdentity> identity;
  rv = GetIdentityFromKey(identityKey.get(), getter_AddRefs(identity));
  NS_ENSURE_SUCCESS(rv, rv);

  // Notify that we're just about to start sending this message
  NotifyListenersOnMessageStartSending(mTotalSendCount, mMessagesToSend.Count(),
                                       identity);

  // Setup what we need to parse the data stream correctly
  m_inhead = true;
  m_headersFP = 0;
  m_headersPosition = 0;
  m_bytesRead = 0;
  m_position = 0;
  m_flagsPosition = 0;
  m_headersSize = 0;
  PR_FREEIF(mLeftoverBuffer);

  // Now, get our stream listener interface and plug it into the DisplayMessage
  // operation
  AddRef();

  rv = messageService->DisplayMessage(messageURI.get(),
                                      static_cast<nsIStreamListener*>(this),
                                      nullptr, nullptr, nullptr, nullptr);

  Release();

  return rv;
}