make message sending scriptable, r=protz, sr=neil, bug 679476
authorDavid Bienvenu <bienvenu@nventure.com>
Thu, 22 Sep 2011 07:27:20 -0700
changeset 8532 9b1d6d96451a4fb97d261f13685e77f049a4d42e
parent 8531 dfe1e3af4773acdd80f42516a25409b7e6c82fd6
child 8533 2e9070d54ee683515cbbfae062fd6e756fcbde46
push id6556
push userbienvenu@nventure.com
push dateThu, 22 Sep 2011 14:27:13 +0000
treeherdercomm-central@9b1d6d96451a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersprotz, neil, bug
bugs679476
make message sending scriptable, r=protz, sr=neil, bug 679476
mailnews/build/nsMailModule.cpp
mailnews/compose/public/nsIMsgCompose.idl
mailnews/compose/public/nsIMsgSend.idl
mailnews/compose/public/nsMsgCompCID.h
mailnews/compose/src/nsMsgAttachmentHandler.cpp
mailnews/compose/src/nsMsgAttachmentHandler.h
mailnews/compose/src/nsMsgCompUtils.cpp
mailnews/compose/src/nsMsgCompose.cpp
mailnews/compose/src/nsMsgSend.cpp
mailnews/compose/src/nsMsgSend.h
mailnews/import/eudora/src/nsEudoraCompose.cpp
mailnews/import/eudora/src/nsEudoraCompose.h
mailnews/import/eudora/src/nsEudoraImport.cpp
mailnews/import/outlook/src/MapiMessage.cpp
mailnews/import/outlook/src/MapiMessage.h
mailnews/import/outlook/src/nsOutlookCompose.cpp
mailnews/import/public/nsIImportService.idl
mailnews/import/src/nsImportService.cpp
mailnews/mime/src/mimedrft.cpp
mailnews/mime/src/mimehdrs.cpp
mailnews/mime/src/mimehdrs.h
mailnews/mime/src/mimemoz2.cpp
mailnews/mime/src/mimemoz2.h
mailnews/mime/src/mimemrel.cpp
mailnews/mime/src/nsStreamConverter.cpp
--- a/mailnews/build/nsMailModule.cpp
+++ b/mailnews/build/nsMailModule.cpp
@@ -569,16 +569,18 @@ NS_DEFINE_NAMED_CID(NS_BAYESIANFILTER_CI
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSmtpService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSmtpServer)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgCompose)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgComposeParams)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgComposeSendListener)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgComposeProgressParams)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgCompFields)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgAttachment)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgAttachmentData)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgAttachedFile)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgComposeAndSend)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgSendLater, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgComposeService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgComposeContentHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgQuote)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgQuoteListener)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSmtpUrl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMailtoUrl)
@@ -588,16 +590,18 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgComp
 NS_DEFINE_NAMED_CID(NS_MSGCOMPOSE_CID);
 NS_DEFINE_NAMED_CID(NS_MSGCOMPOSESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MSGCOMPOSECONTENTHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_MSGCOMPOSEPARAMS_CID);
 NS_DEFINE_NAMED_CID(NS_MSGCOMPOSESENDLISTENER_CID);
 NS_DEFINE_NAMED_CID(NS_MSGCOMPOSEPROGRESSPARAMS_CID);
 NS_DEFINE_NAMED_CID(NS_MSGCOMPFIELDS_CID);
 NS_DEFINE_NAMED_CID(NS_MSGATTACHMENT_CID);
+NS_DEFINE_NAMED_CID(NS_MSGATTACHMENTDATA_CID);
+NS_DEFINE_NAMED_CID(NS_MSGATTACHEDFILE_CID);
 NS_DEFINE_NAMED_CID(NS_MSGSEND_CID);
 NS_DEFINE_NAMED_CID(NS_MSGSENDLATER_CID);
 NS_DEFINE_NAMED_CID(NS_SMTPSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SMTPSERVER_CID);
 NS_DEFINE_NAMED_CID(NS_SMTPURL_CID);
 NS_DEFINE_NAMED_CID(NS_MAILTOURL_CID);
 NS_DEFINE_NAMED_CID(NS_MSGQUOTE_CID);
 NS_DEFINE_NAMED_CID(NS_MSGQUOTELISTENER_CID);
@@ -906,16 +910,18 @@ const mozilla::Module::CIDEntry kMailNew
   { &kNS_MSGCOMPOSE_CID, false, NULL, nsMsgComposeConstructor},
   { &kNS_MSGCOMPOSESERVICE_CID, false, NULL, nsMsgComposeServiceConstructor},
   { &kNS_MSGCOMPOSECONTENTHANDLER_CID, false, NULL, nsMsgComposeContentHandlerConstructor},
   { &kNS_MSGCOMPOSEPARAMS_CID, false, NULL, nsMsgComposeParamsConstructor},
   { &kNS_MSGCOMPOSESENDLISTENER_CID, false, NULL, nsMsgComposeSendListenerConstructor},
   { &kNS_MSGCOMPOSEPROGRESSPARAMS_CID, false, NULL, nsMsgComposeProgressParamsConstructor},
   { &kNS_MSGCOMPFIELDS_CID, false, NULL, nsMsgCompFieldsConstructor},
   { &kNS_MSGATTACHMENT_CID, false, NULL, nsMsgAttachmentConstructor},
+  { &kNS_MSGATTACHMENTDATA_CID, false, NULL, nsMsgAttachmentDataConstructor},
+  { &kNS_MSGATTACHEDFILE_CID, false, NULL, nsMsgAttachedFileConstructor},
   { &kNS_MSGSEND_CID, false, NULL, nsMsgComposeAndSendConstructor},
   { &kNS_MSGSENDLATER_CID, false, NULL, nsMsgSendLaterConstructor},
   { &kNS_SMTPSERVICE_CID, false, NULL, nsSmtpServiceConstructor},
   { &kNS_SMTPSERVER_CID, false, NULL, nsSmtpServerConstructor},
   { &kNS_SMTPURL_CID, false, NULL, nsSmtpUrlConstructor},
   { &kNS_MAILTOURL_CID, false, NULL, nsMailtoUrlConstructor},
   { &kNS_MSGQUOTE_CID, false, NULL, nsMsgQuoteConstructor},
   { &kNS_MSGQUOTELISTENER_CID, false, NULL, nsMsgQuoteListenerConstructor},
@@ -1107,16 +1113,18 @@ const mozilla::Module::ContractIDEntry k
   { NS_MSGCOMPOSESERVICE_CONTRACTID, &kNS_MSGCOMPOSESERVICE_CID },
   { NS_MSGCOMPOSESTARTUPHANDLER_CONTRACTID, &kNS_MSGCOMPOSESERVICE_CID },
   { NS_MSGCOMPOSECONTENTHANDLER_CONTRACTID, &kNS_MSGCOMPOSECONTENTHANDLER_CID },
   { NS_MSGCOMPOSEPARAMS_CONTRACTID, &kNS_MSGCOMPOSEPARAMS_CID },
   { NS_MSGCOMPOSESENDLISTENER_CONTRACTID, &kNS_MSGCOMPOSESENDLISTENER_CID },
   { NS_MSGCOMPOSEPROGRESSPARAMS_CONTRACTID, &kNS_MSGCOMPOSEPROGRESSPARAMS_CID },
   { NS_MSGCOMPFIELDS_CONTRACTID, &kNS_MSGCOMPFIELDS_CID },
   { NS_MSGATTACHMENT_CONTRACTID, &kNS_MSGATTACHMENT_CID },
+  { NS_MSGATTACHMENTDATA_CONTRACTID, &kNS_MSGATTACHMENTDATA_CID },
+  { NS_MSGATTACHEDFILE_CONTRACTID, &kNS_MSGATTACHEDFILE_CID },
   { NS_MSGSEND_CONTRACTID, &kNS_MSGSEND_CID },
   { NS_MSGSENDLATER_CONTRACTID, &kNS_MSGSENDLATER_CID },
   { NS_SMTPSERVICE_CONTRACTID, &kNS_SMTPSERVICE_CID },
   { NS_MAILTOHANDLER_CONTRACTID, &kNS_SMTPSERVICE_CID },
   { NS_SMTPSERVER_CONTRACTID, &kNS_SMTPSERVER_CID },
   { NS_SMTPURL_CONTRACTID, &kNS_SMTPURL_CID },
   { NS_MAILTOURL_CONTRACTID, &kNS_MAILTOURL_CID },
   { NS_MSGQUOTE_CONTRACTID, &kNS_MSGQUOTE_CID },
--- a/mailnews/compose/public/nsIMsgCompose.idl
+++ b/mailnews/compose/public/nsIMsgCompose.idl
@@ -313,15 +313,15 @@ interface nsIMsgCompose : nsIMsgSendList
   void addMsgSendListener(in nsIMsgSendListener sendListener);
 
   /* for easier use of nsIMsgSendListener */
   void removeMsgSendListener(in nsIMsgSendListener sendListener);
 
 };
 
 /* send listener interface */
-[noscript, uuid(ACC72780-2CEA-11D5-9DAA-BACDEAC1EEFC)]
+[uuid(ACC72780-2CEA-11D5-9DAA-BACDEAC1EEFC)]
 interface nsIMsgComposeSendListener : nsISupports {
 
   void setMsgCompose(in nsIMsgCompose msgCompose);
   void setDeliverMode(in MSG_DeliverMode deliverMode);
  
 };
--- a/mailnews/compose/public/nsIMsgSend.idl
+++ b/mailnews/compose/public/nsIMsgSend.idl
@@ -51,126 +51,213 @@
 #include "nsIMsgSendReport.idl"
 #include "domstubs.idl"
 #include "nsIPrompt.idl"
 #include "MailNewsTypes2.idl"
 #include "nsIMsgComposeParams.idl"
 
 %{C++
 #include "nsIURL.h"
+#include "nsStringGlue.h"
 %}
 
 interface nsIMsgProgress;
 interface nsIURI;
 interface nsIRequest;
 interface nsIMsgDBHdr;
 interface nsIMsgHdr;
 interface nsIDocShell;
 interface nsIFile;
 interface nsILocalFile;
 interface nsIOutputStream;
 interface nsIMsgComposeSecure;
 interface nsIMsgStatusFeedback;
 interface nsIEditor;
+interface nsIArray;
 
 typedef long nsMsgDeliverMode;
 
-%{ C++
-//
-// Callback declarations for message delivery
-//
-// For completion of send/message creation operations...
-typedef nsresult (*nsMsgSendCompletionCallback) (nsresult aExitCode, void *tagData, nsILocalFile *returnFile);
+[scriptable, uuid(d664fd40-87b6-487f-a01f-c54ab2e29314)]
+interface nsIMsgAttachmentData : nsISupports
+{
+  /// The URL to attach.
+  attribute nsIURI url;
+
+  /**
+   * The type to which this document should be
+   * converted.  Legal values are NULL, TEXT_PLAIN
+   * and APPLICATION_POSTSCRIPT (which are macros
+   * defined in net.h); other values are ignored.
+   */
+  attribute ACString desiredType;
+
+  /**
+   * The type of the URL if known, otherwise empty. For example, if
+   * you were attaching a temp file which was known to contain HTML data,
+   * you would pass in TEXT_HTML as the realType, to override whatever type
+   * the name of the tmp file might otherwise indicate.
+   */
+  attribute ACString realType;
+
+  /// Goes along with real_type.
+  attribute ACString realEncoding; 
+
+  /**
+   * The original name of this document, which will eventually show up in the
+   * Content-Disposition header. For example, if you had copied a document to a
+   * tmp file, this would be the original, human-readable name of the document.
+   */
+  attribute ACString realName;
+  /**
+   * If you put a string here, it will show up as the Content-Description
+   * header. This can be any explanatory text; it's not a file name.
+   */
+  attribute ACString description;
+
+  /// mac-specific info
+  attribute ACString xMacType;
+
+  /// mac-specific info
+  attribute ACString xMacCreator;
+};
 
-// For completion of sending unsent messages operations...
-typedef nsresult (*nsMsgSendUnsentMessagesCallback) (nsresult aExitCode, PRUint32 totalSentCount,
-                                                     PRUint32 totalSentSuccessfully, void *tagData);
-%}
+/**
+ * When we have downloaded a URL to a tmp file for attaching, this
+ * represents everything we learned about it (and did to it) in the
+ * process.
+ */
+[scriptable, uuid(156bad99-c5a1-425d-8319-3e79c02571d4)]
+interface nsIMsgAttachedFile : nsISupports
+{
+  /// Where it came from on the network (or even elsewhere on the local disk.)
+  attribute nsIURI origUrl;
+
+  /// The tmp file in which the (possibly converted) data now resides.
+  attribute nsILocalFile tmpFile;
+
+  /// The type of the data in file_name (not necessarily the same as the type of orig_url.)
+  attribute ACString type;
+
+  /**
+   * The encoding of the tmp file. This will be set only if the original
+   * document had an encoding already; we don't do base64 encoding and so forth
+   * until it's time to assemble a full MIME message of all parts.
+   */
+  attribute ACString encoding;
+  /// For Content-Description header.
+  attribute ACString description;
+
+  attribute ACString xMacType;    // mac-specific info 
+  attribute ACString xMacCreator; // mac-specific info 
+  attribute ACString realName;      // The real name of the file. 
+
+  /**
+   * Some statistics about the data that was written to the file, so that when
+   * it comes time to compose a MIME message, we can make an informed decision
+   * about what Content-Transfer-Encoding would be best for this attachment.
+   * (If it's encoded already, we ignore this information and ship it as-is.)
+   */
+  attribute unsigned long size;
+  attribute unsigned long unprintableCount;
+  attribute unsigned long highbitCount;
+  attribute unsigned long ctlCount;
+  attribute unsigned long nullCount;
+  attribute unsigned long maxLineLength;
+};
 
 %{ C++
 // Forward declaration
 class nsMsgAttachmentHandler;
 
-// Attachment file/URL structures
-struct nsMsgAttachmentData
+// Attachment file/URL structures - we're letting libmime use this directly
+class nsMsgAttachmentData : public nsIMsgAttachmentData
 {
-  nsIURI* url;            // The URL to attach. This should be 0 to signify "end of list".
+public:
+  NS_DECL_NSIMSGATTACHMENTDATA
+  NS_DECL_ISUPPORTS
 
-  char *desired_type;      // The type to which this document should be
+  nsMsgAttachmentData();
+  ~nsMsgAttachmentData();
+
+  nsCOMPtr<nsIURI> m_url; // The URL to attach.
+
+  nsCString m_desiredType; // The type to which this document should be
                           // converted.  Legal values are NULL, TEXT_PLAIN
                           // and APPLICATION_POSTSCRIPT (which are macros
                           // defined in net.h); other values are ignored.
 
-  char *real_type;        // The type of the URL if known, otherwise NULL. For example, if 
+  nsCString m_realType;        // The type of the URL if known, otherwise NULL. For example, if 
                           // you were attaching a temp file which was known to contain HTML data, 
                           // you would pass in TEXT_HTML as the real_type, to override whatever type 
                           // the name of the tmp file might otherwise indicate.
 
-  char *real_encoding;    // Goes along with real_type 
+  nsCString m_realEncoding;    // Goes along with real_type 
 
-  char *real_name;        // The original name of this document, which will eventually show up in the 
+  nsCString m_realName;        // The original name of this document, which will eventually show up in the 
                           // Content-Disposition header. For example, if you had copied a document to a 
                           // tmp file, this would be the original, human-readable name of the document.
 
-  char *description;      // If you put a string here, it will show up as the Content-Description header.  
+  nsCString m_description;      // If you put a string here, it will show up as the Content-Description header.  
                           // This can be any explanatory text; it's not a file name.             
 
-  char *x_mac_type, *x_mac_creator; // Mac-specific data that should show up as optional parameters
-                                    // to the content-type header.
-  PRInt32 size;                  // The size of the attachment. May be 0.
-  PRBool  isExternalAttachment;  // Flag for determining if the attachment is external
-  PRBool  isDownloaded;          // Flag for determining if the attachment has already been downloaded
-  PRBool  hasFilename;           // Tells whether the name is provided by us or if it's a Part 1.2-like attachment
+  // Mac-specific data that should show up as optional parameters
+  // to the content-type header.
+  nsCString m_xMacType;
+  nsCString m_xMacCreator;
+
+  PRInt32 m_size;                  // The size of the attachment. May be 0.
+  PRBool  m_isExternalAttachment;  // Flag for determining if the attachment is external
+  PRBool  m_isDownloaded;          // Flag for determining if the attachment has already been downloaded
+  PRBool  m_hasFilename;           // Tells whether the name is provided by us or if it's a Part 1.2-like attachment
 };
 
-
-//
-// When we have downloaded a URL to a tmp file for attaching, this
-// represents everything we learned about it (and did to it) in the
-// process. 
-//
-typedef struct nsMsgAttachedFile
+class nsMsgAttachedFile : public nsIMsgAttachedFile
 {
-  nsCOMPtr<nsIURI> orig_url;  // Where it came from on the network (or even elsewhere on the local disk.)
+public:
+  NS_DECL_NSIMSGATTACHEDFILE
+  NS_DECL_ISUPPORTS
+
+  nsMsgAttachedFile();
+  ~nsMsgAttachedFile();
 
-  nsCOMPtr <nsILocalFile>  tmp_file;    // The tmp file in which the (possibly converted) data now resides.
-  
-  char        *type;        // The type of the data in file_name (not necessarily the same as the type of orig_url.)
+  nsCOMPtr<nsIURI> m_origUrl; // Where it came from on the network (or even elsewhere on the local disk.)
+
+  nsCOMPtr<nsILocalFile>  m_tmpFile;    // The tmp file in which the (possibly converted) data now resides.
 
-  char        *encoding;    // Likewise, the encoding of the tmp file. This will be set only if the original 
+  nsCString m_type;        // The type of the data in file_name (not necessarily the same as the type of orig_url.)
+
+  nsCString m_encoding;    // Likewise, the encoding of the tmp file. This will be set only if the original 
                             // document had an encoding already; we don't do base64 encoding and so forth until 
                             // it's time to assemble a full MIME message of all parts.
 
 
-  char        *description;    // For Content-Description header 
-  char        *x_mac_type;    // mac-specific info 
-  char        *x_mac_creator; // mac-specific info 
-  char        *real_name;      // The real name of the file. 
+  nsCString m_description;    // For Content-Description header 
+  nsCString m_xMacType;    // mac-specific info 
+  nsCString m_xMacCreator; // mac-specific info 
+  nsCString m_realName;      // The real name of the file. 
 
   // Some statistics about the data that was written to the file, so that when
   // it comes time to compose a MIME message, we can make an informed decision
   // about what Content-Transfer-Encoding would be best for this attachment.
   // (If it's encoded already, we ignore this information and ship it as-is.)
-  PRUint32    size;
-  PRUint32    unprintable_count;
-  PRUint32    highbit_count;
-  PRUint32    ctl_count;
-  PRUint32    null_count;
-  PRUint32    max_line_length;
-  
-} nsMsgAttachedFile;
+  PRUint32    m_size;
+  PRUint32    m_unprintableCount;
+  PRUint32    m_highbitCount;
+  PRUint32    m_ctlCount;
+  PRUint32    m_nullCount;
+  PRUint32    m_maxLineLength;
+};
+
 %}
 
-
-[ptr] native nsMsgAttachmentData(nsMsgAttachmentData);
+[ptr] native nsMsgAttachmentHandler(nsMsgAttachmentHandler);
 [ptr] native nsMsgAttachedFile(nsMsgAttachedFile);
-[ptr] native nsMsgAttachmentHandler(nsMsgAttachmentHandler);
 
-[scriptable, uuid(8a3eb87e-6643-439b-bf0c-3aa2ede692ef)]
-interface nsIMsgSend : nsISupports 
+[scriptable, uuid(95b2fafb-1b2a-4cea-8774-72b15f31f428)]
+interface nsIMsgSend : nsISupports
 {
   //
   // This is the primary interface for creating and sending RFC822 messages
   // in the new architecture. Currently, this method supports many arguments
   // that change the behavior of the operation. This will change in time to 
   // be separate calls that will be more singluar in nature.
   //
   // NOTE: when aEditor is non-null, a multipart related MHTML message will 
@@ -188,38 +275,59 @@ interface nsIMsgSend : nsISupports
   const nsMsgDeliverMode nsMsgSaveAs = 3;
   const nsMsgDeliverMode nsMsgSaveAsDraft = 4;
   const nsMsgDeliverMode nsMsgSaveAsTemplate = 5;
   const nsMsgDeliverMode nsMsgSendUnsent = 6;
 
   /// Queue the message in the unsent folder and send it in the background.
   const nsMsgDeliverMode nsMsgDeliverBackground = 8;
 
-    [noscript]
-    void createAndSendMessage(in nsIEditor                    aEditor,
-                              in nsIMsgIdentity               aUserIdentity,
-                              in string                       aAccountKey,
-                              in nsIMsgCompFields             fields,
-                              in boolean                      digest_p,
-                              in boolean                      dont_deliver_p,
-                              in nsMsgDeliverMode             mode, 
-                              in nsIMsgDBHdr                  msgToReplace,
-                              in string               attachment1_type,
-                              in string               attachment1_body,
-                              in PRUint32                     attachment1_body_length,
-                              [const] in nsMsgAttachmentData  attachments,
-                              [const] in nsMsgAttachedFile    preloaded_attachments,
-                              in voidPtr                      relatedPart,
-                              in nsIDOMWindow                 parentWindow,
-                              in nsIMsgProgress               progress,
-                              in nsIMsgSendListener           aListener,
-                              in string                       password,
-                              in AUTF8String                  aOriginalMsgURI,
-                              in MSG_ComposeType              aType
-                             );
+  /**
+   * Create an rfc822 message and send it.
+   * @param aEditor nsIEditor instance that contains message. May be a dummy,
+   *                especially in the case of import.
+   * @param aUserIdentity identity to send from.
+   * @param aAccountKey account we're sending message from. May be null.
+   * @param aFields composition fields from addressing widget
+   * @param aIsDigest is this a digest message?
+   * @param aDontDeliver Set to false by the import code - used when we're
+   *                     trying to create a message from parts.
+   * @param aMode delivery mode
+   * @param aMsgToReplace e.g., when saving a draft over an old draft. May be 0
+   * @param aBodyType content type of message body
+   * @param aBody message body text (should have native line endings)
+   * @param aBodyLength passed in to avoid extra strlen call.
+   * @param aAttachments Array of nsIMsgAttachmentData
+   * @param aPreloadedAttachments Array of nsIMsgAttachedFile
+   * @param aParentWindow compose window; may be null.
+   * @param aProgress where to send progress info; may be null.
+   * @param aListener optional listener for send progress
+   * @param aPassword optional smtp server password
+   * @param aOriginalMsgURI may be null.
+   * @param aType see nsIMsgComposeParams.idl
+   */
+    void createAndSendMessage(in nsIEditor aEditor,
+                              in nsIMsgIdentity aUserIdentity,
+                              in string aAccountKey,
+                              in nsIMsgCompFields aFields,
+                              in boolean aIsDigest,
+                              in boolean aDontDeliver,
+                              in nsMsgDeliverMode aMode,
+                              in nsIMsgDBHdr aMsgToReplace,
+                              in string aBodyType,
+                              in string aBody,
+                              in unsigned long aBodyLength,
+                              in nsIArray aAttachments,
+                              in nsIArray aPreloadedAttachments,
+                              in nsIDOMWindow aParentWindow,
+                              in nsIMsgProgress aProgress,
+                              in nsIMsgSendListener aListener,
+                              in string aPassword,
+                              in AUTF8String aOriginalMsgURI,
+                              in MSG_ComposeType aType);
 
   /**
    * Sends a file to the specified composition fields, via the user identity
    * provided.
    *
    * @param aUserIdentity    The user identity to use for sending this email.
    * @param aAccountKey      The key of the account that this message relates
    *                         to.
@@ -257,58 +365,58 @@ interface nsIMsgSend : nsISupports
                        in nsIMsgDBHdr          aMsgToReplace,
                        in nsIMsgSendListener   aListener,
                        in nsIMsgStatusFeedback aStatusFeedback,
                        in string               aPassword
                        ); 
 
     /* Abort current send/save operation */
     void abort();
-    
+
     /* Report a send failure */
     nsresult fail(in nsresult failure_code, in wstring error_msg);
 
     /* Disable UI notification (alert message) */
     void setGUINotificationState(in boolean aEnableFlag);
-    
+
     /* Crypto */
     void BeginCryptoEncapsulation();
 
     /* retreive the last send process report*/
     readonly attribute nsIMsgSendReport sendReport; 
-    
+
     /* methods for send listener ... */
-    [noscript] void notifyListenerOnStartSending(in string aMsgID, in unsigned long aMsgSize);
-    [noscript] void notifyListenerOnProgress(in string aMsgID, in unsigned long aProgress, in unsigned long aProgressMax);
-    [noscript] void notifyListenerOnStatus(in string aMsgID, in wstring aMsg);
-    [noscript] void notifyListenerOnStopSending(in string aMsgID, in nsresult aStatus, in wstring aMsg, in nsIFile returnFile);
-    [noscript] void deliverAsMailExit(in nsIURI aUrl, in nsresult aExitCode);
-    [noscript] void deliverAsNewsExit(in nsIURI aUrl, in nsresult aExitCode);
+    void notifyListenerOnStartSending(in string aMsgID, in unsigned long aMsgSize);
+    void notifyListenerOnProgress(in string aMsgID, in unsigned long aProgress, in unsigned long aProgressMax);
+    void notifyListenerOnStatus(in string aMsgID, in wstring aMsg);
+    void notifyListenerOnStopSending(in string aMsgID, in nsresult aStatus, in wstring aMsg, in nsIFile returnFile);
+    void deliverAsMailExit(in nsIURI aUrl, in nsresult aExitCode);
+    void deliverAsNewsExit(in nsIURI aUrl, in nsresult aExitCode);
     
-    [noscript] void sendDeliveryCallback(in nsIURI aUrl, in boolean inIsNewsDelivery, in nsresult aExitCode);
+    void sendDeliveryCallback(in nsIURI aUrl, in boolean inIsNewsDelivery, in nsresult aExitCode);
 
     /* methods for copy listener ... */
-    [noscript] void notifyListenerOnStartCopy(); 
-    [noscript] void notifyListenerOnProgressCopy(in unsigned long aProgress, in unsigned long aProgressMax);
-    [noscript] void notifyListenerOnStopCopy(in nsresult aStatus);
+    void notifyListenerOnStartCopy(); 
+    void notifyListenerOnProgressCopy(in unsigned long aProgress, in unsigned long aProgressMax);
+    void notifyListenerOnStopCopy(in nsresult aStatus);
     void getMessageId(out ACString messageID);
-    [noscript] attribute nsMsgKey messageKey;
+    attribute nsMsgKey messageKey;
 
-    [noscript] nsIPrompt getDefaultPrompt();
-    
+    nsIPrompt getDefaultPrompt();
+
     /* process attachment */
-    [noscript] void gatherMimeAttachments();
-    [noscript] boolean getProcessAttachmentsSynchronously();
+    void gatherMimeAttachments();
+    readonly attribute boolean processAttachmentsSynchronously;
     [noscript] nsMsgAttachmentHandler getAttachmentHandlers();
-    [noscript] readonly attribute unsigned long attachmentCount;
-    [noscript] attribute unsigned long pendingAttachmentCount;
-    [noscript] readonly attribute nsMsgDeliverMode deliveryMode;
+    readonly attribute unsigned long attachmentCount;
+    attribute unsigned long pendingAttachmentCount;
+    readonly attribute nsMsgDeliverMode deliveryMode;
 
-    [noscript] nsIMsgProgress getProgress();
-    
+    nsIMsgProgress getProgress();
+
     nsIOutputStream getOutputStream();
 
-    [noscript] attribute nsIRequest runningRequest;
+    attribute nsIRequest runningRequest;
 
-    [noscript] attribute nsresult status;
+    attribute nsresult status;
 
-    [noscript] attribute nsIMsgComposeSecure cryptoclosure;
+    attribute nsIMsgComposeSecure cryptoclosure;
 };
--- a/mailnews/compose/public/nsMsgCompCID.h
+++ b/mailnews/compose/public/nsMsgCompCID.h
@@ -134,16 +134,38 @@ 0x0b63fb80, 0xbbba, 0x11d4,             
   "@mozilla.org/messengercompose/attachment;1"
 
 #define NS_MSGATTACHMENT_CID                    \
 { /* 27B8D045-8D9F-4fa8-BFB6-8A0F8D09CE89 */    \
  0x27b8d045, 0x8d9f, 0x4fa8,                    \
  {0xbf, 0xb6, 0x8a, 0xf, 0x8d, 0x9, 0xce, 0x89}}
 
 //
+// nsMsgAttachmentData
+//
+#define NS_MSGATTACHMENTDATA_CONTRACTID \
+  "@mozilla.org/messengercompose/attachmentdata;1"
+
+#define NS_MSGATTACHMENTDATA_CID                    \
+{ /* 9e16958d-d9e9-4cae-b723-a5bccf104998 */ \
+ 0x9e16958d, 0xd9e9, 0x4cae, \
+ {0xb7, 0x23, 0xa5, 0xbc, 0xcf, 0x10, 0x49, 0x98}}
+
+//
+// nsMsgAttachedFile
+//
+#define NS_MSGATTACHEDFILE_CONTRACTID \
+  "@mozilla.org/messengercompose/attachedfile;1"
+
+#define NS_MSGATTACHEDFILE_CID                    \
+{ /* ef173501-4e14-42b9-ae1f-7770de235c29 */ \
+ 0xef173501, 0x4e14, 0x42b9, \
+ {0xae, 0x1f, 0x77, 0x70, 0xde, 0x23, 0x5c, 0x29}}
+
+//
 // nsMsgSend
 //
 #define NS_MSGSEND_CONTRACTID \
   "@mozilla.org/messengercompose/send;1"
 
 #define NS_MSGSEND_CID                \
 { /* 935284E0-C5D8-11d2-8297-000000000000 */      \
  0x935284e0, 0xc5d8, 0x11d2,                      \
--- a/mailnews/compose/src/nsMsgAttachmentHandler.cpp
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.cpp
@@ -140,34 +140,20 @@ nsresult nsSimpleZipper::AddToZip(nsIZip
 #endif // XP_MACOSX
 
 //
 // Class implementation...
 //
 nsMsgAttachmentHandler::nsMsgAttachmentHandler() :
   mRequest(nsnull),
   mCompFields(nsnull),   // Message composition fields for the sender
-  
-  m_x_mac_type(nsnull),
-  m_x_mac_creator(nsnull),
-
+  m_bogus_attachment(PR_FALSE),
   m_done(PR_FALSE),
-  m_charset(nsnull),
-  m_content_id(nsnull),
-  m_type(nsnull),
-  m_type_param(nsnull),
-  m_override_type(nsnull),
-  m_override_encoding(nsnull),
-  m_desired_type(nsnull),
-  m_description(nsnull),
-  m_real_name(nsnull),
-  m_encoding(nsnull),
   m_already_encoded_p(PR_FALSE),
   m_decrypted_p(PR_FALSE),
-  
   mDeleteFile(PR_FALSE),
   mMHTMLPart(PR_FALSE),
   mPartUserOmissionOverride(PR_FALSE),
   mMainBody(PR_FALSE),
 
   // For analyzing the attachment file...
   m_size(0),
   m_unprintable_count(0),
@@ -179,44 +165,29 @@ nsMsgAttachmentHandler::nsMsgAttachmentH
   m_have_crlf(0),
   m_prev_char_was_cr(PR_FALSE),
   m_current_column(0),
   m_max_column(0),
   m_lines(0),
   m_file_analyzed(PR_FALSE),
 
   // Mime
-  m_encoder_data(nsnull),
-  m_uri(nsnull)
+  m_encoder_data(nsnull)
 {
 }
 
 nsMsgAttachmentHandler::~nsMsgAttachmentHandler()
 {
   if (mTmpFile && mDeleteFile)
     mTmpFile->Remove(PR_FALSE);
-    
+
   if (mOutFile)
     mOutFile->Close();
-    
+
   CleanupTempFile();
-
-  PR_Free(m_charset);
-  PR_Free(m_type);
-  PR_Free(m_type_param);
-  PR_Free(m_content_id);
-  PR_Free(m_desired_type);
-  PR_Free(m_encoding);
-  PR_Free(m_override_type);
-  PR_Free(m_description);
-  PR_Free(m_real_name);
-  PR_Free(m_override_encoding);
-  PR_Free(m_x_mac_type);
-  PR_Free(m_x_mac_creator);
-  PR_Free(m_uri);
 }
 
 void
 nsMsgAttachmentHandler::CleanupTempFile()
 {
 #ifdef XP_MACOSX
   if (mEncodedWorkingFile) {
     mEncodedWorkingFile->Remove(PR_FALSE);
@@ -334,17 +305,17 @@ nsMsgAttachmentHandler::PickEncoding(con
 
   AnalyzeSnarfedFile();
 
   /* Allow users to override our percentage-wise guess on whether
   the file is text or binary */
   if (pPrefBranch)
     pPrefBranch->GetBoolPref ("mail.file_attach_binary", &forceB64);
 
-  if (!mMainBody && (forceB64 || mime_type_requires_b64_p (m_type) ||
+  if (!mMainBody && (forceB64 || mime_type_requires_b64_p (m_type.get()) ||
     m_have_cr+m_have_lf+m_have_crlf != 1 || m_current_column != 0))
   {
   /* If the content-type is "image/" or something else known to be binary
   or several flavors of newlines are present or last line is incomplete,
   always use base64 (so that we don't get confused by newline
   conversions.)
      */
     needsB64 = PR_TRUE;
@@ -379,86 +350,69 @@ nsMsgAttachmentHandler::PickEncoding(con
       else if (m_null_count)  /* If there are nulls, we must always encode,
         because sendmail will blow up. */
         encode_p = PR_TRUE;
       else
         encode_p = PR_FALSE;
 
         /* MIME requires a special case that these types never be encoded.
       */
-      if (!PL_strncasecmp (m_type, "message", 7) ||
-        !PL_strncasecmp (m_type, "multipart", 9))
+      if (StringBeginsWith(m_type, NS_LITERAL_CSTRING("message"),
+                           nsCaseInsensitiveCStringComparator()) ||
+         StringBeginsWith(m_type, NS_LITERAL_CSTRING("multipart"),
+                          nsCaseInsensitiveCStringComparator()))
       {
         encode_p = PR_FALSE;
-        if (m_desired_type && !PL_strcasecmp (m_desired_type, TEXT_PLAIN))
-        {
-          PR_Free (m_desired_type);
-          m_desired_type = 0;
-        }
+        if (m_desiredType.LowerCaseEqualsLiteral(TEXT_PLAIN))
+          m_desiredType.Truncate();
       }
 
       // If the Mail charset is multibyte, we force it to use Base64 for attachments.
       if ((!mMainBody && charset && nsMsgI18Nmultibyte_charset(charset)) &&
-        ((PL_strcasecmp(m_type, TEXT_HTML) == 0) ||
-        (PL_strcasecmp(m_type, TEXT_MDL) == 0) ||
-        (PL_strcasecmp(m_type, TEXT_PLAIN) == 0) ||
-        (PL_strcasecmp(m_type, TEXT_RICHTEXT) == 0) ||
-        (PL_strcasecmp(m_type, TEXT_ENRICHED) == 0) ||
-        (PL_strcasecmp(m_type, TEXT_VCARD) == 0) ||
-        (PL_strcasecmp(m_type, APPLICATION_DIRECTORY) == 0) || /* text/x-vcard synonym */
-        (PL_strcasecmp(m_type, TEXT_CSS) == 0) ||
-        (PL_strcasecmp(m_type, TEXT_JSSS) == 0)))
-      {
+          (m_type.LowerCaseEqualsLiteral(TEXT_HTML) ||
+           m_type.LowerCaseEqualsLiteral(TEXT_MDL) ||
+           m_type.LowerCaseEqualsLiteral(TEXT_PLAIN) ||
+           m_type.LowerCaseEqualsLiteral(TEXT_RICHTEXT) ||
+           m_type.LowerCaseEqualsLiteral(TEXT_ENRICHED) ||
+           m_type.LowerCaseEqualsLiteral(TEXT_VCARD) ||
+           m_type.LowerCaseEqualsLiteral(APPLICATION_DIRECTORY) || /* text/x-vcard synonym */
+           m_type.LowerCaseEqualsLiteral(TEXT_CSS) ||
+           m_type.LowerCaseEqualsLiteral(TEXT_JSSS)))
         needsB64 = PR_TRUE;
-      }
       else if (charset && nsMsgI18Nstateful_charset(charset))
-      {
-        PR_Free(m_encoding);
-        m_encoding = PL_strdup (ENCODING_7BIT);
-      }
+        m_encoding = ENCODING_7BIT;
       else if (encode_p &&
         m_unprintable_count > (m_size / 10))
         /* If the document contains more than 10% unprintable characters,
         then that seems like a good candidate for base64 instead of
         quoted-printable.
         */
         needsB64 = PR_TRUE;
-      else if (encode_p) {
-        PR_Free(m_encoding);
-        m_encoding = PL_strdup (ENCODING_QUOTED_PRINTABLE);
-      }
-      else if (m_highbit_count > 0) {
-        PR_Free(m_encoding);
-        m_encoding = PL_strdup (ENCODING_8BIT);
-      }
-      else {
-        PR_Free(m_encoding);
-        m_encoding = PL_strdup (ENCODING_7BIT);
-      }
+      else if (encode_p)
+        m_encoding = ENCODING_QUOTED_PRINTABLE;
+      else if (m_highbit_count > 0)
+        m_encoding = ENCODING_8BIT;
+      else
+        m_encoding = ENCODING_7BIT;
   }
 
+  // always base64 binary data.
   if (needsB64)
-  {
-    //
-    // always base64 binary data.
-    //
-    PR_Free(m_encoding);
-    m_encoding = PL_strdup (ENCODING_BASE64);
-  }
+    m_encoding = ENCODING_BASE64;
 
   /* Now that we've picked an encoding, initialize the filter.
   */
   NS_ASSERTION(!m_encoder_data, "not-null m_encoder_data");
-  if (!PL_strcasecmp(m_encoding, ENCODING_BASE64))
+  if (m_encoding.LowerCaseEqualsLiteral(ENCODING_BASE64))
   {
     m_encoder_data = MIME_B64EncoderInit(mime_encoder_output_fn,
       mime_delivery_state);
     if (!m_encoder_data) return NS_ERROR_OUT_OF_MEMORY;
   }
-  else if (!PL_strcasecmp(m_encoding, ENCODING_QUOTED_PRINTABLE))
+  else if (m_encoding.LowerCaseEqualsLiteral(ENCODING_QUOTED_PRINTABLE))
   {
     m_encoder_data = MIME_QPEncoderInit(mime_encoder_output_fn,
       mime_delivery_state);
     if (!m_encoder_data) return NS_ERROR_OUT_OF_MEMORY;
   }
   else
   {
     m_encoder_data = 0;
@@ -480,59 +434,57 @@ nsMsgAttachmentHandler::PickEncoding(con
         bad charset things happen as well.
 
           So, the heuristic we use is, if the type is unknown, then the type is
           set to application/octet-stream for data which needs base64 (binary data)
           and is set to text/plain for data which didn't need base64 (unencoded or
           lightly encoded data.)
   */
 DONE:
-  if (!m_type || !*m_type || !PL_strcasecmp(m_type, UNKNOWN_CONTENT_TYPE))
+  if (m_type.IsEmpty() || m_type.LowerCaseEqualsLiteral(UNKNOWN_CONTENT_TYPE))
   {
-    PR_Free(m_type);
     if (m_already_encoded_p)
-      m_type = PL_strdup (APPLICATION_OCTET_STREAM);
-    else if (m_encoding &&
-         (!PL_strcasecmp(m_encoding, ENCODING_BASE64) ||
-         !PL_strcasecmp(m_encoding, ENCODING_UUENCODE)))
-         m_type = PL_strdup (APPLICATION_OCTET_STREAM);
+      m_type = APPLICATION_OCTET_STREAM;
+    else if (m_encoding.LowerCaseEqualsLiteral(ENCODING_BASE64) ||
+             m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE))
+      m_type = APPLICATION_OCTET_STREAM;
     else
-      m_type = PL_strdup (TEXT_PLAIN);
+      m_type = TEXT_PLAIN;
   }
   return 0;
 }
 
 class CharsetDetectionObserver : public nsICharsetDetectionObserver
 {
 public:
   NS_DECL_ISUPPORTS
   CharsetDetectionObserver(nsMsgAttachmentHandler* aAttachment)
   {
     m_attachment = aAttachment;
   };
 
   virtual ~CharsetDetectionObserver() {};
   NS_IMETHOD Notify(const char* aCharset, nsDetectionConfident aConf)
   {
-    m_attachment->m_charset = PL_strdup(aCharset);
+    m_attachment->m_charset = aCharset;
     return NS_OK;
   };
 
 private:
   nsMsgAttachmentHandler* m_attachment;
 };
 
 NS_IMPL_ISUPPORTS1(CharsetDetectionObserver, nsICharsetDetectionObserver)
 
 nsresult
 nsMsgAttachmentHandler::PickCharset()
 {
 
-  if (m_charset || strcmp(m_type, TEXT_PLAIN))
-    return NS_OK;;
+  if (!m_charset.IsEmpty() || !m_type.LowerCaseEqualsLiteral(TEXT_PLAIN))
+    return NS_OK;
 
   nsCOMPtr<nsILocalFile> tmpFile =
     do_QueryInterface(mTmpFile);
   if (!tmpFile)
     return NS_OK;
   
   nsCOMPtr<nsICharsetDetector> detector =
     do_CreateInstance(NS_CHARSET_DETECTOR_CONTRACTID_BASE
@@ -611,54 +563,46 @@ FetcherURLDoneCallback(nsresult aStatus,
     ma->m_size = totalSize;
     if (!aContentType.IsEmpty())
     {
 #ifdef XP_MACOSX
       //Do not change the type if we are dealing with an encoded (e.g., appledouble or zip) file
       if (!ma->mEncodedWorkingFile)
 #else
         // can't send appledouble on non-macs
-        if (!aContentType.EqualsLiteral("multipart/appledouble"))
+      if (!aContentType.EqualsLiteral("multipart/appledouble"))
 #endif
-      {
-        PR_Free(ma->m_type);
-        ma->m_type = ToNewCString(aContentType);
-      }
+        ma->m_type = aContentType;
     }
 
     if (!aCharset.IsEmpty())
-    {
-      PR_Free(ma->m_charset);
-      ma->m_charset = ToNewCString(aCharset);
-    }
+      ma->m_charset = aCharset;
 
     return ma->UrlExit(aStatus, aMsg);
   }
   else
     return NS_OK;
 }
 
 nsresult
 nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields)
 {
   nsresult rv = NS_ERROR_INVALID_ARG;
   nsCOMPtr <nsIMsgMessageService> messageService;
 
-  if (PL_strcasestr(m_uri, "-message:"))
+  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 = 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);
+    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)
@@ -682,17 +626,17 @@ nsMsgAttachmentHandler::SnarfMsgAttachme
     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));
+    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));
 
@@ -860,30 +804,28 @@ nsMsgAttachmentHandler::ConvertToZipFile
   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.
-  PR_Free(m_type);
-  m_type = PL_strdup(APPLICATION_ZIP);
-  PR_Free(m_real_name);
-  m_real_name = PL_strdup(zippedName.get());
-  
+  m_type = APPLICATION_ZIP;
+  m_real_name = zippedName.get();
+
   return NS_OK;
 }
 
 nsresult
 nsMsgAttachmentHandler::ConvertToAppleEncoding(const nsCString &aFileURI, 
                                                const nsCString &aFilePath, 
                                                nsILocalFileMac *aSourceFile)
 {
@@ -894,25 +836,23 @@ nsMsgAttachmentHandler::ConvertToAppleEn
 
   char fileInfo[32];
   OSType type, creator;
 
   nsresult rv = aSourceFile->GetFileType(&type);
   if (NS_FAILED(rv))
     return PR_FALSE;
   PR_snprintf(fileInfo, sizeof(fileInfo), "%X", type);
-  PR_Free(m_x_mac_type);
-  m_x_mac_type = PL_strdup(fileInfo);
+  m_xMacType = fileInfo;
 
   rv = aSourceFile->GetFileCreator(&creator);
   if (NS_FAILED(rv))
     return PR_FALSE;
   PR_snprintf(fileInfo, sizeof(fileInfo), "%X", creator);
-  PR_Free(m_x_mac_creator);
-  m_x_mac_creator = PL_strdup(fileInfo);
+  m_xMacCreator = fileInfo;
 
   FSRef fsRef;
   aSourceFile->GetFSRef(&fsRef);
   PRBool sendResourceFork = HasResourceFork(&fsRef);
 
   // if we have a resource fork, check the filename extension, maybe we don't need the resource fork!
   if (sendResourceFork)
   {
@@ -1057,39 +997,37 @@ nsMsgAttachmentHandler::ConvertToAppleEn
       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);
-    PR_Free(m_type);
-    m_type = PL_strdup(tmp);
+    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");
     }
 
     PRBool    useDefault;
     char      *macType, *macEncoding;
-    if (m_type == NULL || !PL_strcasecmp (m_type, TEXT_PLAIN))
+    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);
-        PR_Free(m_type);
         m_type = macType;
       }
     }
     // don't bother to set the types if we failed in getting the file info.
   }
 
   return NS_OK;
 }
@@ -1117,17 +1055,17 @@ nsMsgAttachmentHandler::LoadDataFromFile
 
   PRUint32 bytesRead;
   inputFile->Read(readBuf, readSize, &bytesRead);
   inputFile->Close();
 
   nsDependentCString cstringReadBuf(readBuf, bytesRead);
   if (charsetConversion)
   {
-    if (NS_FAILED(ConvertToUnicode(m_charset, cstringReadBuf, sigData)))
+    if (NS_FAILED(ConvertToUnicode(m_charset.get(), cstringReadBuf, sigData)))
       CopyASCIItoUTF16(cstringReadBuf, sigData);
   }
   else
     CopyASCIItoUTF16(cstringReadBuf, sigData);
 
   PR_FREEIF(readBuf);
   return NS_OK;
 }
@@ -1177,29 +1115,19 @@ nsMsgAttachmentHandler::UrlExit(nsresult
   mRequest = nsnull;
 
   // First things first, we are now going to see if this is an HTML
   // Doc and if it is, we need to see if we can determine the charset
   // for this part by sniffing the HTML file.
   // This is needed only when the charset is not set already.
   // (e.g. a charset may be specified in HTTP header)
   //
-  if ( (m_type) &&  (*m_type) &&
-       (!m_charset || !(*m_charset)) )
-  {
-    if (PL_strcasecmp(m_type, TEXT_HTML) == 0)
-    {
-      char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(mTmpFile);
-      if (tmpCharset[0] != '\0')
-      {
-        PR_Free(m_charset);
-        m_charset = PL_strdup(tmpCharset);
-      }
-    }
-  }
+  if (!m_type.IsEmpty() && m_charset.IsEmpty() &&
+      m_type.LowerCaseEqualsLiteral(TEXT_HTML))
+    m_charset = nsMsgI18NParseMetaCharset(mTmpFile);
 
   nsresult mimeDeliveryStatus;
   m_mime_delivery_state->GetStatus(&mimeDeliveryStatus);
 
   if (mimeDeliveryStatus == NS_ERROR_ABORT)
     status = NS_ERROR_ABORT;
 
   if (NS_FAILED(status) && status != NS_ERROR_ABORT && NS_SUCCEEDED(mimeDeliveryStatus))
@@ -1218,28 +1146,27 @@ nsMsgAttachmentHandler::UrlExit(nsresult
     rv = bundleService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(bundle));
     NS_ENSURE_SUCCESS(rv, rv);
     nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
     m_mime_delivery_state->GetDeliveryMode(&mode);
     if (mode == nsIMsgSend::nsMsgSaveAsDraft || mode == nsIMsgSend::nsMsgSaveAsTemplate)
       bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SAVING, getter_Copies(msg));
     else
       bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SENDING, getter_Copies(msg));
-    if (m_real_name && *m_real_name)
-      printfString = nsTextFormatter::smprintf(msg.get(), m_real_name);
-    else
-    if (NS_SUCCEEDED(mURL->GetSpec(turl)) && !turl.IsEmpty())
-      {
-        nsCAutoString unescapedUrl;
-        MsgUnescapeString(turl, 0, unescapedUrl);
-        if (unescapedUrl.IsEmpty())
-          printfString = nsTextFormatter::smprintf(msg.get(), turl.get());
-        else
-          printfString = nsTextFormatter::smprintf(msg.get(), unescapedUrl.get());
-      }
+    if (!m_realName.IsEmpty())
+      printfString = nsTextFormatter::smprintf(msg.get(), m_realName.get());
+    else if (NS_SUCCEEDED(mURL->GetSpec(turl)) && !turl.IsEmpty())
+    {
+      nsCAutoString unescapedUrl;
+      MsgUnescapeString(turl, 0, unescapedUrl);
+      if (unescapedUrl.IsEmpty())
+        printfString = nsTextFormatter::smprintf(msg.get(), turl.get());
+      else
+        printfString = nsTextFormatter::smprintf(msg.get(), unescapedUrl.get());
+    }
     else
       printfString = nsTextFormatter::smprintf(msg.get(), "?");
 
     nsCOMPtr<nsIPrompt> aPrompt;
     if (m_mime_delivery_state)
       m_mime_delivery_state->GetDefaultPrompt(getter_AddRefs(aPrompt));
     nsMsgAskBooleanQuestionByString(aPrompt, printfString, &keepOnGoing);
     PR_FREEIF(printfString);
@@ -1263,82 +1190,78 @@ nsMsgAttachmentHandler::UrlExit(nsresult
 
   m_done = PR_TRUE;
 
   //
   // Ok, now that we have the file here on disk, we need to see if there was
   // a need to do conversion to plain text...if so, the magic happens here,
   // otherwise, just move on to other attachments...
   //
-  if (NS_SUCCEEDED(status) && m_type && PL_strcasecmp(m_type, TEXT_PLAIN) )
+  if (NS_SUCCEEDED(status) && m_type.LowerCaseEqualsLiteral(TEXT_PLAIN) &&
+      m_desiredType.LowerCaseEqualsLiteral(TEXT_PLAIN))
   {
-    if (m_desired_type && !PL_strcasecmp(m_desired_type, TEXT_PLAIN) )
+    //
+    // Conversion to plain text desired.
+    //
+    PRInt32       width = 72;
+    nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
+    if (pPrefBranch)
+      pPrefBranch->GetIntPref("mailnews.wraplength", &width);
+    // Let sanity reign!
+    if (width == 0)
+      width = 72;
+    else if (width < 10)
+      width = 10;
+    else if (width > 30000)
+      width = 30000;
+
+    //
+    // Now use the converter service here to do the right
+    // thing and convert this data to plain text for us!
+    //
+    nsAutoString      conData;
+
+    if (NS_SUCCEEDED(LoadDataFromFile(mTmpFile, conData, PR_TRUE)))
     {
-      //
-      // Conversion to plain text desired.
-      //
-      PRInt32       width = 72;
-      nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
-      if (pPrefBranch)
-        pPrefBranch->GetIntPref("mailnews.wraplength", &width);
-      // Let sanity reign!
-      if (width == 0)
-        width = 72;
-      else if (width < 10)
-        width = 10;
-      else if (width > 30000)
-        width = 30000;
+      if (NS_SUCCEEDED(ConvertBufToPlainText(conData, UseFormatFlowed(m_charset.get()))))
+      {
+        if (mDeleteFile)
+          mTmpFile->Remove(PR_FALSE);
 
-      //
-      // Now use the converter service here to do the right
-      // thing and convert this data to plain text for us!
-      //
-      nsAutoString      conData;
+        nsCOMPtr<nsIOutputStream> outputStream;
+        nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile,  PR_WRONLY | PR_CREATE_FILE, 00600);
 
-      if (NS_SUCCEEDED(LoadDataFromFile(mTmpFile, conData, PR_TRUE)))
-      {
-        if (NS_SUCCEEDED(ConvertBufToPlainText(conData, UseFormatFlowed(m_charset))))
+        if (NS_SUCCEEDED(rv))
         {
-          if (mDeleteFile)
-            mTmpFile->Remove(PR_FALSE);
-
-          nsCOMPtr<nsIOutputStream> outputStream;
-          nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile,  PR_WRONLY | PR_CREATE_FILE, 00600);
-
-          if (NS_SUCCEEDED(rv))
+          nsCAutoString tData;
+          if (NS_FAILED(ConvertFromUnicode(m_charset.get(), conData, tData)))
+            LossyCopyUTF16toASCII(conData, tData);
+          if (!tData.IsEmpty())
           {
-            nsCAutoString tData;
-            if (NS_FAILED(ConvertFromUnicode(m_charset, conData, tData)))
-              LossyCopyUTF16toASCII(conData, tData);
-            if (!tData.IsEmpty())
-            {
-              PRUint32 bytesWritten;
-              (void) outputStream->Write(tData.get(), tData.Length(), &bytesWritten);
-            }
-            outputStream->Close();
-            // this silliness is because Windows nsILocalFile caches its file size
-            // so if an output stream writes to it, it will still return the original
-            // cached size.
-            if (mTmpFile)
-            {
-              nsCOMPtr <nsIFile> tmpFile;
-              mTmpFile->Clone(getter_AddRefs(tmpFile));
-              mTmpFile = do_QueryInterface(tmpFile);
-            }
+            PRUint32 bytesWritten;
+            (void) outputStream->Write(tData.get(), tData.Length(), &bytesWritten);
+          }
+          outputStream->Close();
+          // this silliness is because Windows nsILocalFile caches its file size
+          // so if an output stream writes to it, it will still return the original
+          // cached size.
+          if (mTmpFile)
+          {
+            nsCOMPtr <nsIFile> tmpFile;
+            mTmpFile->Clone(getter_AddRefs(tmpFile));
+            mTmpFile = do_QueryInterface(tmpFile);
+          }
 
-          }
         }
       }
+    }
 
-      PR_FREEIF(m_type);
-      m_type = m_desired_type;
-      m_desired_type = nsnull;
-      PR_FREEIF(m_encoding);
-      m_encoding = nsnull;
-    }
+    m_type = m_desiredType;
+    m_desiredType.Truncate();
+    m_encoding.Truncate();
   }
 
   PRUint32 pendingAttachmentCount = 0;
   m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount);
   NS_ASSERTION (pendingAttachmentCount > 0, "no more pending attachment");
 
   m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1);
 
@@ -1364,17 +1287,17 @@ nsMsgAttachmentHandler::UrlExit(nsresult
       {
         next = &attachments[i];
         //
         // rhp: We need to get a little more understanding to failed URL
         // requests. So, at this point if most of next is NULL, then we
         // should just mark it fetched and move on! We probably ignored
         // this earlier on in the send process.
         //
-        if ( (!next->mURL) && (!next->m_uri) )
+        if ( (!next->mURL) && (next->m_uri.IsEmpty()) )
         {
           attachments[i].m_done = PR_TRUE;
           m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount);
           m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1);
           next->mPartUserOmissionOverride = PR_TRUE;
           next = nsnull;
           continue;
         }
--- a/mailnews/compose/src/nsMsgAttachmentHandler.h
+++ b/mailnews/compose/src/nsMsgAttachmentHandler.h
@@ -123,47 +123,47 @@ private:
                                                nsILocalFileMac *aSourceFile);
   // zips this attachment and does the work to make this attachment handler handle it properly.
   nsresult ConvertToZipFile(nsILocalFileMac *aSourceFile);
   PRBool HasResourceFork(FSRef *fsRef);
 #endif
 
   //
 public:
-  nsCOMPtr <nsIURI> mURL;
-  nsCOMPtr <nsILocalFile>        mTmpFile;         // The temp file to which we save it 
+  nsCOMPtr<nsIURI> mURL;
+  nsCOMPtr<nsILocalFile>        mTmpFile;         // The temp file to which we save it 
   nsCOMPtr<nsIOutputStream>  mOutFile;          
   nsCOMPtr<nsIRequest> mRequest; // The live request used while fetching an attachment
   nsMsgCompFields       *mCompFields;       // Message composition fields for the sender
   PRBool                m_bogus_attachment; // This is to catch problem children...
   
 #ifdef XP_MACOSX
   // if we need to encode this file into for example an appledouble, or zip file,
   // this file is our working file. currently only needed on mac.
   nsCOMPtr<nsILocalFile> mEncodedWorkingFile;
 #endif
 
-  char                  *m_x_mac_type;      // Mac file type
-  char                  *m_x_mac_creator;   // Mac file creator
-  
-  PRBool                m_done;
-  char                  *m_charset;         // charset name 
-  char                  *m_content_id;      // This is for mutipart/related Content-ID's
-  char                  *m_type;            // The real type, once we know it.
-  char                  *m_type_param;      // Any addition parameters to add to the content-type (other than charset, macType and maccreator)
-  char                  *m_override_type;   // The type we should assume it to be
+  nsCString m_xMacType;      // Mac file type
+  nsCString m_xMacCreator;   // Mac file creator
+
+  PRBool m_done;
+  nsCString m_charset;         // charset name 
+  nsCString m_contentId;      // This is for mutipart/related Content-ID's
+  nsCString m_type;            // The real type, once we know it.
+  nsCString m_typeParam;      // Any addition parameters to add to the content-type (other than charset, macType and maccreator)
+  nsCString m_overrideType;   // The type we should assume it to be
                                             // or 0, if we should get it from the
                                             // server)
-  char                  *m_override_encoding; // Goes along with override_type 
+  nsCString m_overrideEncoding; // Goes along with override_type 
 
-  char                  *m_desired_type;    // The type it should be converted to. 
-  char                  *m_description;     // For Content-Description header
-  char                  *m_real_name;       // The name for the headers, if different
+  nsCString m_desiredType;    // The type it should be converted to. 
+  nsCString m_description;     // For Content-Description header
+  nsCString m_realName;       // The name for the headers, if different
                                             // from the URL. 
-  char                  *m_encoding;        // The encoding, once we've decided. */
+  nsCString m_encoding;        // The encoding, once we've decided. */
   PRBool                m_already_encoded_p; // If we attach a document that is already
                                              // encoded, we just pass it through.
 
   PRBool                m_decrypted_p;  /* S/MIME -- when attaching a message that was
                                            encrypted, it's necessary to decrypt it first
                                            (since nobody but the original recipient can
                                            read it -- if you forward it to someone in the
                                            raw, it will be useless to them.)  This flag
@@ -190,18 +190,18 @@ public:
   PRUint8               m_have_cr, m_have_lf, m_have_crlf; 
   PRBool                m_prev_char_was_cr;
   PRUint32              m_current_column;
   PRUint32              m_max_column;
   PRUint32              m_lines;
   PRBool                m_file_analyzed;
 
   MimeEncoderData       *m_encoder_data;  /* Opaque state for base64/qp encoder. */
-  char *                m_uri; // original uri string
-  
+  nsCString             m_uri; // original uri string
+
   nsresult              GetMimeDeliveryState(nsIMsgSend** _retval);
   nsresult              SetMimeDeliveryState(nsIMsgSend* mime_delivery_state);
 private:
   nsCOMPtr<nsIMsgSend>  m_mime_delivery_state;
   nsCOMPtr<nsIStreamConverter> m_mime_parser;
   nsCOMPtr<nsIChannel>  m_converter_channel;
 };
 
--- a/mailnews/compose/src/nsMsgCompUtils.cpp
+++ b/mailnews/compose/src/nsMsgCompUtils.cpp
@@ -1599,24 +1599,23 @@ msg_make_filename_qtext(const char *srcT
 }
 
 /* Rip apart the URL and extract a reasonable value for the `real_name' slot.
  */
 void
 msg_pick_real_name (nsMsgAttachmentHandler *attachment, const PRUnichar *proposedName, const char *charset)
 {
   const char *s, *s2;
-  char *s3;
 
-  if ( (attachment->m_real_name) && (*attachment->m_real_name))
+  if (!attachment->m_realName.IsEmpty())
     return;
 
   if (proposedName && *proposedName)
   {
-    attachment->m_real_name = ToNewUTF8String(nsAutoString(proposedName));
+    attachment->m_realName.Adopt(ToNewUTF8String(nsAutoString(proposedName)));
   }
   else //Let's extract the name from the URL
   {
     nsCString url;
     attachment->mURL->GetSpec(url);
 
     s = url.get();
     s2 = PL_strchr (s, ':');
@@ -1639,19 +1638,18 @@ msg_pick_real_name (nsMsgAttachmentHandl
       nsCString nonDataPart(Substring(url, 5, endNonData - 5));
       PRInt32 filenamePos = nonDataPart.Find("filename=");
       if (filenamePos != -1)
       {
         filenamePos += 9;
         PRInt32 endFilename = nonDataPart.FindChar(';', filenamePos);
         if (endFilename == -1)
           endFilename = endNonData;
-        PR_FREEIF(attachment->m_real_name);
-        attachment->m_real_name = ToNewCString(Substring(nonDataPart, filenamePos,
-                                                         endFilename - filenamePos));
+        attachment->m_realName = Substring(nonDataPart, filenamePos,
+                                           endFilename - filenamePos);
       }
       else
       {
         // no filename; need to construct one based on the content type.
         nsCOMPtr<nsIMIMEService> mimeService(do_GetService(NS_MIMESERVICE_CONTRACTID));
         if (!mimeService)
           return;
         nsCOMPtr<nsIMIMEInfo> mimeInfo;
@@ -1663,42 +1661,41 @@ msg_pick_real_name (nsMsgAttachmentHandl
         nsCString extension;
         mimeInfo->GetPrimaryExtension(extension);
         unsigned char filePrefix[10];
         GenerateGlobalRandomBytes(filePrefix, 8);
         for (PRInt32 i = 0; i < 8; i++)
           filename.Append(filePrefix[i] + 'a');
         filename.Append('.');
         filename.Append(extension);
-        PR_FREEIF(attachment->m_real_name);
-        attachment->m_real_name = ToNewCString(filename);
+        attachment->m_realName = filename;
       }
     }
     else
     {
       /* Take the part of the file name after the last / or \ */
       s2 = PL_strrchr (s, '/');
       if (s2) s = s2+1;
       s2 = PL_strrchr (s, '\\');
 
       if (s2) s = s2+1;
       /* Copy it into the attachment struct. */
-      PR_FREEIF(attachment->m_real_name);
-      attachment->m_real_name = PL_strdup (s);
+      attachment->m_realName = s;
+      PRInt32 charPos = attachment->m_realName.FindChar('?');
+      if (charPos != -1)
+        attachment->m_realName.SetLength(charPos);
       /* Now trim off any named anchors or search data. */
-      s3 = PL_strchr (attachment->m_real_name, '?');
-      if (s3) *s3 = 0;
-      s3 = PL_strchr (attachment->m_real_name, '#');
-      if (s3) *s3 = 0;
+      charPos = attachment->m_realName.FindChar('#');
+      if (charPos != -1)
+        attachment->m_realName.SetLength(charPos);
     }
     /* Now lose the %XX crap. */
     nsCString unescaped_real_name;
-    MsgUnescapeString(nsDependentCString(attachment->m_real_name), 0, unescaped_real_name);
-    NS_Free(attachment->m_real_name);
-    attachment->m_real_name = ToNewCString(unescaped_real_name);
+    MsgUnescapeString(attachment->m_realName, 0, unescaped_real_name);
+    attachment->m_realName = unescaped_real_name;
   }
 
   /* Now a special case for attaching uuencoded files...
 
    If we attach a file "foo.txt.uu", we will send it out with
    Content-Type: text/plain; Content-Transfer-Encoding: x-uuencode.
    When saving such a file, a mail reader will generally decode it first
    (thus removing the uuencoding.)  So, let's make life a little easier by
@@ -1706,54 +1703,37 @@ msg_pick_real_name (nsMsgAttachmentHandl
    will presumably make the file name in the Content-Disposition header be
    the same as the file name in the "begin" line of the uuencoded data.)
 
    However, since there are mailers out there (including earlier versions of
    Mozilla) that will use "foo.txt.uu" as the file name, we still need to
    cope with that; the code which copes with that is in the MIME parser, in
    libmime/mimei.c.
    */
-  if (attachment->m_already_encoded_p &&
-    attachment->m_encoding)
+  if (attachment->m_already_encoded_p && !attachment->m_encoding.IsEmpty())
   {
-    char *result = attachment->m_real_name;
-    PRInt32 L = PL_strlen(result);
-    const char **exts = 0;
-
     /* #### TOTAL KLUDGE.
      I'd like to ask the mime.types file, "what extensions correspond
      to obj->encoding (which happens to be "x-uuencode") but doing that
      in a non-sphagetti way would require brain surgery.  So, since
      currently uuencode is the only content-transfer-encoding which we
      understand which traditionally has an extension, we just special-
      case it here!
 
      Note that it's special-cased in a similar way in libmime/mimei.c.
      */
-    if (!PL_strcasecmp(attachment->m_encoding, ENCODING_UUENCODE) ||
-      !PL_strcasecmp(attachment->m_encoding, ENCODING_UUENCODE2) ||
-      !PL_strcasecmp(attachment->m_encoding, ENCODING_UUENCODE3) ||
-      !PL_strcasecmp(attachment->m_encoding, ENCODING_UUENCODE4))
-    {
-      static const char *uue_exts[] = { "uu", "uue", 0 };
-      exts = uue_exts;
-    }
-
-    while (exts && *exts)
+    if (attachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE) ||
+        attachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE2) ||
+        attachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE3) ||
+        attachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE4))
     {
-      const char *ext = *exts;
-      PRInt32 L2 = PL_strlen(ext);
-      if (L > L2 + 1 &&             /* long enough */
-        result[L - L2 - 1] == '.' &&      /* '.' in right place*/
-        !PL_strcasecmp(ext, result + (L - L2))) /* ext matches */
-      {
-        result[L - L2 - 1] = 0;   /* truncate at '.' and stop. */
-        break;
-      }
-      exts++;
+      if (StringEndsWith(attachment->m_realName, NS_LITERAL_CSTRING(".uu")))
+        attachment->m_realName.Cut(attachment->m_realName.Length() - 3, 3);
+      else if (StringEndsWith(attachment->m_realName, NS_LITERAL_CSTRING(".uue")))
+        attachment->m_realName.Cut(attachment->m_realName.Length() - 4, 4);
     }
   }
 }
 
 // Utility to create a nsIURI object...
 nsresult
 nsMsgNewURL(nsIURI** aInstancePtrResult, const char * aSpec)
 {
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -1030,19 +1030,18 @@ nsresult nsMsgCompose::_SendMsg(MSG_Deli
                     m_compFields,
                     PR_FALSE,                           // PRBool                            digest_p,
                     PR_FALSE,                           // PRBool                            dont_deliver_p,
                     (nsMsgDeliverMode)deliverMode,      // nsMsgDeliverMode                  mode,
                     nsnull,                             // nsIMsgDBHdr                       *msgToReplace,
                     m_composeHTML?TEXT_HTML:TEXT_PLAIN, // const char                        *attachment1_type,
                     bodyString,                         // const char                        *attachment1_body,
                     bodyLength,                         // PRUint32                          attachment1_body_length,
-                    nsnull,                             // const struct nsMsgAttachmentData  *attachments,
-                    nsnull,                             // const struct nsMsgAttachedFile    *preloaded_attachments,
-                    nsnull,                             // nsMsgSendPart                     *relatedPart,
+                    nsnull,                             // nsIArray  *attachments,
+                    nsnull,                             // nsIArray preloaded_attachments,
                     m_window,                           // nsIDOMWindow                      *parentWindow;
                     mProgress,                          // nsIMsgProgress                    *progress,
                     sendListener,                       // listener
                     mSmtpPassword.get(),
                     mOriginalMsgURI,
                     mType);
 
       // Cleanup converted body...
--- a/mailnews/compose/src/nsMsgSend.cpp
+++ b/mailnews/compose/src/nsMsgSend.cpp
@@ -103,16 +103,18 @@
 #include "nsIAbCard.h"
 #include "nsIMsgProgress.h"
 #include "nsIMsgMessageService.h"
 #include "nsIMsgHdr.h"
 #include "nsIMsgFolder.h"
 #include "nsComposeStrings.h"
 #include "nsStringGlue.h"
 #include "nsMsgUtils.h"
+#include "nsIArray.h"
+#include "nsArrayUtils.h"
 
 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
 
 #define PREF_MAIL_SEND_STRUCT "mail.send_struct"
 #define PREF_MAIL_STRICTLY_MIME "mail.strictly_mime"
 #define PREF_MAIL_MESSAGE_WARNING_SIZE "mailnews.message_warning_size"
 #define PREF_MAIL_COLLECT_EMAIL_ADDRESS_OUTGOING "mail.collect_email_address_outgoing"
 #define PREF_MAIL_DONT_ATTACH_SOURCE "mail.compose.dont_attach_source_of_local_network_links"
@@ -526,68 +528,55 @@ nsMsgComposeAndSend::GatherMimeAttachmen
   if (status < 0)
     goto FAIL;
 
   if (m_attachments_only_p)
   {
     /* If we get here, we should be fetching attachments only! */
     if (m_attachments_done_callback)
     {
-      struct nsMsgAttachedFile *attachments;
+      nsMsgAttachedFile *attachments;
 
       NS_ASSERTION(m_attachment_count > 0, "not more attachment");
       if (m_attachment_count <= 0)
       {
         m_attachments_done_callback (nsnull, nsnull, nsnull);
         m_attachments_done_callback = nsnull;
         goto FAIL;
       }
 
-      attachments = (struct nsMsgAttachedFile *)PR_Malloc((m_attachment_count + 1) * sizeof(*attachments));
+      attachments = new nsMsgAttachedFile[m_attachment_count + 1];
 
       if (!attachments)
         goto FAILMEM;
-      memset(attachments, 0, ((m_attachment_count + 1) * sizeof(*attachments)));
       for (i = 0; i < m_attachment_count; i++)
       {
         nsMsgAttachmentHandler *ma = &m_attachments[i];
 
-#undef SNARF
-#define SNARF(x,y) do { if((y) && *(y) && !(x)) { ((x) = (y)); ((y) = 0); }} \
-           while(0)
-        // Rather than copying the strings and dealing with allocation
-        // failures, we'll just "move" them into the other struct (this
-        // should be ok since this file uses PR_FREEIF when discarding
-        // the mime_attachment objects.)
-        //
-        attachments[i].orig_url = ma->mURL;
-        attachments[i].tmp_file = ma->mTmpFile;
-
-        SNARF(attachments[i].type, ma->m_type);
-        SNARF(attachments[i].encoding, ma->m_encoding);
-        SNARF(attachments[i].description, ma->m_description);
-        SNARF(attachments[i].x_mac_type, ma->m_x_mac_type);
-        SNARF(attachments[i].x_mac_creator, ma->m_x_mac_creator);
-
-#undef SNARF
-        attachments[i].size = ma->m_size;
-        attachments[i].unprintable_count = ma->m_unprintable_count;
-        attachments[i].highbit_count = ma->m_highbit_count;
-        attachments[i].ctl_count = ma->m_ctl_count;
-        attachments[i].null_count = ma->m_null_count;
-        attachments[i].max_line_length = ma->m_max_column;
+        attachments[i].m_origUrl = ma->mURL;
+        attachments[i].m_tmpFile = ma->mTmpFile;
+
+        attachments[i].m_type = ma->m_type;
+        attachments[i].m_encoding, ma->m_encoding;
+        attachments[i].m_description = ma->m_description;
+        attachments[i].m_xMacType = ma->m_xMacType;
+        attachments[i].m_xMacCreator = ma->m_xMacCreator;
+
+        attachments[i].m_size = ma->m_size;
+        attachments[i].m_unprintableCount = ma->m_unprintable_count;
+        attachments[i].m_highbitCount = ma->m_highbit_count;
+        attachments[i].m_ctlCount = ma->m_ctl_count;
+        attachments[i].m_nullCount = ma->m_null_count;
+        attachments[i].m_maxLineLength = ma->m_max_column;
 
         /* Doesn't really matter, but let's not lie about encoding
            in case it does someday. */
-        if (attachments[i].highbit_count > 0 && attachments[i].encoding &&
-            !PL_strcasecmp(attachments[i].encoding, ENCODING_7BIT))
-        {
-          PR_Free(attachments[i].encoding);
-          attachments[i].encoding = PL_strdup(ENCODING_8BIT);
-        }
+        if (attachments[i].m_highbitCount > 0 &&
+            attachments[i].m_encoding.LowerCaseEqualsLiteral(ENCODING_7BIT))
+          attachments[i].m_encoding = ENCODING_8BIT;
       }
 
       m_attachments_done_callback(nsnull, nsnull, attachments);
       PR_FREEIF(attachments);
       m_attachments_done_callback = nsnull;
     }
     goto FAIL;
   }
@@ -667,22 +656,19 @@ nsMsgComposeAndSend::GatherMimeAttachmen
     rv = NS_GetURLSpecFromFile(mHTMLFile, tempURL);
     if (NS_FAILED(rv) || NS_FAILED(nsMsgNewURL(getter_AddRefs(m_plaintext->mURL), tempURL.get())))
     {
       delete m_plaintext;
       m_plaintext = nsnull;
       goto FAILMEM;
     }
 
-    PR_FREEIF(m_plaintext->m_type);
-    m_plaintext->m_type = PL_strdup(TEXT_HTML);
-    PR_FREEIF(m_plaintext->m_charset);
-    m_plaintext->m_charset = PL_strdup(mCompFields->GetCharacterSet());
-    PR_FREEIF(m_plaintext->m_desired_type);
-    m_plaintext->m_desired_type = PL_strdup(TEXT_PLAIN);
+    m_plaintext->m_type = TEXT_HTML;
+    m_plaintext->m_charset = mCompFields->GetCharacterSet();
+    m_plaintext->m_desiredType = TEXT_PLAIN;
     m_attachment_pending_count ++;
     status = m_plaintext->SnarfAttachment(mCompFields);
     if (NS_FAILED(status))
       goto FAIL;
     if (m_attachment_pending_count > 0)
       return NS_OK;
   }
 
@@ -784,22 +770,22 @@ nsMsgComposeAndSend::GatherMimeAttachmen
     if (status < 0)
       goto FAIL;
 
     m_plaintext->mMainBody = PR_TRUE;
 
     // Determine Content-Transfer-Encoding for the attachments.
     m_plaintext->PickEncoding(mCompFields->GetCharacterSet(), this);
     const char *charset = mCompFields->GetCharacterSet();
-    hdrs = mime_generate_attachment_headers(m_plaintext->m_type,
+    hdrs = mime_generate_attachment_headers(m_plaintext->m_type.get(),
                         nsnull,
-                        m_plaintext->m_encoding,
-                        m_plaintext->m_description,
-                        m_plaintext->m_x_mac_type,
-                        m_plaintext->m_x_mac_creator,
+                        m_plaintext->m_encoding.get(),
+                        m_plaintext->m_description.get(),
+                        m_plaintext->m_xMacType.get(),
+                        m_plaintext->m_xMacCreator.get(),
                         nsnull, 0,
                         m_digest_p,
                         m_plaintext,
                         charset,
                         charset,
                         body_is_us_ascii,
                         nsnull,
                         PR_TRUE);
@@ -832,27 +818,27 @@ nsMsgComposeAndSend::GatherMimeAttachmen
         goto FAIL;
 
       // Create the encoder for the plaintext part here,
       // because we aren't the main part (attachment1).
       // (This, along with the rest of the routine, should really
       // be restructured so that no special treatment is given to
       // the main body text that came in. Best to put attachment1_text
       // etc. into a nsMsgSendPart, then reshuffle the parts. Sigh.)
-      if (!PL_strcasecmp(m_plaintext->m_encoding, ENCODING_QUOTED_PRINTABLE))
+      if (m_plaintext->m_encoding.LowerCaseEqualsLiteral(ENCODING_QUOTED_PRINTABLE))
       {
         MimeEncoderData *plaintext_enc = MIME_QPEncoderInit(mime_encoder_output_fn, this);
         if (!plaintext_enc)
         {
           status = NS_ERROR_OUT_OF_MEMORY;
           goto FAIL;
         }
         plainpart->SetEncoderData(plaintext_enc);
       }
-      else if (!PL_strcasecmp(m_plaintext->m_encoding, ENCODING_BASE64))
+      else if (m_plaintext->m_encoding.LowerCaseEqualsLiteral(ENCODING_BASE64))
       {
         MimeEncoderData *plaintext_enc = MIME_B64EncoderInit(mime_encoder_output_fn, this);
         if (!plaintext_enc)
         {
           status = NS_ERROR_OUT_OF_MEMORY;
           goto FAIL;
         }
         plainpart->SetEncoderData(plaintext_enc);
@@ -867,17 +853,17 @@ nsMsgComposeAndSend::GatherMimeAttachmen
       mainbody = maincontainer;
       PR_FREEIF(m_attachment1_type);
       m_attachment1_type = PL_strdup(TEXT_PLAIN);
       if (!m_attachment1_type)
         goto FAILMEM;
 
       /* Override attachment1_encoding here. */
       PR_FREEIF(m_attachment1_encoding);
-      m_attachment1_encoding = PL_strdup(m_plaintext->m_encoding);
+      m_attachment1_encoding = ToNewCString(m_plaintext->m_encoding);
 
       plaintext_is_mainbody_p = PR_TRUE; // converted plaintext is mainbody
     }
   }
 
   // check if we need to encapsulate the message in a multipart/mixed or multipart/digest
   if (m_attachment_count > multipartRelatedCount)
   {
@@ -1154,63 +1140,59 @@ nsMsgComposeAndSend::PreProcessPart(nsMs
   // If this was one of those dead parts from a quoted web page,
   // then just return safely.
   //
   if (ma->m_bogus_attachment)
     return 0;
 
   // If at this point we *still* don't have a content-type, then
   // we're never going to get one.
-  if (ma->m_type == nsnull)
-  {
-    ma->m_type = PL_strdup(UNKNOWN_CONTENT_TYPE);
-    if (ma->m_type == nsnull)
-      return 0;
-  }
+  if (ma->m_type.IsEmpty())
+    ma->m_type = UNKNOWN_CONTENT_TYPE;
 
   ma->PickEncoding (mCompFields->GetCharacterSet(), this);
   ma->PickCharset();
 
   part = new nsMsgSendPart(this);
   if (!part)
     return 0;
   status = toppart->AddChild(part);
   if (NS_FAILED(status))
     return 0;
-  status = part->SetType(ma->m_type);
+  status = part->SetType(ma->m_type.get());
   if (NS_FAILED(status))
     return 0;
 
   nsCString turl;
   if (!ma->mURL)
-    {
-      if (ma->m_uri)
-        turl = ma->m_uri;
-    }
+  {
+    if (!ma->m_uri.IsEmpty())
+      turl = ma->m_uri;
+  }
   else
     ma->mURL->GetSpec(turl);
-  hdrs = mime_generate_attachment_headers (ma->m_type,
-                                           ma->m_type_param,
-                                           ma->m_encoding,
-                                           ma->m_description,
-                                           ma->m_x_mac_type,
-                                           ma->m_x_mac_creator,
-                                           ma->m_real_name,
+  hdrs = mime_generate_attachment_headers (ma->m_type.get(),
+                                           ma->m_typeParam.get(),
+                                           ma->m_encoding.get(),
+                                           ma->m_description.get(),
+                                           ma->m_xMacType.get(),
+                                           ma->m_xMacCreator.get(),
+                                           ma->m_realName.get(),
                                            turl.get(),
                                            m_digest_p,
                                            ma,
-                                           ma->m_charset, // rhp - this needs
+                                           ma->m_charset.get(), // rhp - this needs
                                                           // to be the charset
                                                           // we determine from
                                                           // the file or none
                                                           // at all!
                                            mCompFields->GetCharacterSet(),
                                            PR_FALSE,      // bodyIsAsciiOnly to false
                                                           // for attachments
-                                           ma->m_content_id,
+                                           ma->m_contentId.get(),
                                            PR_FALSE);
   if (!hdrs)
     return 0;
 
   status = part->SetOtherHeaders(hdrs);
   PR_FREEIF(hdrs);
   if (NS_FAILED(status))
     return 0;
@@ -1222,19 +1204,18 @@ nsMsgComposeAndSend::PreProcessPart(nsMs
     status = part->SetEncoderData(ma->m_encoder_data);
     if (NS_FAILED(status))
       return 0;
     ma->m_encoder_data = nsnull;
   }
 
   ma->m_current_column = 0;
 
-  if (ma->m_type &&
-      (!PL_strcasecmp (ma->m_type, MESSAGE_RFC822) ||
-      !PL_strcasecmp (ma->m_type, MESSAGE_NEWS))) {
+  if (ma->m_type.LowerCaseEqualsLiteral(MESSAGE_RFC822) ||
+      ma->m_type.LowerCaseEqualsLiteral(MESSAGE_NEWS)) {
     status = part->SetStripSensitiveHeaders(PR_TRUE);
     if (NS_FAILED(status))
       return 0;
   }
 
   return 1;
 }
 
@@ -1342,17 +1323,16 @@ nsMsgComposeAndSend::GetEmbeddedObjectIn
   NS_ENSURE_ARG_POINTER(acceptObject);
 
 // GetEmbeddedObjectInfo will determine if we need to attach the source of the embedded object with the message
 // The decision is made automatically unless the attribute moz-do-not-send has been set to true or false
 // The default rule is that all image and anchor objects are attached as well link to a local file
   nsresult rv;
 
   // Reset this structure to null!
-  memset(attachment, 0, sizeof(nsMsgAttachmentData));
   *acceptObject = PR_FALSE;
 
   // Check if the object has a moz-do-not-send attribute set. If it's true,
   // we must ignore it, if false set forceToBeAttached to be true.
 
   PRBool forceToBeAttached = PR_FALSE;
   nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(node);
   if (domElement)
@@ -1378,34 +1358,32 @@ nsMsgComposeAndSend::GetEmbeddedObjectIn
   // First, try to see if the body as a background image
   if (body)
   {
     nsAutoString    tUrl;
     if (NS_SUCCEEDED(body->GetBackground(tUrl)))
     {
       nsCAutoString turlC;
       CopyUTF16toUTF8(tUrl, turlC);
-      if (NS_SUCCEEDED(nsMsgNewURL(&attachment->url, turlC.get())))
-        NS_IF_ADDREF(attachment->url);
-      else
+      if (NS_FAILED(nsMsgNewURL(getter_AddRefs(attachment->m_url), turlC.get())))
         return NS_OK;
      }
   }
   else if (image)        // Is this an image?
   {
     nsString    tUrl;
     nsString    tName;
     nsString    tDesc;
 
     // Create the URI
     if (NS_FAILED(image->GetSrc(tUrl)))
       return NS_ERROR_FAILURE;
     nsCAutoString turlC;
     CopyUTF16toUTF8(tUrl, turlC);
-    if (NS_FAILED(nsMsgNewURL(&attachment->url, turlC.get())))
+    if (NS_FAILED(nsMsgNewURL(getter_AddRefs(attachment->m_url), turlC.get())))
     {
       // Well, the first time failed...which means we probably didn't get
       // the full path name...
       //
       nsIDOMDocument    *ownerDocument = nsnull;
       node->GetOwnerDocument(&ownerDocument);
       if (ownerDocument)
       {
@@ -1425,83 +1403,74 @@ nsMsgComposeAndSend::GetEmbeddedObjectIn
         // got from the GetSrc() call....
         NS_ConvertUTF8toUTF16 workURL(spec);
 
         PRInt32 loc = workURL.RFindChar('/');
         if (loc >= 0)
           workURL.SetLength(loc+1);
         workURL.Append(tUrl);
         NS_ConvertUTF16toUTF8 workurlC(workURL);
-        if (NS_FAILED(nsMsgNewURL(&attachment->url, workurlC.get())))
-        {
+        if (NS_FAILED(nsMsgNewURL(getter_AddRefs(attachment->m_url), workurlC.get())))
           // rhp - just try to continue and send it without this image.
           return NS_OK;
-        }
       }
     }
 
-    NS_IF_ADDREF(attachment->url);
-
     rv = image->GetName(tName);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    attachment->real_name = ToNewCString(NS_LossyConvertUTF16toASCII(tName)); // XXX i18n
+    LossyCopyUTF16toASCII(tName, attachment->m_realName);
     rv = image->GetLongDesc(tDesc);
     NS_ENSURE_SUCCESS(rv, rv);
-    attachment->description = ToNewCString(NS_LossyConvertUTF16toASCII(tDesc)); // XXX i18n
-
+    attachment->m_description = NS_LossyConvertUTF16toASCII(tDesc); // XXX i18n
   }
   else if (link)        // Is this a link?
   {
     nsString    tUrl;
 
     // Create the URI
     rv = link->GetHref(tUrl);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCAutoString turlC;
     CopyUTF16toUTF8(tUrl, turlC);
-    rv = nsMsgNewURL(&attachment->url, turlC.get());
+    rv = nsMsgNewURL(getter_AddRefs(attachment->m_url), turlC.get());
     NS_ENSURE_SUCCESS(rv, rv);
-
-    NS_IF_ADDREF(attachment->url);
   }
   else if (anchor)
   {
     nsString    tUrl;
     nsString    tName;
 
     // Create the URI
     rv = anchor->GetHref(tUrl);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCAutoString turlC;
     CopyUTF16toUTF8(tUrl, turlC);
-    rv = nsMsgNewURL(&attachment->url, turlC.get());
+    rv = nsMsgNewURL(getter_AddRefs(attachment->m_url), turlC.get());
     NS_ENSURE_SUCCESS(rv, rv);
 
-    NS_IF_ADDREF(attachment->url);
-
     rv = anchor->GetName(tName);
     NS_ENSURE_SUCCESS(rv, rv);
-    attachment->real_name = ToNewCString(NS_LossyConvertUTF16toASCII(tName));
+    LossyCopyUTF16toASCII(tName, attachment->m_realName);
   }
   else
   {
     // If we get here, we got something we didn't expect!
     // Just try to continue and send it without this thing.
     return NS_OK;
   }
 
   //
   // Before going further, check if we are dealing with a local file and
   // if it's the case be sure the file exist!
   PRBool schemeIsFile = PR_FALSE;
-  rv = attachment->url->SchemeIs("file", &schemeIsFile);
+  rv = attachment->m_url->SchemeIs("file", &schemeIsFile);
   if (NS_SUCCEEDED(rv) && schemeIsFile)
   {
-    nsCOMPtr<nsIFileURL> fileUrl (do_QueryInterface(attachment->url));
+    nsCOMPtr<nsIFileURL> fileUrl (do_QueryInterface(attachment->m_url));
     if (fileUrl)
     {
       PRBool isAValidFile = PR_FALSE;
 
       nsCOMPtr<nsIFile> aFile;
       rv = fileUrl->GetFile(getter_AddRefs(aFile));
       if (NS_SUCCEEDED(rv) && aFile)
       {
@@ -1513,17 +1482,17 @@ nsMsgComposeAndSend::GetEmbeddedObjectIn
             isAValidFile = PR_FALSE;
           else
           {
             if (anchor)
             {
               // One more test, if the anchor points to a local network server, let's check what the pref
               // mail.compose.dont_attach_source_of_local_network_links tells us to do.
               nsCAutoString urlSpec;
-              rv = attachment->url->GetSpec(urlSpec);
+              rv = attachment->m_url->GetSpec(urlSpec);
               if (NS_SUCCEEDED(rv))
                 if (StringBeginsWith(urlSpec, NS_LITERAL_CSTRING("file://///")))
                 {
                   nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
                   if (pPrefBranch)
                   {
                     PRBool dontSend = PR_FALSE;
                     rv = pPrefBranch->GetBoolPref(PREF_MAIL_DONT_ATTACH_SOURCE, &dontSend);
@@ -1580,17 +1549,16 @@ nsMsgComposeAndSend::GetMultipartRelated
 
       PRInt32 i;
       nsCOMPtr<nsIDOMNode> node;
       nsCOMPtr <nsISupports> isupp;
 
       for (i = count - 1, count = 0; i >= 0; i --)
       {
         // Reset this structure to null!
-        memset(&attachment, 0, sizeof(nsMsgAttachmentData));
 
         // now we need to get the element in the array and do the magic
         // to process this element.
         //
         mEmbeddedObjectList->QueryElementAt(i, NS_GET_IID(nsIDOMNode), getter_AddRefs(node));
         if (!node)
           continue;
 
@@ -1897,19 +1865,16 @@ nsMsgComposeAndSend::ProcessMultipartRel
     if (!domSaveArray)
       return NS_ERROR_MIME_MPART_ATTACHMENT_ERROR;
     memset(domSaveArray, 0, sizeof(domSaveStruct) * multipartCount);
   }
 
   nsCOMPtr<nsIDOMNode> node;
   for (i = mPreloadedAttachmentCount; i < (mPreloadedAttachmentCount + multipartCount); i++)
   {
-    // Reset this structure to null!
-    memset(&attachment, 0, sizeof(nsMsgAttachmentData));
-
     // MUST set this to get placed in the correct part of the message
     m_attachments[i].mMHTMLPart = PR_TRUE;
 
     locCount++;
     m_attachments[i].mDeleteFile = PR_TRUE;
     m_attachments[i].m_done = PR_FALSE;
     m_attachments[i].SetMimeDeliveryState(this);
 
@@ -1931,64 +1896,52 @@ nsMsgComposeAndSend::ProcessMultipartRel
     j++;
     domSaveArray[j].node = node;
 
     // check if we have alreay attached this object, don't need to attach it twice
     duplicateOf = -1;
     for (k = mPreloadedAttachmentCount; k < i; k++)
     {
       PRBool isEqual = PR_FALSE;
-      (void)attachment.url->Equals(m_attachments[k].mURL, &isEqual);
+      (void)attachment.m_url->Equals(m_attachments[k].mURL, &isEqual);
       if (isEqual)
       {
         duplicateOf = k;
         break;
       }
     }
 
     if (duplicateOf == -1)
     {
       //
       // Now we have to get all of the interesting information from
       // the nsIDOMNode we have in hand...
-      m_attachments[i].mURL = attachment.url;
-
-      PR_FREEIF(m_attachments[i].m_override_type);
-      m_attachments[i].m_override_type = PL_strdup (attachment.real_type);
-      PR_FREEIF(m_attachments[i].m_override_encoding);
-      m_attachments[i].m_override_encoding = PL_strdup (attachment.real_encoding);
-      PR_FREEIF(m_attachments[i].m_desired_type);
-      m_attachments[i].m_desired_type = PL_strdup (attachment.desired_type);
-      PR_FREEIF(m_attachments[i].m_description);
-      m_attachments[i].m_description = PL_strdup (attachment.description);
-      PR_FREEIF(m_attachments[i].m_real_name);
-      m_attachments[i].m_real_name = PL_strdup (attachment.real_name);
-      PR_FREEIF(m_attachments[i].m_x_mac_type);
-      m_attachments[i].m_x_mac_type = PL_strdup (attachment.x_mac_type);
-      PR_FREEIF(m_attachments[i].m_x_mac_creator);
-      m_attachments[i].m_x_mac_creator = PL_strdup (attachment.x_mac_creator);
-
-      PR_FREEIF(m_attachments[i].m_charset);
-      m_attachments[i].m_charset = PL_strdup (mCompFields->GetCharacterSet());
-      PR_FREEIF(m_attachments[i].m_encoding);
-      m_attachments[i].m_encoding = PL_strdup ("7bit");
+      m_attachments[i].mURL = attachment.m_url;
+
+      m_attachments[i].m_overrideType = attachment.m_realType;
+      m_attachments[i].m_overrideEncoding = attachment.m_realEncoding;
+      m_attachments[i].m_desiredType = attachment.m_desiredType;
+      m_attachments[i].m_description = attachment.m_description;
+      m_attachments[i].m_realName = attachment.m_realName;
+      m_attachments[i].m_xMacType = attachment.m_xMacType;
+      m_attachments[i].m_xMacCreator = attachment.m_xMacCreator;
+
+      m_attachments[i].m_charset = mCompFields->GetCharacterSet();
+      m_attachments[i].m_encoding = "7bit";
 
       if (m_attachments[i].mURL)
         msg_pick_real_name(&m_attachments[i], nsnull, mCompFields->GetCharacterSet());
 
       //
       // Next, generate a content id for use with this part
       //
       nsCString email;
       mUserIdentity->GetEmail(email);
       email.StripWhitespace();
-      m_attachments[i].m_content_id = mime_gen_content_id(locCount+1, email.get());
-
-      if (!m_attachments[i].m_content_id)
-        return NS_ERROR_OUT_OF_MEMORY;
+      m_attachments[i].m_contentId = mime_gen_content_id(locCount+1, email.get());
 
       //
       // Start counting the attachments which are going to come from mail folders
       // and from NNTP servers.
       //
       if (m_attachments[i].mURL)
       {
         nsIURI *uri = m_attachments[i].mURL;
@@ -1997,35 +1950,26 @@ nsMsgComposeAndSend::ProcessMultipartRel
            (NS_SUCCEEDED(uri->SchemeIs("imap", &match)) && match))
           (*aMailboxCount)++;
         else if ((NS_SUCCEEDED(uri->SchemeIs("news", &match)) && match) ||
                 (NS_SUCCEEDED(uri->SchemeIs("snews", &match)) && match))
           (*aNewsCount)++;
       }
     }
 
-    // Ok, cleanup the temp structure...
-    PR_Free(attachment.real_name);
-    PR_Free(attachment.description);
-    PR_Free(attachment.real_type);
-    PR_Free(attachment.real_encoding);
-    PR_Free(attachment.desired_type);
-    PR_Free(attachment.x_mac_type);
-    PR_Free(attachment.x_mac_creator);
-
     //
     // Ok, while we are here, we should whack the DOM with the generated
     // Content-ID for this object. This will be necessary for generating
     // the HTML we need.
     //
     nsString domURL;
-    if (m_attachments[duplicateOf == -1 ? i : duplicateOf].m_content_id)
+    if (!m_attachments[duplicateOf == -1 ? i : duplicateOf].m_contentId.IsEmpty())
     {
       nsString   newSpec(NS_LITERAL_STRING("cid:"));
-      newSpec.Append(NS_ConvertASCIItoUTF16(m_attachments[duplicateOf == -1 ? i : duplicateOf].m_content_id));
+      newSpec.Append(NS_ConvertASCIItoUTF16(m_attachments[duplicateOf == -1 ? i : duplicateOf].m_contentId));
 
       // Now, we know the types of objects this node can be, so we will do
       // our query interface here and see what we come up with
       nsCOMPtr<nsIDOMHTMLBodyElement>     body = (do_QueryInterface(domSaveArray[j].node));
       nsCOMPtr<nsIDOMHTMLImageElement>    image = (do_QueryInterface(domSaveArray[j].node));
       nsCOMPtr<nsIDOMHTMLLinkElement>     link = (do_QueryInterface(domSaveArray[j].node));
       nsCOMPtr<nsIDOMHTMLAnchorElement>   anchor = (do_QueryInterface(domSaveArray[j].node));
 
@@ -2236,105 +2180,99 @@ nsMsgComposeAndSend::AddCompFieldLocalAt
 
   #ifdef MAC_OSX
           //Mac always need to snarf the file to figure out how to send it, maybe we need to use apple double...
           //  unless caller has already set the content type, in which case, trust them.
           PRBool mustSnarfAttachment = PR_TRUE;
   #else
           PRBool mustSnarfAttachment = PR_FALSE;
   #endif
-          PR_FREEIF(m_attachments[newLoc].m_type);
-          attachment->GetContentType(&m_attachments[newLoc].m_type);
-          if (!m_attachments[newLoc].m_type || !(*m_attachments[newLoc].m_type))
+          attachment->GetContentType(getter_Copies(m_attachments[newLoc].m_type));
+          if (m_attachments[newLoc].m_type.IsEmpty())
           {
             nsresult  rv = NS_OK;
             nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
             if (NS_SUCCEEDED(rv) && mimeFinder)
             {
               nsCOMPtr<nsIURL> fileUrl(do_CreateInstance(NS_STANDARDURL_CONTRACTID));
               if (fileUrl)
               {
                 nsCAutoString fileExt;
                 //First try using the real file name
-                rv = fileUrl->SetFileName(nsDependentCString(m_attachments[newLoc].m_real_name));
+                rv = fileUrl->SetFileName(m_attachments[newLoc].m_realName);
                 if (NS_SUCCEEDED(rv))
                 {
                   rv = fileUrl->GetFileExtension(fileExt);
                   if (NS_SUCCEEDED(rv) && !fileExt.IsEmpty()) {
                     nsCAutoString type;
                     mimeFinder->GetTypeFromExtension(fileExt, type);
   #ifndef XP_MACOSX
                     if (!type.Equals("multipart/appledouble"))  // can't do apple double on non-macs
   #endif
-                    m_attachments[newLoc].m_type = ToNewCString(type);
+                    m_attachments[newLoc].m_type = type;
                   }
                 }
 
                 //Then try using the url if we still haven't figured out the content type
-                if ((!m_attachments[newLoc].m_type) ||  (!*m_attachments[newLoc].m_type))
+                if (m_attachments[newLoc].m_type.IsEmpty())
                 {
                   rv = fileUrl->SetSpec(url);
                   if (NS_SUCCEEDED(rv))
                   {
                     rv = fileUrl->GetFileExtension(fileExt);
                     if (NS_SUCCEEDED(rv) && !fileExt.IsEmpty()) {
                       nsCAutoString type;
                       mimeFinder->GetTypeFromExtension(fileExt, type);
   #ifndef XP_MACOSX
                     if (!type.Equals("multipart/appledouble"))  // can't do apple double on non-macs
   #endif
-                      m_attachments[newLoc].m_type = ToNewCString(type);
+                      m_attachments[newLoc].m_type = type;
                     // rtf and vcs files may look like text to sniffers,
                     // but they're not human readable.
                     if (type.IsEmpty() && !fileExt.IsEmpty() &&
                          (MsgLowerCaseEqualsLiteral(fileExt, "rtf") ||
                           MsgLowerCaseEqualsLiteral(fileExt, "vcs")))
-                      m_attachments[newLoc].m_type = PL_strdup(APPLICATION_OCTET_STREAM);
+                      m_attachments[newLoc].m_type = APPLICATION_OCTET_STREAM;
                     }
                   }
                 }
               }
             }
           }
           else
           {
-            attachment->GetContentTypeParam(&m_attachments[newLoc].m_type_param);
+            attachment->GetContentTypeParam(getter_Copies(m_attachments[newLoc].m_typeParam));
             mustSnarfAttachment = PR_FALSE;
           }
 
           //We need to snarf the file to figure out how to send it only if we don't have a content type...
-          if (mustSnarfAttachment || (!m_attachments[newLoc].m_type) || (!*m_attachments[newLoc].m_type))
+          if (mustSnarfAttachment || m_attachments[newLoc].m_type.IsEmpty())
           {
             m_attachments[newLoc].m_done = PR_FALSE;
             m_attachments[newLoc].SetMimeDeliveryState(this);
           }
           else
           {
             m_attachments[newLoc].m_done = PR_TRUE;
             m_attachments[newLoc].SetMimeDeliveryState(nsnull);
           }
           // For local files, if they are HTML docs and we don't have a charset, we should
           // sniff the file and see if we can figure it out.
-          if ( (m_attachments[newLoc].m_type) &&  (*m_attachments[newLoc].m_type) )
+          if (!m_attachments[newLoc].m_type.IsEmpty())
           {
-            if (PL_strcasecmp(m_attachments[newLoc].m_type, TEXT_HTML) == 0)
+            if (m_attachments[newLoc].m_type.LowerCaseEqualsLiteral(TEXT_HTML))
             {
               char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(m_attachments[newLoc].mTmpFile);
               if (tmpCharset[0] != '\0')
-              {
-                PR_FREEIF(m_attachments[newLoc].m_charset);
-                m_attachments[newLoc].m_charset = PL_strdup(tmpCharset);
-              }
+                m_attachments[newLoc].m_charset = tmpCharset;
             }
           }
 
-          PR_FREEIF(m_attachments[newLoc].m_x_mac_type);
-          attachment->GetMacType(&m_attachments[newLoc].m_x_mac_type);
-          PR_FREEIF(m_attachments[newLoc].m_x_mac_creator);
-          attachment->GetMacCreator(&m_attachments[newLoc].m_x_mac_creator);
+          attachment->GetMacType(getter_Copies(m_attachments[newLoc].m_xMacType));
+          attachment->GetMacCreator(getter_Copies(m_attachments[newLoc].m_xMacCreator));
 
           ++newLoc;
         }
       }
     }
   }
   return NS_OK;
 }
@@ -2380,36 +2318,33 @@ nsMsgComposeAndSend::AddCompFieldRemoteA
 
           m_attachments[newLoc].mDeleteFile = PR_TRUE;
           m_attachments[newLoc].m_done = PR_FALSE;
           m_attachments[newLoc].SetMimeDeliveryState(this);
 
           if (!isAMessageAttachment)
             nsMsgNewURL(getter_AddRefs(m_attachments[newLoc].mURL), url.get());
 
-          PR_FREEIF(m_attachments[newLoc].m_encoding);
-          m_attachments[newLoc].m_encoding = PL_strdup ("7bit");
-
-          PR_FREEIF(m_attachments[newLoc].m_x_mac_type);
-          attachment->GetMacType(&m_attachments[newLoc].m_x_mac_type);
-          PR_FREEIF(m_attachments[newLoc].m_x_mac_creator);
-          attachment->GetMacCreator(&m_attachments[newLoc].m_x_mac_creator);
+          m_attachments[newLoc].m_encoding = "7bit";
+
+          attachment->GetMacType(getter_Copies(m_attachments[newLoc].m_xMacType));
+          attachment->GetMacCreator(getter_Copies(m_attachments[newLoc].m_xMacCreator));
 
           /* Count up attachments which are going to come from mail folders
              and from NNTP servers. */
           PRBool do_add_attachment = PR_FALSE;
           if (isAMessageAttachment)
           {
             do_add_attachment = PR_TRUE;
             if (!PL_strncasecmp(url.get(), "news-message://", 15))
               (*aNewsCount)++;
             else
               (*aMailboxCount)++;
 
-            m_attachments[newLoc].m_uri = PL_strdup(url.get());
+            m_attachments[newLoc].m_uri = url;
             m_attachments[newLoc].mURL = nsnull;
           }
           else
             do_add_attachment = (nsnull != m_attachments[newLoc].mURL);
 
           if (do_add_attachment)
           {
             nsAutoString proposedName;
@@ -2420,151 +2355,137 @@ nsMsgComposeAndSend::AddCompFieldRemoteA
         }
       }
     }
   }
   return NS_OK;
 }
 
 nsresult
-nsMsgComposeAndSend::HackAttachments(const nsMsgAttachmentData *attachments,
-                                     const nsMsgAttachedFile *preloaded_attachments)
+nsMsgComposeAndSend::HackAttachments(nsIArray *attachments,
+                                     nsIArray *preloadedAttachments)
 {
   //
   // First, count the total number of attachments we are going to process
   // for this operation! This is a little more complicated than you might
   // think because we have a few ways to specify attachments. Via the nsMsgAttachmentData
   // as well as the composition fields.
   //
   CountCompFieldAttachments();
 
   // Count the preloaded attachments!
   mPreloadedAttachmentCount = 0;
 
   // For now, manually add the local attachments in the comp field!
   mPreloadedAttachmentCount += mCompFieldLocalAttachments;
-
-  if (preloaded_attachments && preloaded_attachments[0].orig_url)
-  {
-    while (preloaded_attachments[mPreloadedAttachmentCount].orig_url)
-      mPreloadedAttachmentCount++;
-  }
+  PRUint32 numAttachments = 0, numPreloadedAttachments = 0;
+  if (attachments)
+    attachments->GetLength(&numAttachments);
+  if (preloadedAttachments)
+    preloadedAttachments->GetLength(&numPreloadedAttachments);
+  mPreloadedAttachmentCount += numPreloadedAttachments;
 
   // Count the attachments we have to go retrieve! Keep in mind, that these
   // will be APPENDED to the current list of URL's that we have gathered if
   // this is a multpart/related send operation
   mRemoteAttachmentCount = GetMultipartRelatedCount();
 
   // For now, manually add the remote attachments in the comp field!
   mRemoteAttachmentCount += mCompFieldRemoteAttachments;
 
-  PRInt32     tCount = 0;
-  if (attachments && attachments[0].url)
-  {
-    while (attachments[tCount].url)
-    {
-      mRemoteAttachmentCount++;
-      tCount++;
-    }
-  }
+  PRInt32 tCount = 0;
+  mRemoteAttachmentCount += numAttachments;
+  tCount += numAttachments;
 
   m_attachment_count = mPreloadedAttachmentCount + mRemoteAttachmentCount;
 
   // Now create the array of attachment handlers...
   m_attachments = (nsMsgAttachmentHandler *) new nsMsgAttachmentHandler[m_attachment_count];
   if (! m_attachments)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // clear this new memory...
-  memset(m_attachments, 0, (sizeof(nsMsgAttachmentHandler) * m_attachment_count));
   PRUint32     i;    // counter for location in attachment array...
 
   //
   // First, we need to attach the files that are defined in the comp fields...
   if (NS_FAILED(AddCompFieldLocalAttachments()))
     return NS_ERROR_INVALID_ARG;
 
   // Now handle the preloaded attachments...
-  if (preloaded_attachments && preloaded_attachments[0].orig_url)
+  if (numPreloadedAttachments > 0)
   {
     // These are attachments which have already been downloaded to tmp files.
     // We merely need to point the internal attachment data at those tmp
     // files.
     m_pre_snarfed_attachments_p = PR_TRUE;
 
     for (i = mCompFieldLocalAttachments; i < mPreloadedAttachmentCount; i++)
     {
+      nsCOMPtr<nsIMsgAttachedFile> attachedFile = do_QueryElementAt(preloadedAttachments, i);
+      if (!attachedFile)
+        continue;
+
       /* These attachments are already "snarfed". */
       m_attachments[i].mDeleteFile = PR_FALSE;
       m_attachments[i].SetMimeDeliveryState(nsnull);
       m_attachments[i].m_done = PR_TRUE;
-      NS_ASSERTION (preloaded_attachments[i].orig_url, "null url");
-
-      m_attachments[i].mURL = preloaded_attachments[i].orig_url;
-
-      PR_FREEIF(m_attachments[i].m_type);
-      m_attachments[i].m_type = PL_strdup (preloaded_attachments[i].type);
+
+      attachedFile->GetOrigUrl(getter_AddRefs(m_attachments[i].mURL));
+
+      attachedFile->GetType(m_attachments[i].m_type);
 
       // Set it to the compose fields for a default...
-      PR_FREEIF(m_attachments[i].m_charset);
-      m_attachments[i].m_charset = PL_strdup (mCompFields->GetCharacterSet());
+      m_attachments[i].m_charset = mCompFields->GetCharacterSet();
 
       // If we still don't have a content type, we should really try sniff one out!
-      if ((!m_attachments[i].m_type) || (!*m_attachments[i].m_type))
-      {
+      if (m_attachments[i].m_type.IsEmpty())
         m_attachments[i].PickEncoding(mCompFields->GetCharacterSet(), this);
-      }
 
       // For local files, if they are HTML docs and we don't have a charset, we should
       // sniff the file and see if we can figure it out.
-      if ( (m_attachments[i].m_type) &&  (*m_attachments[i].m_type) )
+      if (!m_attachments[i].m_type.IsEmpty())
       {
-        if ( (PL_strcasecmp(m_attachments[i].m_type, TEXT_HTML) == 0) && (preloaded_attachments[i].tmp_file) )
+        nsCOMPtr<nsILocalFile> tmpFile;
+        attachedFile->GetTmpFile(getter_AddRefs(tmpFile));
+        if (m_attachments[i].m_type.LowerCaseEqualsLiteral(TEXT_HTML) && tmpFile)
         {
-          char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(preloaded_attachments[i].tmp_file);
+          char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(tmpFile);
           if (tmpCharset[0] != '\0')
-          {
-            PR_FREEIF(m_attachments[i].m_charset);
-            m_attachments[i].m_charset = PL_strdup(tmpCharset);
-          }
+            m_attachments[i].m_charset = tmpCharset;
         }
       }
 
-      PR_FREEIF(m_attachments[i].m_description);
-      m_attachments[i].m_description = PL_strdup (preloaded_attachments[i].description);
-      PR_FREEIF(m_attachments[i].m_real_name);
-      m_attachments[i].m_real_name = PL_strdup (preloaded_attachments[i].real_name);
-      PR_FREEIF(m_attachments[i].m_x_mac_type);
-      m_attachments[i].m_x_mac_type = PL_strdup (preloaded_attachments[i].x_mac_type);
-      PR_FREEIF(m_attachments[i].m_x_mac_creator);
-      m_attachments[i].m_x_mac_creator = PL_strdup (preloaded_attachments[i].x_mac_creator);
-      PR_FREEIF(m_attachments[i].m_encoding);
-      m_attachments[i].m_encoding = PL_strdup (preloaded_attachments[i].encoding);
+      attachedFile->GetDescription(m_attachments[i].m_description);
+      attachedFile->GetRealName(m_attachments[i].m_realName);
+      attachedFile->GetXMacType(m_attachments[i].m_xMacType);
+      attachedFile->GetXMacCreator(m_attachments[i].m_xMacCreator);
+      attachedFile->GetEncoding(m_attachments[i].m_encoding);
 
       if (m_attachments[i].mTmpFile)
       {
         if (m_attachments[i].mDeleteFile)
           m_attachments[i].mTmpFile->Remove(PR_FALSE);
         m_attachments[i].mTmpFile = nsnull;
       }
-      m_attachments[i].mTmpFile = preloaded_attachments[i].tmp_file;
-
-      m_attachments[i].m_size = preloaded_attachments[i].size;
-      m_attachments[i].m_unprintable_count = preloaded_attachments[i].unprintable_count;
-      m_attachments[i].m_highbit_count = preloaded_attachments[i].highbit_count;
-      m_attachments[i].m_ctl_count = preloaded_attachments[i].ctl_count;
-      m_attachments[i].m_null_count = preloaded_attachments[i].null_count;
-      m_attachments[i].m_max_column = preloaded_attachments[i].max_line_length;
+      attachedFile->GetTmpFile(getter_AddRefs(m_attachments[i].mTmpFile));
+
+      attachedFile->GetSize(&m_attachments[i].m_size);
+      attachedFile->GetUnprintableCount(&m_attachments[i].m_unprintable_count);
+      attachedFile->GetHighbitCount(&m_attachments[i].m_highbit_count);
+      attachedFile->GetCtlCount(&m_attachments[i].m_ctl_count);
+      attachedFile->GetNullCount(&m_attachments[i].m_null_count);
+      attachedFile->GetMaxLineLength(&m_attachments[i].m_max_column);
 
       /* If the attachment has an encoding, and it's not one of
       the "null" encodings, then keep it. */
-      if (m_attachments[i].m_encoding &&
-          PL_strcasecmp (m_attachments[i].m_encoding, ENCODING_7BIT) &&
-          PL_strcasecmp (m_attachments[i].m_encoding, ENCODING_8BIT) &&
-          PL_strcasecmp (m_attachments[i].m_encoding, ENCODING_BINARY))
+      if (!m_attachments[i].m_encoding.IsEmpty() &&
+          !m_attachments[i].m_encoding.LowerCaseEqualsLiteral(ENCODING_7BIT) &&
+          !m_attachments[i].m_encoding.LowerCaseEqualsLiteral(ENCODING_8BIT) &&
+          !m_attachments[i].m_encoding.LowerCaseEqualsLiteral(ENCODING_BINARY))
         m_attachments[i].m_already_encoded_p = PR_TRUE;
 
             if (m_attachments[i].mURL)
         msg_pick_real_name(&m_attachments[i], nsnull, mCompFields->GetCharacterSet());
     }
   }
 
   // First, handle the multipart related attachments if any...
@@ -2588,48 +2509,41 @@ nsMsgComposeAndSend::HackAttachments(con
   if (NS_FAILED( AddCompFieldRemoteAttachments( (mPreloadedAttachmentCount + multipartRelatedCount),
                                                  &mailbox_count, &news_count) ))
     return NS_ERROR_INVALID_ARG;
 
   //
   // Now deal remote attachments and attach multipart/related attachments (url's and such..)
   // first!
   //
-  if (attachments && attachments[0].url)
+  if (attachments)
   {
     PRInt32     locCount = -1;
 
     for (i = (mPreloadedAttachmentCount + GetMultipartRelatedCount() + mCompFieldRemoteAttachments); i < m_attachment_count; i++)
     {
       locCount++;
+      nsCOMPtr<nsIMsgAttachmentData> attachment(do_QueryElementAt(attachments, i));
+      if (!attachment)
+        continue;
       m_attachments[i].mDeleteFile = PR_TRUE;
       m_attachments[i].m_done = PR_FALSE;
       m_attachments[i].SetMimeDeliveryState(this);
-      NS_ASSERTION (attachments[locCount].url, "null url");
-
-      m_attachments[i].mURL = attachments[locCount].url;
-
-      PR_FREEIF(m_attachments[i].m_override_type);
-      m_attachments[i].m_override_type = PL_strdup (attachments[locCount].real_type);
-      PR_FREEIF(m_attachments[i].m_charset);
-      m_attachments[i].m_charset = PL_strdup (mCompFields->GetCharacterSet());
-      PR_FREEIF(m_attachments[i].m_override_encoding);
-      m_attachments[i].m_override_encoding = PL_strdup (attachments[locCount].real_encoding);
-      PR_FREEIF(m_attachments[i].m_desired_type);
-      m_attachments[i].m_desired_type = PL_strdup (attachments[locCount].desired_type);
-      PR_FREEIF(m_attachments[i].m_description);
-      m_attachments[i].m_description = PL_strdup (attachments[locCount].description);
-      PR_FREEIF(m_attachments[i].m_real_name);
-      m_attachments[i].m_real_name = PL_strdup (attachments[locCount].real_name);
-      PR_FREEIF(m_attachments[i].m_x_mac_type);
-      m_attachments[i].m_x_mac_type = PL_strdup (attachments[locCount].x_mac_type);
-      PR_FREEIF(m_attachments[i].m_x_mac_creator);
-      m_attachments[i].m_x_mac_creator = PL_strdup (attachments[locCount].x_mac_creator);
-      PR_FREEIF(m_attachments[i].m_encoding);
-      m_attachments[i].m_encoding = PL_strdup ("7bit");
+
+      attachment->GetUrl(getter_AddRefs(m_attachments[i].mURL));
+
+      attachment->GetRealType(m_attachments[i].m_overrideType);
+      m_attachments[i].m_charset = mCompFields->GetCharacterSet();
+      attachment->GetRealEncoding(m_attachments[i].m_overrideEncoding);
+      attachment->GetDesiredType(m_attachments[i].m_desiredType);
+      attachment->GetDescription(m_attachments[i].m_description);
+      attachment->GetRealName(m_attachments[i].m_realName);
+      attachment->GetXMacType(m_attachments[i].m_xMacType);
+      attachment->GetXMacCreator(m_attachments[i].m_xMacCreator);
+      m_attachments[i].m_encoding = "7bit";
 
       // real name is set in the case of vcard so don't change it.  XXX STILL NEEDED?
       // m_attachments[i].m_real_name = 0;
 
       /* Count up attachments which are going to come from mail folders
       and from NNTP servers. */
     if (m_attachments[i].mURL)
     {
@@ -2668,17 +2582,17 @@ nsMsgComposeAndSend::HackAttachments(con
       {
         m_attachment_pending_count--;
         continue;
       }
 
       //
       //  IF we get here and the URL is NULL, just dec the pending count and move on!!!
       //
-      if ( (!m_attachments[i].mURL) && (!m_attachments[i].m_uri) )
+      if ( (!m_attachments[i].mURL) && (!m_attachments[i].m_uri.Length()) )
       {
         m_attachments[i].m_bogus_attachment = PR_TRUE;
         m_attachments[i].m_done = PR_TRUE;
         m_attachments[i].SetMimeDeliveryState(nsnull);
         m_attachment_pending_count--;
         continue;
       }
 
@@ -2687,20 +2601,17 @@ nsMsgComposeAndSend::HackAttachments(con
       // (and thus no exit routine was or will be called.)
       //
 
       // Display some feedback to user...
       PRUnichar     *printfString = nsnull;
       nsString msg;
       mComposeBundle->GetStringFromID(NS_MSG_GATHERING_ATTACHMENT, getter_Copies(msg));
 
-      if (m_attachments[i].m_real_name)
-        printfString = nsTextFormatter::smprintf(msg.get(), m_attachments[i].m_real_name);
-      else
-        printfString = nsTextFormatter::smprintf(msg.get(), "");
+      printfString = nsTextFormatter::smprintf(msg.get(), m_attachments[i].m_realName.get());
 
       if (printfString)
       {
         SetStatusMessage(nsDependentString(printfString));
         PR_Free(printfString);
       }
 
       /* As SnarfAttachment will call GatherMimeAttachments when it will be done (this is an async process),
@@ -2708,17 +2619,17 @@ nsMsgComposeAndSend::HackAttachments(con
       */
       needToCallGatherMimeAttachments = PR_FALSE;
 
       nsresult status = m_attachments[i].SnarfAttachment(mCompFields);
       if (NS_FAILED(status))
       {
         nsString errorMsg;
         nsAutoString attachmentFileName;
-        nsresult rv = ConvertToUnicode(nsMsgI18NFileSystemCharset(), m_attachments[i].m_real_name, attachmentFileName);
+        nsresult rv = ConvertToUnicode(nsMsgI18NFileSystemCharset(), m_attachments[i].m_realName, attachmentFileName);
         if (NS_SUCCEEDED(rv))
         {
           nsCOMPtr<nsIStringBundle> bundle;
           const PRUnichar *params[] = { attachmentFileName.get() };
           mComposeBundle->FormatStringFromID(NS_ERROR_GET_CODE(NS_MSG_ERROR_ATTACHING_FILE), params, 1, getter_Copies(errorMsg));
           mSendReport->SetMessage(nsIMsgSendReport::process_Current, errorMsg.get(), PR_FALSE);
           mSendReport->SetError(nsIMsgSendReport::process_Current, NS_MSG_GENERATE_FAILURE(NS_MSG_ERROR_ATTACHING_FILE) /* status */,
                                 PR_FALSE);
@@ -3311,18 +3222,18 @@ nsMsgComposeAndSend::Init(
               nsIFile      *sendFile,
               PRBool digest_p,
               PRBool dont_deliver_p,
               nsMsgDeliverMode mode,
               nsIMsgDBHdr *msgToReplace,
               const char *attachment1_type,
               const char *attachment1_body,
               PRUint32 attachment1_body_length,
-              const nsMsgAttachmentData *attachments,
-              const nsMsgAttachedFile *preloaded_attachments,
+              nsIArray *attachments,
+              nsIArray *preloaded_attachments,
               const char *password,
               const nsACString &aOriginalMsgURI,
               MSG_ComposeType aType)
 {
   nsresult      rv = NS_OK;
 
   //Reset last error
   mLastErrorReported = NS_OK;
@@ -4240,20 +4151,19 @@ nsMsgComposeAndSend::CreateAndSendMessag
               const char                        *aAccountKey,
               nsIMsgCompFields                  *fields,
               PRBool                            digest_p,
               PRBool                            dont_deliver_p,
               nsMsgDeliverMode                  mode,
               nsIMsgDBHdr                       *msgToReplace,
               const char                        *attachment1_type,
               const char                        *attachment1_body,
-              PRUint32                          attachment1_body_length,
-              const nsMsgAttachmentData         *attachments,
-              const nsMsgAttachedFile           *preloaded_attachments,
-              void                              *relatedPart,
+              PRUint32 attachment1_body_length,
+              nsIArray *attachments,
+              nsIArray *preloaded_attachments,
               nsIDOMWindow                      *parentWindow,
               nsIMsgProgress                    *progress,
               nsIMsgSendListener                *aListener,
               const char                        *password,
               const nsACString                  &aOriginalMsgURI,
               MSG_ComposeType                   aType
               )
 {
@@ -4347,42 +4257,41 @@ nsMsgComposeAndSend::SendMessageFile(
 
   return rv;
 }
 
 nsMsgAttachmentData *
 BuildURLAttachmentData(nsIURI *url)
 {
   int                 attachCount = 2;  // one entry and one empty entry
-  nsMsgAttachmentData *attachments = nsnull;
+  nsMsgAttachmentData *attachments;
   const char          *theName = nsnull;
 
   if (!url)
     return nsnull;
 
-  attachments = (nsMsgAttachmentData *) PR_Malloc(sizeof(nsMsgAttachmentData) * attachCount);
+  attachments = new nsMsgAttachmentData[attachCount];
   if (!attachments)
     return nsnull;
 
   // Now get a readable name...
   nsCAutoString spec;
   url->GetSpec(spec);
   if (!spec.IsEmpty())
   {
     theName = strrchr(spec.get(), '/');
   }
 
   if (!theName)
     theName = "Unknown"; // Don't I18N this string...should never happen...
   else
     theName++;
 
-  memset(attachments, 0, sizeof(nsMsgAttachmentData) * attachCount);
-  attachments[0].url = url; // The URL to attach. This should be 0 to signify "end of list".
-  attachments[0].real_name = (char *)PL_strdup(theName);  // The original name of this document, which will eventually show up in the
+  attachments[0].m_url = url; // The URL to attach.
+  attachments[0].m_realName = theName;  // The original name of this document, which will eventually show up in the
 
   NS_IF_ADDREF(url);
   return attachments;
 }
 
 //
 // Send the message to the magic folder, and runs the completion/failure
 // callback.
@@ -5076,8 +4985,302 @@ NS_IMETHODIMP nsMsgComposeAndSend::GetCr
 }
 
 NS_IMETHODIMP nsMsgComposeAndSend::SetCryptoclosure(nsIMsgComposeSecure * aCryptoclosure)
 {
   m_crypto_closure = aCryptoclosure;
   return NS_OK;
 }
 
+NS_IMPL_ISUPPORTS1(nsMsgAttachmentData, nsIMsgAttachmentData)
+
+nsMsgAttachmentData::nsMsgAttachmentData() :  m_size(0), m_isExternalAttachment(0),
+  m_isDownloaded(PR_FALSE), m_hasFilename(PR_FALSE)
+{
+}
+
+nsMsgAttachmentData::~nsMsgAttachmentData()
+{
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetUrl(nsIURI **aUrl)
+{
+  NS_ENSURE_ARG_POINTER(aUrl);
+  NS_IF_ADDREF(*aUrl = m_url);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetUrl(nsIURI *aUrl)
+{
+  m_url = aUrl;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetDesiredType(nsACString &aDesiredType)
+{
+  aDesiredType = m_desiredType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetDesiredType(const nsACString &aDesiredType)
+{
+  m_desiredType = aDesiredType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetRealType(nsACString &aRealType)
+{
+  aRealType = m_realType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetRealType(const nsACString &aRealType)
+{
+  m_realType = aRealType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetRealEncoding(nsACString &aRealEncoding)
+{
+  aRealEncoding = m_realEncoding;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetRealEncoding(const nsACString &aRealEncoding)
+{
+  m_realEncoding = aRealEncoding;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetRealName(nsACString &aRealName)
+{
+  aRealName = m_realName;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetRealName(const nsACString &aRealName)
+{
+  m_realName = aRealName;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetDescription(nsACString &aDescription)
+{
+  aDescription = m_description;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetDescription(const nsACString &aDescription)
+{
+  m_description = aDescription;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetXMacType(nsACString & aXMacType)
+{
+  aXMacType = m_xMacType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetXMacType(const nsACString & aXMacType)
+{
+  m_xMacType = aXMacType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::GetXMacCreator(nsACString & aXMacCreator)
+{
+  aXMacCreator = m_xMacCreator;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachmentData::SetXMacCreator(const nsACString & aXMacCreator)
+{
+  m_xMacCreator = aXMacCreator;
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(nsMsgAttachedFile, nsIMsgAttachedFile)
+
+nsMsgAttachedFile::nsMsgAttachedFile() :  m_size(0), m_unprintableCount(0),
+  m_highbitCount(0), m_ctlCount(0), m_nullCount(0), m_maxLineLength(0)
+{
+}
+
+nsMsgAttachedFile::~nsMsgAttachedFile()
+{
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetOrigUrl(nsIURI **aOrigUrl)
+{
+  NS_ENSURE_ARG_POINTER(aOrigUrl);
+  NS_IF_ADDREF(*aOrigUrl = m_origUrl);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetOrigUrl(nsIURI *aOrigUrl)
+{
+  m_origUrl = aOrigUrl;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetTmpFile(nsILocalFile **aTmpFile)
+{
+  NS_ENSURE_ARG_POINTER(aTmpFile);
+  NS_IF_ADDREF(*aTmpFile = m_tmpFile);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetTmpFile(nsILocalFile *aTmpFile)
+{
+  m_tmpFile = aTmpFile;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetType(nsACString &aType)
+{
+  aType = m_type;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetType(const nsACString &aType)
+{
+  m_type = aType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetEncoding(nsACString &aEncoding)
+{
+  aEncoding = m_encoding;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetEncoding(const nsACString &aEncoding)
+{
+  m_encoding = aEncoding;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetDescription(nsACString &aDescription)
+{
+  aDescription = m_description;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetDescription(const nsACString &aDescription)
+{
+  m_description = aDescription;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetXMacType(nsACString & aXMacType)
+{
+  aXMacType = m_xMacType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetXMacType(const nsACString & aXMacType)
+{
+  m_xMacType = aXMacType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetXMacCreator(nsACString & aXMacCreator)
+{
+  aXMacCreator = m_xMacCreator;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetXMacCreator(const nsACString & aXMacCreator)
+{
+  m_xMacCreator = aXMacCreator;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetRealName(nsACString & aRealName)
+{
+  aRealName = m_realName;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetRealName(const nsACString & aRealName)
+{
+  m_realName = aRealName;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetSize(PRUint32 *aSize)
+{
+  NS_ENSURE_ARG_POINTER(aSize);
+  *aSize = m_size;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetSize(PRUint32 aSize)
+{
+  m_size = aSize;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetUnprintableCount(PRUint32 *aUnprintableCount)
+{
+  NS_ENSURE_ARG_POINTER(aUnprintableCount);
+  *aUnprintableCount = m_unprintableCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetUnprintableCount(PRUint32 aUnprintableCount)
+{
+  m_unprintableCount = aUnprintableCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetHighbitCount(PRUint32 *aHighbitCount)
+{
+  NS_ENSURE_ARG_POINTER(aHighbitCount);
+  *aHighbitCount = m_highbitCount;
+  return NS_OK;
+}
+NS_IMETHODIMP nsMsgAttachedFile::SetHighbitCount(PRUint32 aHighbitCount)
+{
+  m_highbitCount = aHighbitCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetCtlCount(PRUint32 *aCtlCount)
+{
+  NS_ENSURE_ARG_POINTER(aCtlCount);
+  *aCtlCount = m_ctlCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetCtlCount(PRUint32 aCtlCount)
+{
+  m_ctlCount = aCtlCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetNullCount(PRUint32 *aNullCount)
+{
+  NS_ENSURE_ARG_POINTER(aNullCount);
+  *aNullCount = m_nullCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetNullCount(PRUint32 aNullCount)
+{
+  m_nullCount = aNullCount;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::GetMaxLineLength(PRUint32 *aMaxLineLength)
+{
+  NS_ENSURE_ARG_POINTER(aMaxLineLength);
+  *aMaxLineLength = m_maxLineLength;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMsgAttachedFile::SetMaxLineLength(PRUint32 aMaxLineLength)
+{
+  m_maxLineLength = aMaxLineLength;
+  return NS_OK;
+}
+
--- a/mailnews/compose/src/nsMsgSend.h
+++ b/mailnews/compose/src/nsMsgSend.h
@@ -156,17 +156,16 @@
 #include "nsIMsgIdentity.h"
 #include "nsIMsgHdr.h"
 #include "nsIMsgIdentity.h"
 #include "nsWeakReference.h"
 #include "nsIDOMWindow.h"
 #include "nsIMsgComposeSecure.h"
 #include "nsAutoPtr.h"
 #include "nsISupportsArray.h"
-
 //
 // Some necessary defines...
 //
 #define TEN_K                 10240
 #define MIME_BUFFER_SIZE      4096 // must be greater than 1000
                                    // SMTP (RFC821) limit
 
 //
@@ -192,17 +191,17 @@ class nsMsgComposeAndSend : public nsIMs
 public:
   //
   // The exit method used when downloading attachments only.
   // This still may be useful because of the fact that it is an
   // internal callback only. This way, no thread boundry issues and
   // we can get away without all of the listener array code.
   //
   void (*m_attachments_done_callback) (nsresult  status,
-        const PRUnichar *error_msg, struct nsMsgAttachedFile *attachments);
+        const PRUnichar *error_msg, nsMsgAttachedFile *attachments);
 
   //
   // Define QueryInterface, AddRef and Release for this class
   //
   NS_DECL_ISUPPORTS
 
   nsMsgComposeAndSend();
   virtual     ~nsMsgComposeAndSend();
@@ -245,18 +244,18 @@ public:
                    nsIFile          *sendFile,
                    PRBool           digest_p,
                    PRBool           dont_deliver_p,
                    nsMsgDeliverMode mode,
                    nsIMsgDBHdr      *msgToReplace,
                    const char       *attachment1_type,
                    const char       *attachment1_body,
                    PRUint32         attachment1_body_length,
-                   const nsMsgAttachmentData   *attachments,
-                   const nsMsgAttachedFile     *preloaded_attachments,
+                   nsIArray   *attachments,
+                   nsIArray     *preloaded_attachments,
                    const char       *password,
                    const nsACString &aOriginalMsgURI,
                    MSG_ComposeType  aType);
 
   //
   // Setup the composition fields
   //
   nsresult    InitCompositionFields(nsMsgCompFields *fields,
@@ -265,18 +264,18 @@ public:
 
   int         SetMimeHeader(nsMsgCompFields::MsgHeaderID header, const char *value);
   NS_IMETHOD  GetBodyFromEditor();
 
 
   //
   // Attachment processing...
   //
-  nsresult    HackAttachments(const struct nsMsgAttachmentData *attachments,
-                              const struct nsMsgAttachedFile *preloaded_attachments);
+  nsresult    HackAttachments(nsIArray *attachments,
+                              nsIArray *preloaded_attachments);
   nsresult    CountCompFieldAttachments();
   nsresult    AddCompFieldLocalAttachments();
   nsresult    AddCompFieldRemoteAttachments(PRUint32  aStartLocation, PRInt32 *aMailboxCount, PRInt32 *aNewsCount);
 
   // Deal with multipart related data
   nsresult    ProcessMultipartRelated(PRInt32 *aMailboxCount, PRInt32 *aNewsCount);
   nsresult    GetEmbeddedObjectInfo(nsIDOMNode *node, nsMsgAttachmentData *attachment, PRBool *acceptObject);
   PRUint32    GetMultipartRelatedCount(PRBool forceToBeCalculated = PR_FALSE);
--- a/mailnews/import/eudora/src/nsEudoraCompose.cpp
+++ b/mailnews/import/eudora/src/nsEudoraCompose.cpp
@@ -66,16 +66,17 @@
 #include "nsEudoraEditor.h"
 
 #include "EudoraDebugLog.h"
 
 #include "nsMimeTypes.h"
 #include "nsMsgUtils.h"
 #include "nsNetUtil.h"
 #include "nsAutoPtr.h"
+#include "nsIMutableArray.h"
 
 static NS_DEFINE_CID( kMsgSendCID, NS_MSGSEND_CID);
 static NS_DEFINE_CID( kMsgCompFieldsCID, NS_MSGCOMPFIELDS_CID);
 
 // We need to do some calculations to set these numbers to something reasonable!
 // Unless of course, CreateAndSendMessage will NEVER EVER leave us in the lurch
 #define kHungCount 100000
 #define kHungAbortCount 1000
@@ -505,80 +506,64 @@ void nsEudoraCompose::ExtractType( nsStr
   // valid multipart!
   if (str.Length() > 10) {
     str.Left( tStr, 10);
     if (tStr.LowerCaseEqualsLiteral("multipart/"))
       str.Truncate();
   }
 }
 
-void nsEudoraCompose::CleanUpAttach( nsMsgAttachedFile *a, PRInt32 count)
-{
-  for (PRInt32 i = 0; i < count; i++) {
-    a[i].orig_url=nsnull;
-    if (a[i].type)
-      NS_Free( a[i].type);
-    if (a[i].description)
-      NS_Free( a[i].description);
-    if (a[i].encoding)
-      NS_Free( a[i].encoding);
-  }
-  delete [] a;
-}
-
-nsMsgAttachedFile * nsEudoraCompose::GetLocalAttachments( void)
+nsresult nsEudoraCompose::GetLocalAttachments(nsIArray **aArray)
 {
   /*
   nsIURI      *url = nsnull;
   */
-
+  nsresult rv;
+  nsCOMPtr<nsIMutableArray> attachments (do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_IF_ADDREF(*aArray = attachments);
   PRInt32 count = 0;
   if (m_pAttachments)
     count = m_pAttachments->Count();
   if (!count)
-    return( nsnull);
-
-  nsMsgAttachedFile *a = (nsMsgAttachedFile *) new nsMsgAttachedFile[count + 1];
-  if (!a)
-    return( nsnull);
-  memset(a, 0, sizeof(nsMsgAttachedFile) * (count + 1));
+    return NS_OK;
 
   nsCString urlStr;
   ImportAttachment * pAttach;
 
   for (PRInt32 i = 0; i < count; i++) {
+    nsCOMPtr<nsIMsgAttachedFile> a(do_CreateInstance(NS_MSGATTACHEDFILE_CONTRACTID, &rv));
+    NS_ENSURE_SUCCESS(rv, rv);
     // nsMsgNewURL(&url, "file://C:/boxster.jpg");
     // a[i].orig_url = url;
 
     // NS_PRECONDITION( PR_FALSE, "Forced Break");
 
     pAttach = (ImportAttachment *) m_pAttachments->ElementAt( i);
-                a[i].tmp_file = do_QueryInterface(pAttach->pAttachment);
+    nsCOMPtr<nsILocalFile> tmpFile = do_QueryInterface(pAttach->pAttachment);
+    a->SetTmpFile(tmpFile);
     urlStr.Adopt(0);
 
     nsCOMPtr <nsIURI> uri;
     nsresult rv = NS_NewFileURI(getter_AddRefs(uri), pAttach->pAttachment);
     NS_ENSURE_SUCCESS(rv, nsnull);
     uri->GetSpec(urlStr);
-    if (urlStr.IsEmpty()) {
-      CleanUpAttach( a, count);
-      return( nsnull);
-    }
-    rv = m_pIOService->NewURI( urlStr, nsnull, nsnull, getter_AddRefs(a[i].orig_url));
-    if (NS_FAILED( rv)) {
-      CleanUpAttach( a, count);
-      return( nsnull);
-    }
+    if (urlStr.IsEmpty())
+      return NS_ERROR_FAILURE;
 
-    a[i].type = strdup( pAttach->mimeType);
-    a[i].real_name = strdup( pAttach->description);
-    a[i].encoding = strdup( ENCODING_BINARY);
+    nsCOMPtr<nsIURI> origUrl;
+    rv = m_pIOService->NewURI( urlStr, nsnull, nsnull, getter_AddRefs(origUrl));
+    NS_ENSURE_SUCCESS(rv, rv);
+    a->SetOrigUrl(origUrl);
+    a->SetType(nsDependentCString(pAttach->mimeType));
+    a->SetRealName(nsDependentCString(pAttach->description));
+    a->SetEncoding(NS_LITERAL_CSTRING(ENCODING_BINARY));
+    attachments->AppendElement(a, PR_FALSE);
   }
-
-  return( a);
+  return NS_OK;
 }
 
 // Test a message send????
 nsresult nsEudoraCompose::SendTheMessage(nsIFile *pMailImportLocation, nsIFile **pMsg)
 {
   nsresult rv = CreateComponents();
   if (NS_SUCCEEDED( rv))
     rv = CreateIdentity();
@@ -639,18 +624,18 @@ nsresult nsEudoraCompose::SendTheMessage
   // what about all of the other headers?!?!?!?!?!?!
   char *pMimeType;
   if (!bodyType.IsEmpty())
     pMimeType = ToNewCString(bodyType);
   else
     pMimeType = ToNewCString(m_bodyType);
 
   // IMPORT_LOG0( "Outlook compose calling CreateAndSendMessage\n");
-  nsMsgAttachedFile *pAttach = GetLocalAttachments();
-
+  nsCOMPtr<nsIArray> pAttach;
+  GetLocalAttachments(getter_AddRefs(pAttach));
 
   /*
     l10n - I have the body of the message in the system charset,
     I need to "encode" it to be the charset for the message
     *UNLESS* of course, I don't know what the charset of the message
     should be?  How do I determine what the charset should
     be if it doesn't exist?
 
@@ -706,19 +691,16 @@ nsresult nsEudoraCompose::SendTheMessage
                         pMimeType,                    // body type
                         body.get(),                   // body pointer
                         body.Length(),                // body length
                         pAttach,                      // local attachments
                         m_pListener);              // originalMsgURI
 
   // IMPORT_LOG0( "Returned from ProxySend\n");
 
-  if (pAttach)
-    delete [] pAttach;
-
   EudoraSendListener *pListen = (EudoraSendListener *)m_pListener;
   if (NS_FAILED( rv)) {
     IMPORT_LOG1( "*** Error, CreateAndSendMessage FAILED: 0x%lx\n", rv);
     // IMPORT_LOG1( "Headers: %80s\n", m_pHeaders);
   }
   else {
     // wait for the listener to get done!
     PRInt32 abortCnt = 0;
--- a/mailnews/import/eudora/src/nsEudoraCompose.h
+++ b/mailnews/import/eudora/src/nsEudoraCompose.h
@@ -155,18 +155,17 @@ private:
     val.Truncate();
     nsCString  hVal;
     GetHeaderValue( pData, dataLen, pHeader, hVal, PR_TRUE);
     NS_CopyNativeToUnicode( hVal, val);
   }
   void    ExtractCharset( nsString& str);
   void    ExtractType( nsString& str);
 
-  nsMsgAttachedFile * GetLocalAttachments( void);
-  void        CleanUpAttach( nsMsgAttachedFile *a, PRInt32 count);
+  nsresult GetLocalAttachments(nsIArray **aArray);
 
   nsresult  ReadHeaders( ReadFileState *pState, SimpleBufferTonyRCopiedOnce& copy, SimpleBufferTonyRCopiedOnce& header);
   PRInt32    FindNextEndLine( SimpleBufferTonyRCopiedOnce& data);
   PRInt32    IsEndHeaders( SimpleBufferTonyRCopiedOnce& data);
   PRInt32    IsSpecialHeader( const char *pHeader);
   nsresult  WriteHeaders( nsIOutputStream *pDst, SimpleBufferTonyRCopiedOnce& newHeaders);
   PRBool    IsReplaceHeader( const char *pHeader);
 
--- a/mailnews/import/eudora/src/nsEudoraImport.cpp
+++ b/mailnews/import/eudora/src/nsEudoraImport.cpp
@@ -523,19 +523,16 @@ NS_IMETHODIMP ImportEudoraMailImpl::Impo
             PRUnichar **pErrorLog,
             PRUnichar **pSuccessLog,
             PRBool *fatalError)
 {
   NS_PRECONDITION(pSource != nsnull, "null ptr");
   NS_PRECONDITION(pDestination != nsnull, "null ptr");
   NS_PRECONDITION(fatalError != nsnull, "null ptr");
 
-
-  nsCOMPtr<nsIStringBundle> bundle( dont_AddRef( nsEudoraStringBundle::GetStringBundle()));
-
   nsString  success;
   nsString  error;
   if (!pSource || !pDestination || !fatalError)
   {
     IMPORT_LOG0( "*** Bad param passed to eudora mailbox import\n");
     nsEudoraStringBundle::GetStringByID( EUDORAIMPORT_MAILBOX_BADPARAM, error);
     if (fatalError)
       *fatalError = PR_TRUE;
--- a/mailnews/import/outlook/src/MapiMessage.cpp
+++ b/mailnews/import/outlook/src/MapiMessage.cpp
@@ -45,16 +45,18 @@
 
 #include "nscore.h"
 #include <time.h>
 #include "nsString.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsMsgUtils.h"
 #include "nsMimeTypes.h"
 
+#include "nsMsgCompCID.h"
+#include "nsIMutableArray.h"
 #include "MapiDbgLog.h"
 #include "MapiApi.h"
 
 #include "MapiMimeTypes.h"
 
 #include <algorithm>
 #include "nsMsgI18N.h"
 #include "nsICharsetConverterManager.h"
@@ -1202,34 +1204,35 @@ void CMapiMessage::ProcessAttachments()
   LPMAPITABLE pTable = NULL;
   HRESULT hr = m_lpMsg->GetAttachmentTable( 0, &pTable);
   if (FAILED( hr) || !pTable)
     return;
   IterateAttachTable(pTable);
   pTable->Release();
 }
 
-nsMsgAttachedFile* CMapiMessage::GetAttachments()
+nsresult CMapiMessage::GetAttachments(nsIArray **aArray)
 {
-  nsMsgAttachedFile* result = new nsMsgAttachedFile[m_stdattachments.size()+1];
-  if (!result)
-    return 0;
-  memset(result, 0, sizeof(nsMsgAttachedFile)*m_stdattachments.size()+1);
+  nsresult rv;
+  nsCOMPtr<nsIMutableArray> attachments (do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_IF_ADDREF(*aArray = attachments);
 
-  nsMsgAttachedFile* pos=result;
   for (std::vector<attach_data*>::const_iterator it = m_stdattachments.begin();
-       it != m_stdattachments.end(); pos++, it++) {
-    pos->orig_url = (*it)->orig_url;
-    pos->tmp_file = (*it)->tmp_file;
-    pos->encoding = (*it)->encoding;
-    pos->real_name = (*it)->real_name;
-    pos->type = (*it)->type;
+       it != m_stdattachments.end(); it++) {
+    nsCOMPtr<nsIMsgAttachedFile> a(do_CreateInstance(NS_MSGATTACHEDFILE_CONTRACTID, &rv));
+    NS_ENSURE_SUCCESS(rv, rv);
+    a->SetOrigUrl((*it)->orig_url);
+    a->SetTmpFile((*it)->tmp_file);
+    a->SetEncoding(nsDependentCString((*it)->encoding));
+    a->SetRealName(nsDependentCString((*it)->real_name));
+    a->SetType(nsDependentCString((*it)->type));
+    attachments->AppendElement(a, PR_FALSE);
   }
-
-  return result;
+  return rv;
 }
 
 bool CMapiMessage::GetEmbeddedAttachmentInfo(unsigned int i, nsIURI **uri,
                                              const char **cid,
                                              const char **name) const
 {
   if ((i < 0) || ( i >= m_embattachments.size()))
     return false;
--- a/mailnews/import/outlook/src/MapiMessage.h
+++ b/mailnews/import/outlook/src/MapiMessage.h
@@ -179,19 +179,18 @@ private:
 //////////////////////////////////////////////////////
 
 class CMapiMessage {
 public:
   CMapiMessage( LPMESSAGE  lpMsg);
   ~CMapiMessage();
 
   // Attachments
-  // Ordinary (not embedded) attachments; result MUST be disposed of with DisposeAttachments()
-  nsMsgAttachedFile* GetAttachments();
-  static void DisposeAttachments(nsMsgAttachedFile* att) { delete[] att; }
+  // Ordinary (not embedded) attachments.
+  nsresult GetAttachments(nsIArray **aArray);
   // Embedded attachments
   size_t EmbeddedAttachmentsCount() const { return m_embattachments.size(); }
   bool GetEmbeddedAttachmentInfo(unsigned int i, nsIURI **uri, const char **cid,
                                  const char **name) const;
   // We don't check MSGFLAG_HASATTACH, since it returns true even if there are
   // only embedded attachmentsin the message. TB only counts the ordinary
   // attachments when shows the message status, so here we check only for the
   // ordinary attachments.
--- a/mailnews/import/outlook/src/nsOutlookCompose.cpp
+++ b/mailnews/import/outlook/src/nsOutlookCompose.cpp
@@ -50,17 +50,17 @@
 #include "nsIProxyObjectManager.h"
 #include "nsProxiedService.h"
 #include "nsMsgI18N.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIOutputStream.h"
 
 #include "nsMsgBaseCID.h"
 #include "nsMsgCompCID.h"
-
+#include "nsIArray.h"
 #include "nsIMsgCompose.h"
 #include "nsIMsgCompFields.h"
 #include "nsIMsgAccountManager.h"
 
 #include "nsNetCID.h"
 
 #include "nsOutlookCompose.h"
 
@@ -321,17 +321,18 @@ nsresult nsOutlookCompose::ComposeTheMes
   LossyCopyUTF16toASCII(headers->Value(CMapiMessageHeaders::hdrMessageID),
                         asciiHeaderVal); // Message-Id cannot fold
   m_pMsgFields->SetMessageId(asciiHeaderVal.get());
   // We only use those headers that may need to be processed by Thunderbird
   // to create a good rfc822 document, or need to be encoded (like To and Cc).
   // These will replace the originals on import. All the other headers
   // will be copied to the destination unaltered in CopyComposedMessage().
 
-  nsMsgAttachedFile *pAttach = msg.GetAttachments();
+  nsCOMPtr<nsIArray> pAttach;
+  msg.GetAttachments(getter_AddRefs(pAttach));
 
   nsString bodyW;
   // Bug 593907
   if (GenerateHackSequence(msg.GetBody(), msg.GetBodyLen()))
     HackBody(msg.GetBody(), msg.GetBodyLen(), bodyW);
   // End Bug 593907
 
   // We only get the editor interface when there's embedded content.
@@ -400,19 +401,16 @@ nsresult nsOutlookCompose::ComposeTheMes
     if (abortCnt >= kHungAbortCount) {
       IMPORT_LOG0( "**** Create and send message hung\n");
 //      IMPORT_LOG1( "Headers: %s\n", m_Headers.get());
 //      IMPORT_LOG1( "Body: %s\n", m_Body.get());
       rv = NS_ERROR_FAILURE;
     }
   }
 
-  if (pAttach)
-    msg.DisposeAttachments(pAttach);
-
   if (pListen->m_location) {
     pListen->m_location->Clone(pMsg);
     rv = NS_OK;
   }
   else {
     rv = NS_ERROR_FAILURE;
     IMPORT_LOG0( "*** Error, Outlook compose unsuccessful\n");
   }
--- a/mailnews/import/public/nsIImportService.idl
+++ b/mailnews/import/public/nsIImportService.idl
@@ -47,18 +47,19 @@
 interface nsIImportModule;
 interface nsIImportMailboxDescriptor;
 interface nsIImportABDescriptor;
 interface nsIImportGeneric;
 interface nsIImportFieldMap;
 interface nsIMsgSendListener;
 interface nsIMsgCompFields;
 interface nsIMsgSendListener;
+interface nsIArray;
 
-[scriptable, uuid(55a52e05-8ce7-4e23-8a2f-a9226b01bcfb)]
+[scriptable, uuid(8de585fc-8557-402e-b784-875b82e79b1a)]
 interface nsIImportService : nsISupports
 {
     void DiscoverModules();
 
   long GetModuleCount( in string filter);
   void GetModuleInfo( in string filter, in long index, out wstring name, out wstring description);
   wstring GetModuleName( in string filter, in long index);
   wstring GetModuleDescription( in string filter, in long index);
@@ -71,17 +72,17 @@ interface nsIImportService : nsISupports
   nsIImportGeneric      CreateNewGenericMail();
   nsIImportGeneric      CreateNewGenericAddressBooks();
   [noscript] void ProxySend(in nsIEditor aEditor, in nsIMsgIdentity aIdentity,
                             in nsIMsgCompFields aMsgFields,
                             in nsMsgDeliverMode aDeliverMode,
                             in string attachment1_type,
                             in string attachment1_body,
                             in PRUint32 attachment1_body_length,
-                            [const] in nsMsgAttachedFile loaded_attachments,
+                            in nsIArray loaded_attachments,
                             in nsIMsgSendListener aListener);
 
 };
 
 %{ C++
 #define NS_IMPORTSERVICE_CID              \
 { /* 5df96d60-1726-11d3-a206-00a0cc26da63 */      \
    0x5df96d60, 0x1726, 0x11d3,                   \
--- a/mailnews/import/src/nsImportService.cpp
+++ b/mailnews/import/src/nsImportService.cpp
@@ -66,16 +66,17 @@
 #include "nsThreadUtils.h"
 #include "nsIEditor.h"
 #include "ImportDebug.h"
 #include "nsImportService.h"
 #include "nsImportStringBundle.h"
 #include "nsCRTGlue.h"
 #include "nsServiceManagerUtils.h"
 #include "nsComponentManagerUtils.h"
+#include "nsIMutableArray.h"
 
 PRLogModuleInfo *IMPORTLOGMODULE = nsnull;
 
 static nsIImportService *  gImportService = nsnull;
 static const char *  kWhitespace = "\b\t\r\n ";
 
 
 ////////////////////////////////////////////////////////////////////////
@@ -320,39 +321,39 @@ class nsProxySendRunnable : public nsRun
 {
 public:
   nsProxySendRunnable(nsIEditor *aEditor, nsIMsgIdentity *aIdentity,
                        nsIMsgCompFields *aMsgFields,
                        nsMsgDeliverMode aDeliverMode,
                        const char *attachment1_type,
                        const char *attachment1_body,
                        PRUint32 attachment1_body_length,
-                       const nsMsgAttachedFile *loaded_attachments,
+                       nsIArray *loaded_attachments,
                        nsIMsgSendListener *aListener);
   NS_DECL_NSIRUNNABLE
 private:
   nsCOMPtr<nsIEditor> m_editor;
   nsCOMPtr<nsIMsgIdentity> m_identity;
   nsCOMPtr<nsIMsgCompFields> m_compFields;
   nsMsgDeliverMode m_deliverMode;
   nsCString m_bodyType;
   nsCString m_body;
   PRUint32 m_bodyLength;
-  const nsMsgAttachedFile *m_loadedAttachments;
+  nsCOMPtr<nsIArray> m_loadedAttachments;
   nsCOMPtr<nsIMsgSendListener> m_listener;
 
 };
 
 nsProxySendRunnable::nsProxySendRunnable(nsIEditor *aEditor, nsIMsgIdentity *aIdentity,
                                          nsIMsgCompFields *aMsgFields,
                                          nsMsgDeliverMode aDeliverMode,
                                          const char *aBodyType,
                                          const char *aBody,
                                          PRUint32 aBodyLength,
-                                         const nsMsgAttachedFile *aLoadedAttachments,
+                                         nsIArray *aLoadedAttachments,
                                          nsIMsgSendListener *aListener) :
   m_editor(aEditor), m_identity(aIdentity), m_compFields(aMsgFields),
   m_deliverMode(aDeliverMode), m_bodyType(aBodyType),
   m_body(aBody), m_bodyLength(aBodyLength), m_loadedAttachments(aLoadedAttachments),
   m_listener(aListener)
 {
 }
 
@@ -361,28 +362,28 @@ NS_IMETHODIMP nsProxySendRunnable::Run()
   nsresult rv;
   nsCOMPtr<nsIMsgSend> msgSend = do_CreateInstance(NS_MSGSEND_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return msgSend->CreateAndSendMessage(m_editor, m_identity, nsnull, m_compFields,
                                        PR_FALSE, PR_TRUE, 
                                        m_deliverMode, nsnull, m_bodyType.get(), m_body.get(),
                                        m_bodyLength, nsnull, m_loadedAttachments,
-                                       nsnull, nsnull, nsnull, m_listener, nsnull,
+                                       nsnull, nsnull, m_listener, nsnull,
                                        EmptyCString(), nsnull);
 }
 
 
 NS_IMETHODIMP nsImportService::ProxySend(nsIEditor *aEditor, nsIMsgIdentity *aIdentity,
                                          nsIMsgCompFields *aMsgFields,
                                          nsMsgDeliverMode aDeliverMode,
                                          const char *attachment1_type,
                                          const char *attachment1_body,
                                          PRUint32 attachment1_body_length,
-                                         const nsMsgAttachedFile *loaded_attachments,
+                                         nsIArray *loaded_attachments,
                                          nsIMsgSendListener *aListener)
 {
     nsRefPtr<nsProxySendRunnable> runnable =
       new nsProxySendRunnable(aEditor, aIdentity,
                                        aMsgFields,
                                        aDeliverMode,
                                        attachment1_type,
                                        attachment1_body,
--- a/mailnews/mime/src/mimedrft.cpp
+++ b/mailnews/mime/src/mimedrft.cpp
@@ -97,16 +97,24 @@ extern "C" char     *MIME_StripContinuat
 nsresult            mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers );
 nsresult            mime_decompose_file_output_fn ( const char *buf, PRInt32 size, void *stream_closure );
 nsresult            mime_decompose_file_close_fn ( void *stream_closure );
 extern int          MimeHeaders_build_heads_list(MimeHeaders *hdrs);
 
 // CID's
 static NS_DEFINE_CID(kCMsgComposeServiceCID,  NS_MSGCOMPOSESERVICE_CID);
 
+mime_draft_data::mime_draft_data() : url_name(nsnull), format_out(0),
+  stream(nsnull), obj(nsnull), options(nsnull), headers(nsnull),
+  messageBody(nsnull), curAttachment(nsnull),
+  decoder_data(nsnull), mailcharset(nsnull), forwardInline(PR_FALSE),
+  forwardInlineFilter(PR_FALSE), overrideComposeFormat(PR_FALSE),
+  originalMsgURI(nsnull)
+{
+}
 ////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////
 // THIS SHOULD ALL MOVE TO ANOTHER FILE AFTER LANDING!
 ////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////////
 
 // safe filename for all OSes
 #define SAFE_TMP_FILENAME "nsmime.tmp"
@@ -151,36 +159,36 @@ typedef enum {
                                   // DON'T remove.
 } nsMsgBoolHeaderSet;
 
 #ifdef NS_DEBUG
 extern "C" void
 mime_dump_attachments ( nsMsgAttachmentData *attachData )
 {
   PRInt32     i = 0;
-  struct nsMsgAttachmentData  *tmp = attachData;
+  class nsMsgAttachmentData  *tmp = attachData;
 
-  while ( (tmp) && (tmp->real_name) )
+  while ( (tmp) && (tmp->m_url) )
   {
-    printf("Real Name         : %s\n", tmp->real_name);
+    printf("Real Name         : %s\n", tmp->m_realName.get());
 
-    if ( tmp->url )
+    if ( tmp->m_url )
     {
       nsCAutoString spec;
-      tmp->url->GetSpec(spec);
+      tmp->m_url->GetSpec(spec);
       printf("URL               : %s\n", spec.get());
     }
 
-    printf("Desired Type      : %s\n", tmp->desired_type ? tmp->desired_type : "nsnull");
-    printf("Real Type         : %s\n", tmp->real_type ? tmp->real_type : "nsnull");
-    printf("Real Encoding     : %s\n", tmp->real_encoding ? tmp->real_encoding : "nsnull");
-    printf("Description       : %s\n", tmp->description ? tmp->description : "nsnull");
-    printf("Mac Type          : %s\n", tmp->x_mac_type ? tmp->x_mac_type : "nsnull");
-    printf("Mac Creator       : %s\n", tmp->x_mac_creator ? tmp->x_mac_creator : "nsnull");
-    printf("Size in bytes     : %d\n", tmp->size);
+    printf("Desired Type      : %s\n", tmp->m_desiredType.get());
+    printf("Real Type         : %s\n", tmp->m_realType.get());
+    printf("Real Encoding     : %s\n", tmp->m_realEncoding.get());
+    printf("Description       : %s\n", tmp->m_description.get());
+    printf("Mac Type          : %s\n", tmp->m_xMacType);
+    printf("Mac Creator       : %s\n", tmp->m_xMacCreator);
+    printf("Size in bytes     : %d\n", tmp->m_size);
     i++;
     tmp++;
   }
 }
 #endif
 
 nsresult CreateComposeParams(nsCOMPtr<nsIMsgComposeParams> &pMsgComposeParams,
                              nsIMsgCompFields * compFields,
@@ -196,35 +204,35 @@ nsresult CreateComposeParams(nsCOMPtr<ns
 #endif
 
   nsresult rv;
   nsMsgAttachmentData *curAttachment = attachmentList;
   if (curAttachment)
   {
     nsCAutoString spec;
 
-    while (curAttachment && curAttachment->real_name) //JFD: Why do we check for real_name?
+    while (curAttachment && curAttachment->m_url)
     {
-      rv = curAttachment->url->GetSpec(spec);
+      rv = curAttachment->m_url->GetSpec(spec);
       if (NS_SUCCEEDED(rv))
       {
         nsCOMPtr<nsIMsgAttachment> attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv);
         if (NS_SUCCEEDED(rv) && attachment)
         {
           nsAutoString nameStr;
-          rv = ConvertToUnicode("UTF-8", curAttachment->real_name, nameStr);
+          rv = ConvertToUnicode("UTF-8", curAttachment->m_realName.get(), nameStr);
           if (NS_FAILED(rv))
-            CopyASCIItoUTF16(nsDependentCString(curAttachment->real_name), nameStr);
+            CopyASCIItoUTF16(curAttachment->m_realName, nameStr);
           attachment->SetName(nameStr);
           attachment->SetUrl(spec);
           attachment->SetTemporary(PR_TRUE);
-          attachment->SetContentType(curAttachment->real_type);
-          attachment->SetMacType(curAttachment->x_mac_type);
-          attachment->SetMacCreator(curAttachment->x_mac_creator);
-          attachment->SetSize(curAttachment->size);
+          attachment->SetContentType(curAttachment->m_realType.get());
+          attachment->SetMacType(curAttachment->m_xMacType.get());
+          attachment->SetMacCreator(curAttachment->m_xMacCreator.get());
+          attachment->SetSize(curAttachment->m_size);
           compFields->AddAttachment(attachment);
         }
       }
       curAttachment++;
     }
   }
 
   MSG_ComposeFormat format = composeFormat; // Format to actually use.
@@ -456,184 +464,118 @@ dummy_file_write( char *buf, PRInt32 siz
   PRUint32 bytesWritten;
   tStream->Write(buf, size, &bytesWritten);
   return (int) bytesWritten;
 }
 
 static int
 mime_parse_stream_write ( nsMIMESession *stream, const char *buf, PRInt32 size )
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
+  mime_draft_data *mdd = (mime_draft_data *) stream->data_object;
   NS_ASSERTION ( mdd, "null mime draft data!" );
 
   if ( !mdd || !mdd->obj )
     return -1;
 
   return mdd->obj->clazz->parse_buffer ((char *) buf, size, mdd->obj);
 }
 
 static void
-mime_free_attach_data ( nsMsgAttachmentData *attachData)
+mime_free_attachments(nsTArray<nsMsgAttachedFile *> &attachments)
 {
-  struct nsMsgAttachmentData  *tmp = attachData;
-
-  while (tmp && tmp->real_name)
-  {
-    NS_IF_RELEASE(tmp->url);
-    PR_FREEIF(tmp->real_name);
-
-    PR_FREEIF(tmp->desired_type);
-    PR_FREEIF(tmp->real_type);
-    PR_FREEIF(tmp->real_encoding);
-    PR_FREEIF(tmp->description);
-    PR_FREEIF(tmp->x_mac_type);
-    PR_FREEIF(tmp->x_mac_creator);
-
-    tmp++;
-  }
-}
-
-static void
-mime_free_attachments ( nsMsgAttachedFile *attachments, int count )
-{
-  int               i;
-  nsMsgAttachedFile *cur = attachments;
-
-  NS_ASSERTION ( attachments && count > 0, "freeing attachments but there aren't any");
-  if ( !attachments || count <= 0 )
+  if (attachments.Length() <= 0)
     return;
 
-  for ( i = 0; i < count; i++, cur++ )
+  for (int i = 0; i < attachments.Length(); i++)
   {
-    cur->orig_url=nsnull;
-
-    PR_FREEIF ( cur->type );
-    PR_FREEIF ( cur->encoding );
-    PR_FREEIF ( cur->description );
-    PR_FREEIF ( cur->x_mac_type );
-    PR_FREEIF ( cur->x_mac_creator );
-    if ( cur->tmp_file )
+    if (attachments[i]->m_tmpFile)
     {
-      cur->tmp_file->Remove(PR_FALSE);
-      cur->tmp_file = nsnull;
+      attachments[i]->m_tmpFile->Remove(PR_FALSE);
+      attachments[i]->m_tmpFile = nsnull;
     }
+    delete attachments[i];
   }
-
-  PR_FREEIF( attachments );
 }
 
 static nsMsgAttachmentData *
 mime_draft_process_attachments(mime_draft_data *mdd)
 {
   if (!mdd)
     return nsnull;
 
   nsMsgAttachmentData         *attachData = NULL, *tmp = NULL;
   nsMsgAttachedFile           *tmpFile = NULL;
-  int                         i;
 
   //It's possible we must treat the message body as attachment!
   PRBool bodyAsAttachment = PR_FALSE;
   if (  mdd->messageBody &&
-        mdd->messageBody->type && *mdd->messageBody->type &&
-        ( PL_strcasestr(mdd->messageBody->type, "text/html") == nsnull ) &&
-        ( PL_strcasestr(mdd->messageBody->type, "text/plain") == nsnull ) &&
-        ( PL_strcasecmp(mdd->messageBody->type, "text") != 0 )
-     )
+        mdd->messageBody->m_type.Find("text/html", CaseInsensitiveCompare) == -1 &&
+        mdd->messageBody->m_type.Find("text/plain", CaseInsensitiveCompare) == -1 &&
+        mdd->messageBody->m_type.Find("text", CaseInsensitiveCompare) == -1)
      bodyAsAttachment = PR_TRUE;
 
-  if ( (!mdd->attachments || !mdd->attachments_count) && !bodyAsAttachment)
+  if (!mdd->attachments.Length() && !bodyAsAttachment)
     return nsnull;
 
-  PRInt32 totalCount = mdd->attachments_count;
+  PRInt32 totalCount = mdd->attachments.Length();
   if (bodyAsAttachment)
-    totalCount ++;
-  attachData = (nsMsgAttachmentData *) PR_CALLOC( ( (totalCount + 1) * sizeof (nsMsgAttachmentData) ) );
+    totalCount++;
+  attachData = new nsMsgAttachmentData[totalCount + 1];
   if ( !attachData )
     return nsnull;
 
-  //mdd->messageBody and mdd->attachments are the same type!
-  if (bodyAsAttachment)
-    tmpFile = mdd->messageBody;
-  else
-    tmpFile = mdd->attachments;
   tmp = attachData;
 
-  for ( i=0; i < totalCount; i++, tmp++)
+  for (int i = 0, attachmentsIndex = 0; i < totalCount; i++, tmp++)
   {
-    if (tmpFile->type)
-    {
-      if (PL_strcasecmp ( tmpFile->type, "text/x-vcard") == 0)
-        NS_MsgSACopy (&(tmp->real_name), tmpFile->description);
-    }
+    if (bodyAsAttachment && i == 0)
+      tmpFile = mdd->messageBody;
+    else
+      tmpFile = mdd->attachments[attachmentsIndex++];
 
-    if ( tmpFile->orig_url )
+    if (tmpFile->m_type.LowerCaseEqualsLiteral("text/x-vcard"))
+      tmp->m_realName = tmpFile->m_description;
+
+    if ( tmpFile->m_origUrl )
     {
       nsCAutoString tmpSpec;
-      if (NS_FAILED(tmpFile->orig_url->GetSpec(tmpSpec)))
+      if (NS_FAILED(tmpFile->m_origUrl->GetSpec(tmpSpec)))
         goto FAIL;
 
-      if (NS_FAILED(nsMimeNewURI(&(tmp->url), tmpSpec.get(), nsnull)))
+      if (NS_FAILED(nsMimeNewURI(getter_AddRefs(tmp->m_url), tmpSpec.get(), nsnull)))
         goto FAIL;
 
-      if (!tmp->real_name)
+      if (tmp->m_realName.IsEmpty())
       {
-        if (tmpFile->real_name)
-          NS_MsgSACopy ( &(tmp->real_name), tmpFile->real_name );
+        if (!tmpFile->m_realName.IsEmpty())
+          tmp->m_realName = tmpFile->m_realName;
         else {
-          if (PL_strstr(tmpFile->type, MESSAGE_RFC822))
+          if (tmpFile->m_type.Find(MESSAGE_RFC822, CaseInsensitiveCompare) != -1)
             // we have the odd case of processing an e-mail that had an unnamed
             // eml message attached
-            NS_MsgSACopy( &(tmp->real_name), "ForwardedMessage.eml" );
+            tmp->m_realName = "ForwardedMessage.eml";
 
           else
-            NS_MsgSACopy ( &(tmp->real_name), tmpSpec.get() );
+            tmp->m_realName = tmpSpec.get();
         }
       }
     }
 
-    if ( tmpFile->type )
-    {
-      NS_MsgSACopy ( &(tmp->desired_type), tmpFile->type );
-      NS_MsgSACopy ( &(tmp->real_type), tmpFile->type );
-    }
-
-    if ( tmpFile->encoding )
-    {
-      NS_MsgSACopy ( &(tmp->real_encoding), tmpFile->encoding );
-    }
-
-    if ( tmpFile->description )
-    {
-      NS_MsgSACopy ( &(tmp->description), tmpFile->description );
-    }
-
-    if ( tmpFile->x_mac_type )
-    {
-      NS_MsgSACopy ( &(tmp->x_mac_type), tmpFile->x_mac_type );
-    }
-
-    if ( tmpFile->x_mac_creator )
-    {
-      NS_MsgSACopy ( &(tmp->x_mac_creator), tmpFile->x_mac_creator );
-    }
-
-    tmp->size = tmpFile->size;
-
-    if (bodyAsAttachment && (i == 0))
-      tmpFile = mdd->attachments;
-    else
-      tmpFile++;
+    tmp->m_desiredType = tmpFile->m_type;
+    tmp->m_realType = tmpFile->m_type;
+    tmp->m_realEncoding = tmpFile->m_encoding;
+    tmp->m_description = tmpFile->m_description;
+    tmp->m_xMacType = tmpFile->m_xMacType;
+    tmp->m_xMacCreator = tmpFile->m_xMacCreator;
+    tmp->m_size = tmpFile->m_size;
   }
-
-  return (attachData);
+  return attachData;
 
 FAIL:
-  mime_free_attach_data (attachData);
-  PR_FREEIF(attachData);
+  delete [] attachData;
   return nsnull;
 }
 
 static void
 mime_fix_up_html_address( char **addr)
 {
   //
   // We need to replace paired <> they are treated as HTML tag
@@ -1218,17 +1160,17 @@ mime_insert_forwarded_message_headers(ch
     mime_insert_all_headers(body, headers, composeFormat, mailcharset);
     break;
   }
 }
 
 static void
 mime_parse_stream_complete (nsMIMESession *stream)
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
+  mime_draft_data *mdd = (mime_draft_data *) stream->data_object;
   nsCOMPtr<nsIMsgCompFields> fields;
   int htmlAction = 0;
   int lineWidth = 0;
 
   char *host = 0;
   char *news_host = 0;
   char *to_and_cc = 0;
   char *re_subject = 0;
@@ -1425,65 +1367,63 @@ mime_parse_stream_complete (nsMIMESessio
             if ( NS_SUCCEEDED(rv) && overrulingIdentity )
                 mdd->identity = overrulingIdentity;
         }
     }
 
     if (mdd->messageBody)
     {
       MSG_ComposeFormat composeFormat = nsIMsgCompFormat::Default;
-      if (mdd->messageBody->type && *mdd->messageBody->type)
+      if (!mdd->messageBody->m_type.IsEmpty())
       {
-        if( PL_strcasestr(mdd->messageBody->type, "text/html"))
+        if(mdd->messageBody->m_type.Find("text/html", CaseInsensitiveCompare) != -1)
           composeFormat = nsIMsgCompFormat::HTML;
-        else if ( PL_strcasestr(mdd->messageBody->type, "text/plain") ||
-                  !PL_strcasecmp(mdd->messageBody->type, "text") )
+        else if (mdd->messageBody->m_type.Find("text/plain", CaseInsensitiveCompare) != -1 ||
+                 mdd->messageBody->m_type.LowerCaseEqualsLiteral("text"))
           composeFormat = nsIMsgCompFormat::PlainText;
         else
-        {
           //We cannot use this kind of data for the message body! Therefore, move it as attachment
           bodyAsAttachment = PR_TRUE;
-        }
       }
       else
         composeFormat = nsIMsgCompFormat::PlainText;
 
       char *body = nsnull;
       PRUint32 bodyLen = 0;
 
       if (!bodyAsAttachment)
       {
         PRInt64 fileSize;
         nsCOMPtr<nsIFile> tempFileCopy;
-        mdd->messageBody->tmp_file->Clone(getter_AddRefs(tempFileCopy));
-        mdd->messageBody->tmp_file = do_QueryInterface(tempFileCopy);
+        mdd->messageBody->m_tmpFile->Clone(getter_AddRefs(tempFileCopy));
+        mdd->messageBody->m_tmpFile = do_QueryInterface(tempFileCopy);
         tempFileCopy = nsnull;
-        mdd->messageBody->tmp_file->GetFileSize(&fileSize);
+        mdd->messageBody->m_tmpFile->GetFileSize(&fileSize);
         bodyLen = fileSize;
         body = (char *)PR_MALLOC (bodyLen + 1);
         if (body)
         {
           memset (body, 0, bodyLen+1);
 
           PRUint32 bytesRead;
           nsCOMPtr <nsIInputStream> inputStream;
 
-          nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), mdd->messageBody->tmp_file);
+          nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), mdd->messageBody->m_tmpFile);
           if (NS_FAILED(rv))
             return;
 
           inputStream->Read(body, bodyLen, &bytesRead);
 
           inputStream->Close();
 
           // Convert the body to UTF-8
           char *mimeCharset = nsnull;
           // Get a charset from the header if no override is set.
           if (!charsetOverride)
-            mimeCharset = MimeHeaders_get_parameter (mdd->messageBody->type, "charset", nsnull, nsnull);
+            mimeCharset = MimeHeaders_get_parameter (mdd->messageBody->m_type.get(), "charset", nsnull, nsnull);
           // If no charset is specified in the header then use the default.
           char *bodyCharset = mimeCharset ? mimeCharset : mdd->mailcharset;
           if (bodyCharset)
           {
             nsAutoString tmpUnicodeBody;
             rv = ConvertToUnicode(bodyCharset, body, tmpUnicodeBody);
             if (NS_FAILED(rv)) // Tough luck, ASCII/ISO-8859-1 then...
               CopyASCIItoUTF16(nsDependentCString(body), tmpUnicodeBody);
@@ -1661,30 +1601,25 @@ mime_parse_stream_complete (nsMIMESessio
     MimeHeaders_free ( mdd->headers );
 
   //
   // Free the original attachment structure...
   // Make sure we only cleanup the local copy of the memory and not kill
   // files we need on disk
   //
   if (bodyAsAttachment)
-    mdd->messageBody->tmp_file = nsnull;
-
-  mime_free_attachments (mdd->messageBody, 1);
+    mdd->messageBody->m_tmpFile = nsnull;
+  else if (mdd->messageBody->m_tmpFile)
+    mdd->messageBody->m_tmpFile->Remove(PR_FALSE);
 
-  if (mdd->attachments)
-  {
-    int               i;
-    nsMsgAttachedFile *cur = mdd->attachments;
+  delete mdd->messageBody;
 
-    for ( i = 0; i < mdd->attachments_count; i++, cur++ )
-        cur->tmp_file = nsnull;
+  for (int i = 0; i < mdd->attachments.Length(); i++)
+    mdd->attachments[i]->m_tmpFile = nsnull;
 
-    mime_free_attachments( mdd->attachments, mdd->attachments_count );
-  }
   PR_FREEIF(mdd->mailcharset);
 
   mdd->identity = nsnull;
   PR_Free(mdd->url_name);
   PR_Free(mdd->originalMsgURI);
   mdd->origMsgHdr = nsnull;
   PR_Free(mdd);
 
@@ -1700,23 +1635,23 @@ mime_parse_stream_complete (nsMIMESessio
   PR_FREEIF(to);
   PR_FREEIF(cc);
   PR_FREEIF(grps);
   PR_FREEIF(foll);
   PR_FREEIF(priority);
   PR_FREEIF(draftInfo);
   PR_Free(identityKey);
 
-  mime_free_attach_data(newAttachData);
+  delete [] newAttachData;
 }
 
 static void
 mime_parse_stream_abort (nsMIMESession *stream, int status )
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
+  mime_draft_data *mdd = (mime_draft_data *) stream->data_object;
   NS_ASSERTION (mdd, "null mime draft data");
 
   if (!mdd)
     return;
 
   if (mdd->obj)
   {
     int status=0;
@@ -1742,28 +1677,27 @@ mime_parse_stream_abort (nsMIMESession *
       mdd->stream = 0;
     }
   }
 
   if ( mdd->headers )
     MimeHeaders_free (mdd->headers);
 
 
-  if (mdd->attachments)
-    mime_free_attachments( mdd->attachments, mdd->attachments_count );
+  mime_free_attachments(mdd->attachments);
 
   PR_FREEIF(mdd->mailcharset);
 
   PR_Free (mdd);
 }
 
 static int
 make_mime_headers_copy ( void *closure, MimeHeaders *headers )
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) closure;
+  mime_draft_data *mdd = (mime_draft_data *) closure;
 
   NS_ASSERTION ( mdd && headers, "null mime draft data and/or headers" );
 
   if ( !mdd || ! headers )
     return 0;
 
   NS_ASSERTION ( mdd->headers == NULL , "non null mime draft data headers");
 
@@ -1771,158 +1705,137 @@ make_mime_headers_copy ( void *closure, 
   mdd->options->done_parsing_outer_headers = PR_TRUE;
 
   return 0;
 }
 
 nsresult
 mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers )
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
+  mime_draft_data *mdd = (mime_draft_data *) stream_closure;
   nsMsgAttachedFile *attachments = 0, *newAttachment = 0;
   int nAttachments = 0;
   //char *hdr_value = NULL;
   char *parm_value = NULL;
   PRBool needURL = PR_FALSE;
   PRBool creatingMsgBody = PR_TRUE;
   PRBool bodyPart = PR_FALSE;
 
   NS_ASSERTION (mdd && headers, "null mime draft data and/or headers");
   if (!mdd || !headers)
     return -1;
 
   if (mdd->options->decompose_init_count)
   {
     mdd->options->decompose_init_count++;
     NS_ASSERTION(mdd->curAttachment, "missing attachment in mime_decompose_file_init_fn");
-    if (mdd->curAttachment) {
-      char *ct = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);
-      if (ct)
-        NS_MsgSACopy(&(mdd->curAttachment->type), ct);
-      PR_FREEIF(ct);
-    }
+    if (mdd->curAttachment)
+      mdd->curAttachment->m_type.Adopt(MimeHeaders_get(headers,
+                                                       HEADER_CONTENT_TYPE,
+                                                       PR_TRUE, PR_FALSE));
     return 0;
   }
   else
     mdd->options->decompose_init_count++;
 
-  nAttachments = mdd->attachments_count;
+  nAttachments = mdd->attachments.Length();
 
   if (!nAttachments && !mdd->messageBody)
   {
     // if we've been told to use an override charset then do so....otherwise use the charset
     // inside the message header...
     if (mdd->options && mdd->options->override_charset)
         mdd->mailcharset = strdup(mdd->options->default_charset);
     else
     {
-      char *contentType = NULL;
+      char *contentType;
       contentType = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);
       if (contentType)
       {
         mdd->mailcharset = MimeHeaders_get_parameter(contentType, "charset", NULL, NULL);
         PR_FREEIF(contentType);
       }
     }
 
-    mdd->messageBody = PR_NEWZAP (nsMsgAttachedFile);
-    NS_ASSERTION (mdd->messageBody, "missing messageBody in mime_decompose_file_init_fn");
+    mdd->messageBody = new nsMsgAttachedFile;
     if (!mdd->messageBody)
       return MIME_OUT_OF_MEMORY;
     newAttachment = mdd->messageBody;
     creatingMsgBody = PR_TRUE;
     bodyPart = PR_TRUE;
   }
   else
   {
     /* always allocate one more extra; don't ask me why */
     needURL = PR_TRUE;
-    if ( nAttachments )
-    {
-      NS_ASSERTION (mdd->attachments, "no attachments");
-
-      attachments = (nsMsgAttachedFile *)PR_REALLOC(mdd->attachments,
-                                                    sizeof (nsMsgAttachedFile) *
-                                                    (nAttachments + 2));
-    if (!attachments)
-        return MIME_OUT_OF_MEMORY;
-      mdd->attachments = attachments;
-      mdd->attachments_count++;
-    }
-    else {
-      NS_ASSERTION (!mdd->attachments, "have attachments but count is 0");
-
-      attachments = (nsMsgAttachedFile *) PR_MALLOC ( sizeof (nsMsgAttachedFile) * 2);
-      if (!attachments)
-        return MIME_OUT_OF_MEMORY;
-      mdd->attachments_count++;
-      mdd->attachments = attachments;
-    }
-
-    newAttachment = attachments + nAttachments;
-    memset ( newAttachment, 0, sizeof (nsMsgAttachedFile) * 2 );
+    newAttachment = new nsMsgAttachedFile;
+    if (!newAttachment)
+      return MIME_OUT_OF_MEMORY;
+    mdd->attachments.AppendElement(newAttachment);
   }
 
   char *workURLSpec = nsnull;
   char *contLoc = nsnull;
 
-  newAttachment->real_name = MimeHeaders_get_name ( headers, mdd->options );
+  newAttachment->m_realName.Adopt(MimeHeaders_get_name(headers, mdd->options));
   contLoc = MimeHeaders_get( headers, HEADER_CONTENT_LOCATION, PR_FALSE, PR_FALSE );
   if (!contLoc)
       contLoc = MimeHeaders_get( headers, HEADER_CONTENT_BASE, PR_FALSE, PR_FALSE );
 
-  if ( (!contLoc) && (newAttachment->real_name) )
-    workURLSpec = strdup(newAttachment->real_name);
+  if (!contLoc && !newAttachment->m_realName.IsEmpty())
+    workURLSpec = ToNewCString(newAttachment->m_realName);
   if ( (contLoc) && (!workURLSpec) )
     workURLSpec = strdup(contLoc);
 
   PR_FREEIF(contLoc);
 
   mdd->curAttachment = newAttachment;
-  newAttachment->type =  MimeHeaders_get ( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE );
+  newAttachment->m_type.Adopt(MimeHeaders_get ( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE ));
 
   //
   // This is to handle the degenerated Apple Double attachment.
   //
   parm_value = MimeHeaders_get( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE );
   if (parm_value)
   {
     char *boundary = NULL;
     char *tmp_value = NULL;
     boundary = MimeHeaders_get_parameter(parm_value, "boundary", NULL, NULL);
     if (boundary)
       tmp_value = PR_smprintf("; boundary=\"%s\"", boundary);
     if (tmp_value)
-      NS_MsgSACat(&(newAttachment->type), tmp_value);
-    newAttachment->x_mac_type = MimeHeaders_get_parameter(parm_value, "x-mac-type", NULL, NULL);
-    newAttachment->x_mac_creator = MimeHeaders_get_parameter(parm_value, "x-mac-creator", NULL, NULL);
+      newAttachment->m_type = tmp_value;
+    newAttachment->m_xMacType.Adopt(
+      MimeHeaders_get_parameter(parm_value, "x-mac-type", NULL, NULL));
+    newAttachment->m_xMacCreator.Adopt(
+      MimeHeaders_get_parameter(parm_value, "x-mac-creator", NULL, NULL));
     PR_FREEIF(parm_value);
     PR_FREEIF(boundary);
     PR_FREEIF(tmp_value);
   }
-  newAttachment->size = 0;
-  newAttachment->encoding = MimeHeaders_get ( headers, HEADER_CONTENT_TRANSFER_ENCODING,
-                                              PR_FALSE, PR_FALSE );
-  newAttachment->description = MimeHeaders_get( headers, HEADER_CONTENT_DESCRIPTION,
-                                                PR_FALSE, PR_FALSE );
+  newAttachment->m_size = 0;
+  newAttachment->m_encoding.Adopt(MimeHeaders_get (headers, HEADER_CONTENT_TRANSFER_ENCODING,
+                                                   PR_FALSE, PR_FALSE ));
+  newAttachment->m_description.Adopt(MimeHeaders_get(headers, HEADER_CONTENT_DESCRIPTION,
+                                                     PR_FALSE, PR_FALSE ));
   //
   // If we came up empty for description or the orig URL, we should do something about it.
   //
-  if  ( ( (!newAttachment->description) || (!*newAttachment->description) ) && (workURLSpec) )
-    newAttachment->description = strdup(workURLSpec);
+  if (newAttachment->m_description.IsEmpty() && workURLSpec)
+    newAttachment->m_description = workURLSpec;
 
   nsCOMPtr <nsIFile> tmpFile = nsnull;
   {
     // Let's build a temp file with an extension based on the content-type: nsmail.<extension>
 
     nsCAutoString  newAttachName ("nsmail");
     PRBool extensionAdded = PR_FALSE;
     // the content type may contain a charset. i.e. text/html; ISO-2022-JP...we want to strip off the charset
     // before we ask the mime service for a mime info for this content type.
-    nsCAutoString contentType (newAttachment->type);
+    nsCAutoString contentType (newAttachment->m_type);
     PRInt32 pos = contentType.FindChar(';');
     if (pos > 0)
       contentType.SetLength(pos);
     nsresult  rv = NS_OK;
     nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
     if (NS_SUCCEEDED(rv) && mimeFinder)
     {
       nsCAutoString fileExtension;
@@ -1948,59 +1861,57 @@ mime_decompose_file_init_fn ( void *stre
   // This needs to be done so the attachment structure has a handle
   // on the temp file for this attachment...
   // if ( (tmpFile) && (!bodyPart) )
   if (tmpFile)
   {
       nsCAutoString fileURL;
       rv = NS_GetURLSpecFromFile(tmpFile, fileURL);
       if (NS_SUCCEEDED(rv))
-        nsMimeNewURI(getter_AddRefs(newAttachment->orig_url),
+        nsMimeNewURI(getter_AddRefs(newAttachment->m_origUrl),
                      fileURL.get(), nsnull);
   }
 
   PR_FREEIF(workURLSpec);
   if (!tmpFile)
     return MIME_OUT_OF_MEMORY;
 
   mdd->tmpFile = do_QueryInterface(tmpFile);
 
-  newAttachment->tmp_file = mdd->tmpFile;
+  newAttachment->m_tmpFile = mdd->tmpFile;
 
   rv = MsgNewBufferedFileOutputStream(getter_AddRefs(mdd->tmpFileStream), tmpFile,PR_WRONLY | PR_CREATE_FILE, 00600);
   if (NS_FAILED(rv))
     return MIME_UNABLE_TO_OPEN_TMP_FILE;
 
   // For now, we are always going to decode all of the attachments
   // for the message. This way, we have native data
   if (creatingMsgBody)
   {
     MimeDecoderData *(*fn) (nsresult (*) (const char*, PRInt32, void*), void*) = 0;
 
     //
     // Initialize a decoder if necessary.
     //
-    if (!newAttachment->encoding)
-      ;
-    else if (!PL_strcasecmp(newAttachment->encoding, ENCODING_BASE64))
+    if (newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_BASE64))
       fn = &MimeB64DecoderInit;
-    else if (!PL_strcasecmp(newAttachment->encoding, ENCODING_QUOTED_PRINTABLE))
+    else if (newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_QUOTED_PRINTABLE))
     {
       mdd->decoder_data = MimeQPDecoderInit (/* The (nsresult (*) ...) cast is to turn the `void' argument into `MimeObject'. */
                               ((nsresult (*) (const char *, PRInt32, void *))
                               dummy_file_write), mdd->tmpFileStream);
       if (!mdd->decoder_data)
         return MIME_OUT_OF_MEMORY;
     }
-    else if (!PL_strcasecmp(newAttachment->encoding, ENCODING_UUENCODE) ||
-             !PL_strcasecmp(newAttachment->encoding, ENCODING_UUENCODE2) ||
-             !PL_strcasecmp(newAttachment->encoding, ENCODING_UUENCODE3) ||
-             !PL_strcasecmp(newAttachment->encoding, ENCODING_UUENCODE4))
+    else if (newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE) ||
+             newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE2) ||
+             newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE3) ||
+             newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_UUENCODE4))
       fn = &MimeUUDecoderInit;
-    else if (!PL_strcasecmp(newAttachment->encoding, ENCODING_YENCODE))
+    else if (newAttachment->m_encoding.LowerCaseEqualsLiteral(ENCODING_YENCODE))
       fn = &MimeYDecoderInit;
 
     if (fn)
     {
       mdd->decoder_data = fn (/* The (nsresult (*) ...) cast is to turn the `void' argument into `MimeObject'. */
                               ((nsresult (*) (const char *, PRInt32, void *))
                               dummy_file_write), mdd->tmpFileStream);
       if (!mdd->decoder_data)
@@ -2011,48 +1922,48 @@ mime_decompose_file_init_fn ( void *stre
   return 0;
 }
 
 nsresult
 mime_decompose_file_output_fn (const char     *buf,
                                PRInt32  size,
                                void     *stream_closure )
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
+  mime_draft_data *mdd = (mime_draft_data *) stream_closure;
   int ret = 0;
 
   NS_ASSERTION (mdd && buf, "missing mime draft data and/or buf");
   if (!mdd || !buf) return -1;
   if (!size) return NS_OK;
 
   if ( !mdd->tmpFileStream )
     return NS_OK;
 
   if (mdd->decoder_data) {
     PRInt32 outsize;
     ret = MimeDecoderWrite(mdd->decoder_data, buf, size, &outsize);
     if (ret == -1) return -1;
-    mdd->curAttachment->size += outsize;
+    mdd->curAttachment->m_size += outsize;
   }
   else
   {
     PRUint32 bytesWritten;
     mdd->tmpFileStream->Write(buf, size, &bytesWritten);
     if (bytesWritten < size)
       return MIME_ERROR_WRITING_FILE;
-    mdd->curAttachment->size += size;
+    mdd->curAttachment->m_size += size;
   }
 
   return NS_OK;
 }
 
 nsresult
 mime_decompose_file_close_fn ( void *stream_closure )
 {
-  struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
+  mime_draft_data *mdd = (mime_draft_data *) stream_closure;
 
   if ( !mdd || !mdd->tmpFileStream )
     return -1;
 
   if ( --mdd->options->decompose_init_count > 0 )
       return 0;
 
   if (mdd->decoder_data) {
@@ -2073,23 +1984,23 @@ extern "C" void  *
 mime_bridge_create_draft_stream(
                           nsIMimeEmitter      *newEmitter,
                           nsStreamConverter   *newPluginObj2,
                           nsIURI              *uri,
                           nsMimeOutputType    format_out)
 {
   int                     status = 0;
   nsMIMESession           *stream = nsnull;
-  struct mime_draft_data  *mdd = nsnull;
+  mime_draft_data  *mdd = nsnull;
   MimeObject              *obj = nsnull;
 
   if ( !uri )
     return nsnull;
 
-  mdd = PR_NEWZAP(struct mime_draft_data);
+  mdd = new mime_draft_data;
   if (!mdd)
     return nsnull;
 
   nsCAutoString turl;
   nsCOMPtr <nsIMsgMessageService> msgService;
   nsCOMPtr<nsIURI> aURL;
   nsCAutoString urlString;
   nsresult rv;
--- a/mailnews/mime/src/mimehdrs.cpp
+++ b/mailnews/mime/src/mimehdrs.cpp
@@ -687,17 +687,17 @@ MIME_StripContinuations(char *original)
   return original;
 }
 
 extern PRInt16 INTL_DefaultMailToWinCharSetID(PRInt16 csid);
 
 /* Given text purporting to be a qtext header value, strip backslashes that
   may be escaping other chars in the string. */
 char *
-mime_decode_filename(char *name, const char *charset,
+mime_decode_filename(const char *name, const char *charset,
                      MimeDisplayOptions *opt)
 {
   nsresult rv;
   nsCOMPtr <nsIMIMEHeaderParam> mimehdrpar =
     do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
 
   if (NS_FAILED(rv))
     return nsnull;
--- a/mailnews/mime/src/mimehdrs.h
+++ b/mailnews/mime/src/mimehdrs.h
@@ -101,17 +101,17 @@ extern char *MimeHeaders_make_crypto_sta
    PRBool close_parent_stamp_p,
 
    const char *stamp_url);
 
 /* Does all the heuristic silliness to find the filename in the given headers.
  */
 extern char *MimeHeaders_get_name(MimeHeaders *hdrs, MimeDisplayOptions *opt);
 
-extern char *mime_decode_filename(char *name, const char* charset,
+extern char *mime_decode_filename(const char *name, const char* charset,
                                   MimeDisplayOptions *opt);
 
 extern "C"  char * MIME_StripContinuations(char *original);
 
 /**
  * Convert this value to a unicode string, based on the charset.
  */
 extern void MimeHeaders_convert_header_value(MimeDisplayOptions *opt,
--- a/mailnews/mime/src/mimemoz2.cpp
+++ b/mailnews/mime/src/mimemoz2.cpp
@@ -127,43 +127,41 @@ ProcessBodyAsAttachment(MimeObject *obj,
   // Ok, this is the special case when somebody sends an "attachment" as the body
   // of an RFC822 message...I really don't think this is the way this should be done.
   // I belive this should really be a multipart/mixed message with an empty body part,
   // but what can ya do...our friends to the North seem to do this.
   //
   MimeObject    *child = obj;
 
   n = 1;
-  *data = (nsMsgAttachmentData *)PR_Malloc( (n + 1) * sizeof(nsMsgAttachmentData));
+  *data = new nsMsgAttachmentData[2];
   if (!*data)
     return NS_ERROR_OUT_OF_MEMORY;
 
   tmp = *data;
-  memset(*data, 0, (n + 1) * sizeof(nsMsgAttachmentData));
-  tmp->real_type = child->content_type ? strdup(child->content_type) : NULL;
-  tmp->real_encoding = child->encoding ? strdup(child->encoding) : NULL;
+  tmp->m_realType = child->content_type;
+  tmp->m_realEncoding = child->encoding;
   disp = MimeHeaders_get(child->headers, HEADER_CONTENT_DISPOSITION, PR_FALSE, PR_FALSE);
-  tmp->real_name = MimeHeaders_get_parameter(disp, "name", &charset, NULL);
-  if (tmp->real_name)
+  tmp->m_realName.Adopt(MimeHeaders_get_parameter(disp, "name", &charset, NULL));
+  if (!tmp->m_realName.IsEmpty())
   {
     char *fname = NULL;
-    fname = mime_decode_filename(tmp->real_name, charset, obj->options);
+    fname = mime_decode_filename(tmp->m_realName.get(), charset, obj->options);
     nsMemory::Free(charset);
-    if (fname && fname != tmp->real_name)
-    {
-      PR_Free(tmp->real_name);
-      tmp->real_name = fname;
-    }
+    if (fname)
+      tmp->m_realName.Adopt(fname);
   }
   else
   {
-    tmp->real_name = MimeHeaders_get_name(child->headers, obj->options);
+    tmp->m_realName.Adopt(MimeHeaders_get_name(child->headers, obj->options));
   }
 
-  if ( (!tmp->real_name) && (tmp->real_type) && (PL_strncasecmp(tmp->real_type, "text", 4)) )
+  if (tmp->m_realName.IsEmpty() &&
+      StringBeginsWith(tmp->m_realType, NS_LITERAL_CSTRING("text"),
+                       nsCaseInsensitiveCStringComparator()))
     ValidateRealName(tmp, child->headers);
 
   char  *tmpURL = nsnull;
   char  *id = nsnull;
   char  *id_imap = nsnull;
 
   id = mime_part_address (obj);
   if (obj->options->missing_parts)
@@ -179,37 +177,37 @@ ProcessBodyAsAttachment(MimeObject *obj,
   if (obj->options && obj->options->url)
   {
     const char  *url = obj->options->url;
     nsresult    rv;
     if (id_imap && id)
     {
       // if this is an IMAP part.
       tmpURL = mime_set_url_imap_part(url, id_imap, id);
-      rv = nsMimeNewURI(&(tmp->url), tmpURL, nsnull);
+      rv = nsMimeNewURI(getter_AddRefs(tmp->m_url), tmpURL, nsnull);
     }
     else
     {
       // This is just a normal MIME part as usual.
       tmpURL = mime_set_url_part(url, id, PR_TRUE);
-      rv = nsMimeNewURI(&(tmp->url), tmpURL, nsnull);
+      rv = nsMimeNewURI(getter_AddRefs(tmp->m_url), tmpURL, nsnull);
     }
 
-    if ( (!tmp->url) || (NS_FAILED(rv)) )
+    if (!tmp->m_url || NS_FAILED(rv))
     {
       PR_FREEIF(*data);
       PR_FREEIF(id);
       PR_FREEIF(id_imap);
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
   PR_FREEIF(id);
   PR_FREEIF(id_imap);
   PR_FREEIF(tmpURL);
-  tmp->description = MimeHeaders_get(child->headers, HEADER_CONTENT_DESCRIPTION, PR_FALSE, PR_FALSE);
+  tmp->m_description.Adopt(MimeHeaders_get(child->headers, HEADER_CONTENT_DESCRIPTION, PR_FALSE, PR_FALSE));
   return NS_OK;
 }
 
 PRInt32
 CountTotalMimeAttachments(MimeContainer *aObj)
 {
   PRInt32     i;
   PRInt32     rc = 0;
@@ -229,62 +227,64 @@ CountTotalMimeAttachments(MimeContainer 
 void
 ValidateRealName(nsMsgAttachmentData *aAttach, MimeHeaders *aHdrs)
 {
   // Sanity.
   if (!aAttach)
     return;
 
   // Do we need to validate?
-  if ( (aAttach->real_name) && (*(aAttach->real_name)) )
+  if (!aAttach->m_realName.IsEmpty())
     return;
 
   // Internal MIME structures need not be named!
-  if ( (!aAttach->real_type) || (aAttach->real_type &&
-                                 !PL_strncasecmp(aAttach->real_type, "multipart", 9)) )
+  if (aAttach->m_realType.IsEmpty() ||
+      StringBeginsWith(aAttach->m_realType, NS_LITERAL_CSTRING("multipart"),
+                       nsCaseInsensitiveCStringComparator()))
     return;
 
   // Special case...if this is a enclosed RFC822 message, give it a nice
   // name.
-  if (aAttach->real_type && !PL_strcasecmp(aAttach->real_type, MESSAGE_RFC822))
+  if (aAttach->m_realType.LowerCaseEqualsLiteral(MESSAGE_RFC822))
   {
     NS_ASSERTION(aHdrs, "How comes the object's headers is null!");
     if (aHdrs && aHdrs->munged_subject)
-      aAttach->real_name = PR_smprintf("%s.eml", aHdrs->munged_subject);
+    {
+      aAttach->m_realName.Assign(aHdrs->munged_subject);
+      aAttach->m_realName.Append(".eml");
+    }
     else
-      NS_MsgSACopy(&(aAttach->real_name), "ForwardedMessage.eml");
+      aAttach->m_realName = "ForwardedMessage.eml";
     return;
   }
 
   //
   // Now validate any other name we have for the attachment!
   //
-  if (!aAttach->real_name || *aAttach->real_name == 0)
+  if (aAttach->m_realName.IsEmpty())
   {
-    nsCString newAttachName(NS_LITERAL_CSTRING("attachment"));
+    aAttach->m_realName = "attachment";
     nsresult rv = NS_OK;
-    nsCAutoString contentType (aAttach->real_type);
+    nsCAutoString contentType (aAttach->m_realType);
     PRInt32 pos = contentType.FindChar(';');
     if (pos > 0)
       contentType.SetLength(pos);
 
     nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
     if (NS_SUCCEEDED(rv))
     {
       nsCAutoString fileExtension;
       rv = mimeFinder->GetPrimaryExtension(contentType, EmptyCString(), fileExtension);
 
       if (NS_SUCCEEDED(rv) && !fileExtension.IsEmpty())
       {
-        newAttachName.Append('.');
-        newAttachName.Append(fileExtension);
+        aAttach->m_realName.Append('.');
+        aAttach->m_realName.Append(fileExtension);
       }
     }
-
-    aAttach->real_name = ToNewCString(newAttachName);
   }
 }
 
 static  PRInt32     attIndex = 0;
 
 nsresult
 GenerateAttachmentData(MimeObject *object, const char *aMessageURL, MimeDisplayOptions *options,
                        PRBool isAnAppleDoublePart, PRInt32 attSize, nsMsgAttachmentData *aAttachData)
@@ -336,156 +336,146 @@ GenerateAttachmentData(MimeObject *objec
   if (!urlSpec)
     return NS_ERROR_OUT_OF_MEMORY;
 
   if ((options->format_out == nsMimeOutput::nsMimeMessageBodyDisplay) && (PL_strncasecmp(aMessageURL, urlSpec, strlen(urlSpec)) == 0))
     return NS_OK;
 
   nsMsgAttachmentData *tmp = &(aAttachData[attIndex++]);
 
-  tmp->real_type = object->content_type ? strdup(object->content_type) : nsnull;
-  tmp->real_encoding = object->encoding ? strdup(object->encoding) : nsnull;
-  tmp->isExternalAttachment = isExternalAttachment;
-  tmp->size = attSize;
+  tmp->m_realType = object->content_type;
+  tmp->m_realEncoding = object->encoding;
+  tmp->m_isExternalAttachment = isExternalAttachment;
+  tmp->m_size = attSize;
 
   char *part_addr = mime_imap_part_address(object);
-  tmp->isDownloaded = (part_addr == nsnull);
+  tmp->m_isDownloaded = (part_addr == nsnull);
   PR_FREEIF(part_addr);
 
   PRInt32 i;
   char *charset = nsnull;
   char *disp = MimeHeaders_get(object->headers, HEADER_CONTENT_DISPOSITION, PR_FALSE, PR_FALSE);
   if (disp)
   {
-    tmp->real_name = MimeHeaders_get_parameter(disp, "filename", &charset, nsnull);
+    tmp->m_realName.Adopt(MimeHeaders_get_parameter(disp, "filename", &charset, nsnull));
     if (isAnAppleDoublePart)
-      for (i = 0; i < 2 && !tmp->real_name; i ++)
+      for (i = 0; i < 2 && tmp->m_realName.IsEmpty(); i ++)
       {
         PR_FREEIF(disp);
         nsMemory::Free(charset);
         disp = MimeHeaders_get(((MimeContainer *)object)->children[i]->headers, HEADER_CONTENT_DISPOSITION, PR_FALSE, PR_FALSE);
-        tmp->real_name = MimeHeaders_get_parameter(disp, "filename", &charset, nsnull);
+        tmp->m_realName.Adopt(MimeHeaders_get_parameter(disp, "filename", &charset, nsnull));
       }
 
-    if (tmp->real_name)
+    if (!tmp->m_realName.IsEmpty())
     {
       // check encoded type
       //
       // The parameter of Content-Disposition must use RFC 2231.
       // But old Netscape 4.x and Outlook Express etc. use RFC2047.
       // So we should parse both types.
 
       char *fname = nsnull;
-      fname = mime_decode_filename(tmp->real_name, charset, options);
+      fname = mime_decode_filename(tmp->m_realName.get(), charset, options);
       nsMemory::Free(charset);
 
-      if (fname && fname != tmp->real_name)
-      {
-        PR_FREEIF(tmp->real_name);
-        tmp->real_name = fname;
-      }
+      if (fname)
+        tmp->m_realName.Adopt(fname);
     }
 
     PR_FREEIF(disp);
   }
 
   disp = MimeHeaders_get(object->headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);
   if (disp)
   {
-    tmp->x_mac_type   = MimeHeaders_get_parameter(disp, PARAM_X_MAC_TYPE, nsnull, nsnull);
-    tmp->x_mac_creator= MimeHeaders_get_parameter(disp, PARAM_X_MAC_CREATOR, nsnull, nsnull);
+    tmp->m_xMacType.Adopt(MimeHeaders_get_parameter(disp, PARAM_X_MAC_TYPE, nsnull, nsnull));
+    tmp->m_xMacCreator.Adopt(MimeHeaders_get_parameter(disp, PARAM_X_MAC_CREATOR, nsnull, nsnull));
 
-    if (!tmp->real_name || *tmp->real_name == 0)
+    if (tmp->m_realName.IsEmpty())
     {
-      PR_FREEIF(tmp->real_name);
-      tmp->real_name = MimeHeaders_get_parameter(disp, "name", &charset, nsnull);
+      tmp->m_realName.Adopt(MimeHeaders_get_parameter(disp, "name", &charset, nsnull));
       if (isAnAppleDoublePart)
         // the data fork is the 2nd part, and we should ALWAYS look there first for the file name
-        for (i = 1; i >= 0 && !tmp->real_name; i --)
+        for (i = 1; i >= 0 && tmp->m_realName.IsEmpty(); i --)
         {
           PR_FREEIF(disp);
           nsMemory::Free(charset);
           disp = MimeHeaders_get(((MimeContainer *)object)->children[i]->headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);
-          tmp->real_name = MimeHeaders_get_parameter(disp, "name", &charset, nsnull);
-          tmp->real_type =
+          tmp->m_realName.Adopt(MimeHeaders_get_parameter(disp, "name", &charset, nsnull));
+          tmp->m_realType.Adopt(
             MimeHeaders_get(((MimeContainer *)object)->children[i]->headers,
-                            HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);
+                            HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE));
         }
 
-      if (tmp->real_name)
+      if (!tmp->m_realName.IsEmpty())
       {
         // check encoded type
         //
         // The parameter of Content-Disposition must use RFC 2231.
         // But old Netscape 4.x and Outlook Express etc. use RFC2047.
         // So we should parse both types.
 
         char *fname = nsnull;
-        fname = mime_decode_filename(tmp->real_name, charset, options);
+        fname = mime_decode_filename(tmp->m_realName.get(), charset, options);
         nsMemory::Free(charset);
 
-        if (fname && fname != tmp->real_name)
-        {
-          PR_Free(tmp->real_name);
-          tmp->real_name = fname;
-        }
+        if (fname)
+          tmp->m_realName.Adopt(fname);
       }
     }
     PR_FREEIF(disp);
   }
 
-  tmp->description = MimeHeaders_get(object->headers, HEADER_CONTENT_DESCRIPTION,
-                                     PR_FALSE, PR_FALSE);
+  tmp->m_description.Adopt(MimeHeaders_get(object->headers, HEADER_CONTENT_DESCRIPTION,
+                                           PR_FALSE, PR_FALSE));
 
   // Now, do the right thing with the name!
-  if (!tmp->real_name && PL_strcasecmp(tmp->real_type, MESSAGE_RFC822))
+  if (tmp->m_realName.IsEmpty() && !(tmp->m_realType.LowerCaseEqualsLiteral(MESSAGE_RFC822)))
   {
     // Keep in mind that the name was provided by us and this is probably not a
     // real attachment.
-    tmp->hasFilename = PR_FALSE;
+    tmp->m_hasFilename = PR_FALSE;
     /* If this attachment doesn't have a name, just give it one... */
-    tmp->real_name = MimeGetStringByID(MIME_MSG_DEFAULT_ATTACHMENT_NAME);
-    if (tmp->real_name)
+    tmp->m_realName.Adopt(MimeGetStringByID(MIME_MSG_DEFAULT_ATTACHMENT_NAME));
+    if (!tmp->m_realName.IsEmpty())
     {
-      char *newName = PR_smprintf(tmp->real_name, part.get());
+      char *newName = PR_smprintf(tmp->m_realName.get(), part.get());
       if (newName)
-      {
-        PR_Free(tmp->real_name);
-        tmp->real_name = newName;
-      }
+        tmp->m_realName.Adopt(newName);
     }
     else
-      tmp->real_name = mime_part_address(object);
+      tmp->m_realName.Adopt(mime_part_address(object));
   } else {
-    tmp->hasFilename = PR_TRUE;
+    tmp->m_hasFilename = PR_TRUE;
   }
   nsCString urlString(urlSpec);
 
-  if (tmp->real_name && !tmp->isExternalAttachment)
+  if (!tmp->m_realName.IsEmpty() && !tmp->m_isExternalAttachment)
   {
     urlString.Append("&filename=");
     nsCAutoString aResult;
-    if (NS_SUCCEEDED(MsgEscapeString(nsDependentCString(tmp->real_name),
+    if (NS_SUCCEEDED(MsgEscapeString(tmp->m_realName,
                                      nsINetUtil::ESCAPE_XALPHAS, aResult)))
       urlString.Append(aResult);
     else
-      urlString.Append(tmp->real_name);
-    if (tmp->real_type && !strcmp(tmp->real_type, "message/rfc822") &&
+      urlString.Append(tmp->m_realName);
+    if (tmp->m_realType.EqualsLiteral("message/rfc822") &&
            !StringEndsWith(urlString, NS_LITERAL_CSTRING(".eml"), nsCaseInsensitiveCStringComparator()))
       urlString.Append(".eml");
-  } else if (tmp->isExternalAttachment) {
+  } else if (tmp->m_isExternalAttachment) {
     // Allows the JS mime emitter to figure out the part information.
     urlString.Append("?part=");
     urlString.Append(part);
   }
-  nsresult rv = nsMimeNewURI(&(tmp->url), urlString.get(), nsnull);
+  nsresult rv = nsMimeNewURI(getter_AddRefs(tmp->m_url), urlString.get(), nsnull);
 
   PR_FREEIF(urlSpec);
 
-  if ( (NS_FAILED(rv)) || (!tmp->url) )
+  if (NS_FAILED(rv) || !tmp->m_url)
     return NS_ERROR_OUT_OF_MEMORY;
 
   ValidateRealName(tmp, object->headers);
 
   return NS_OK;
 }
 
 nsresult MimeGetSize(MimeObject *child, PRInt32 *size) {
@@ -624,114 +614,83 @@ MimeGetAttachmentList(MimeObject *tobj, 
   if (n <= 0)
     return n;
 
   // in case of an inline message (as body), we need an extra slot for the
   // message itself that we will fill later...
   if (isAnInlineMessage)
     n ++;
 
-  *data = (nsMsgAttachmentData *)PR_Malloc( (n + 1) * sizeof(nsMsgAttachmentData));
+  *data = new nsMsgAttachmentData[n + 1];
   if (!*data)
     return NS_ERROR_OUT_OF_MEMORY;
 
   attIndex = 0;
-  memset(*data, 0, (n + 1) * sizeof(nsMsgAttachmentData));
 
   // Now, build the list!
 
   nsresult rv;
 
   if (isAnInlineMessage)
   {
     rv = GenerateAttachmentData(obj, aMessageURL, obj->options, PR_FALSE, -1, *data);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return BuildAttachmentList((MimeObject *) cobj, *data, aMessageURL);
 }
 
 extern "C" void
 MimeFreeAttachmentList(nsMsgAttachmentData *data)
 {
-  if (data)
-  {
-    nsMsgAttachmentData   *tmp;
-    for (tmp = data ; tmp->url ; tmp++)
-    {
-      /* Can't do PR_FREEIF on `const' values... */
-      NS_IF_RELEASE(tmp->url);
-      if (tmp->real_type) PR_Free((char *) tmp->real_type);
-      if (tmp->real_encoding) PR_Free((char *) tmp->real_encoding);
-      if (tmp->real_name) PR_Free((char *) tmp->real_name);
-      if (tmp->x_mac_type) PR_Free((char *) tmp->x_mac_type);
-      if (tmp->x_mac_creator) PR_Free((char *) tmp->x_mac_creator);
-      if (tmp->description) PR_Free((char *) tmp->description);
-      tmp->url = 0;
-      tmp->real_type = 0;
-      tmp->real_name = 0;
-      tmp->description = 0;
-    }
-    PR_Free(data);
-  }
+  delete [] data;
 }
 
 extern "C" void
 NotifyEmittersOfAttachmentList(MimeDisplayOptions     *opt,
                                nsMsgAttachmentData    *data)
 {
   PRInt32     i = 0;
-  struct      nsMsgAttachmentData  *tmp = data;
+  nsMsgAttachmentData  *tmp = data;
 
   if (!tmp)
     return;
 
-  while (tmp->url)
+  while (tmp->m_url)
   {
-    if (!tmp->real_name || (!tmp->hasFilename && (opt->html_as_p != 4 || opt->metadata_only)))
+    if (tmp->m_realName.IsEmpty() || (!tmp->m_hasFilename &&
+        (opt->html_as_p != 4 || opt->metadata_only)))
     {
       ++i;
       ++tmp;
       continue;
     }
 
     nsCAutoString spec;
-    if ( tmp->url )
-      tmp->url->GetSpec(spec);
+    if (tmp->m_url)
+      tmp->m_url->GetSpec(spec);
 
     nsCAutoString sizeStr;
-    sizeStr.AppendInt(tmp->size);
+    sizeStr.AppendInt(tmp->m_size);
     nsCAutoString downloadedStr;
-    downloadedStr.AppendInt(tmp->isDownloaded);
+    downloadedStr.AppendInt(tmp->m_isDownloaded);
 
-    mimeEmitterStartAttachment(opt, tmp->real_name, tmp->real_type, spec.get(), tmp->isExternalAttachment);
+    mimeEmitterStartAttachment(opt, tmp->m_realName.get(), tmp->m_realType.get(),
+                               spec.get(), tmp->m_isExternalAttachment);
     mimeEmitterAddAttachmentField(opt, HEADER_X_MOZILLA_PART_URL, spec.get());
     mimeEmitterAddAttachmentField(opt, HEADER_X_MOZILLA_PART_SIZE, sizeStr.get());
     mimeEmitterAddAttachmentField(opt, HEADER_X_MOZILLA_PART_DOWNLOADED, downloadedStr.get());
 
     if ( (opt->format_out == nsMimeOutput::nsMimeMessageQuoting) ||
          (opt->format_out == nsMimeOutput::nsMimeMessageBodyQuoting) ||
          (opt->format_out == nsMimeOutput::nsMimeMessageSaveAs) ||
          (opt->format_out == nsMimeOutput::nsMimeMessagePrintOutput))
     {
-      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_DESCRIPTION, tmp->description);
-      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_TYPE, tmp->real_type);
-      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_ENCODING,    tmp->real_encoding);
-
-      /* rhp - for now, just leave these here, but they are really
-               not necessary
-      printf("URL for Part      : %s\n", spec.get());
-      printf("Real Name         : %s\n", tmp->real_name);
-      printf("Desired Type      : %s\n", tmp->desired_type);
-      printf("Real Type         : %s\n", tmp->real_type);
-      printf("Real Encoding     : %s\n", tmp->real_encoding);
-      printf("Description       : %s\n", tmp->description);
-      printf("Mac Type          : %s\n", tmp->x_mac_type);
-      printf("Mac Creator       : %s\n", tmp->x_mac_creator);
-      printf("Size              : %d\n", tmp->size);
-      */
+      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_DESCRIPTION, tmp->m_description.get());
+      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_TYPE, tmp->m_realType.get());
+      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_ENCODING, tmp->m_realEncoding.get());
     }
 
     mimeEmitterEndAttachment(opt);
     ++i;
     ++tmp;
   }
   mimeEmitterEndAllAttachments(opt);
 }
@@ -1993,18 +1952,18 @@ mimeEmitterEndHeader(MimeDisplayOptions 
     nsIMimeEmitter *emitter = (nsIMimeEmitter *)msd->output_emitter;
 
     nsCString name;
     nsMsgAttachmentData *attachments = nsnull;
     if (msd->format_out == nsMimeOutput::nsMimeMessageSplitDisplay ||
         msd->format_out == nsMimeOutput::nsMimeMessageHeaderDisplay ||
         msd->format_out == nsMimeOutput::nsMimeMessageBodyDisplay) {
       nsresult rv = MimeGetAttachmentList(msd->obj, msd->url_name, &attachments);
-      if (NS_SUCCEEDED(rv) && attachments && attachments->real_name)
-        name.Assign(attachments->real_name);
+      if (NS_SUCCEEDED(rv) && attachments)
+        name.Assign(attachments->m_realName);
     }
 
     MimeHeaders_convert_header_value(opt, name, false);
     MimeFreeAttachmentList(attachments);
     return emitter->EndHeader(name);
   }
 
   return NS_ERROR_FAILURE;
--- a/mailnews/mime/src/mimemoz2.h
+++ b/mailnews/mime/src/mimemoz2.h
@@ -125,33 +125,29 @@ struct mime_stream_data {           /* T
   MimeDisplayOptions  *options;     /* Data for communicating with libmime.a */
   MimeHeaders         *headers;     /* Copy of outer most mime header */
 
   nsIMimeEmitter      *output_emitter;  /* Output emitter engine for libmime */
   PRBool              firstCheck;   /* Is this the first look at the stream data */
 };
 
 //
-// This struct is the state we use for loading drafts and templates...
+// This object is the state we use for loading drafts and templates...
 //
-struct mime_draft_data
+class mime_draft_data
 {
-  /* WARNING: You cannot use a c++ object, in that structure, which is dependent on its constructor or
-           destructor as mime_draft_data is not created using the new operator. nsCOMPtr however are ok
-           to use as long you set it to null before the structure get freed.
-  */
-
+public:
+  mime_draft_data();
   char                *url_name;           // original url name */
   nsMimeOutputType    format_out;          // intended output format; should be FO_OPEN_DRAFT */
   nsMIMESession       *stream;             // not used for now
   MimeObject          *obj;                // The root
   MimeDisplayOptions  *options;            // data for communicating with libmime
   MimeHeaders         *headers;            // Copy of outer most mime header
-  PRInt32             attachments_count;   // how many attachments we have
-  nsMsgAttachedFile   *attachments;        // attachments
+  nsTArray<nsMsgAttachedFile*> attachments;// attachments
   nsMsgAttachedFile   *messageBody;        // message body
   nsMsgAttachedFile   *curAttachment;       // temp
 
   nsCOMPtr <nsILocalFile> tmpFile;
   nsCOMPtr <nsIOutputStream> tmpFileStream;      // output file handle
 
   MimeDecoderData     *decoder_data;
   char                *mailcharset;        // get it from CHARSET of Content-Type
--- a/mailnews/mime/src/mimemrel.cpp
+++ b/mailnews/mime/src/mimemrel.cpp
@@ -764,17 +764,17 @@ real_write(MimeMultipartRelated* relobj,
   {
 
     // the buf here has already been decoded, but we want to use general output
     // functions here that permit decoded or encoded input, using the closure
     // to tell the difference. We'll temporarily disable the closure's decoder, 
     // then restore it when we are done. Not sure if we shouldn't just turn it off
     // permanently though.
 
-    struct mime_draft_data *mdd = (struct mime_draft_data *) obj->options->stream_closure;
+    mime_draft_data *mdd = (mime_draft_data *) obj->options->stream_closure;
     MimeDecoderData* old_decoder_data = mdd->decoder_data;
     mdd->decoder_data = nsnull;
     int status = obj->options->decompose_file_output_fn
                  (buf, size, (void *)mdd);
     mdd->decoder_data = old_decoder_data;
     return status;
   }
   else
--- a/mailnews/mime/src/nsStreamConverter.cpp
+++ b/mailnews/mime/src/nsStreamConverter.cpp
@@ -138,17 +138,17 @@ bridge_new_new_uri(void *bridgeStream, n
     {
       PRBool   *override_charset = nsnull;
       char    **default_charset = nsnull;
       char    **url_name = nsnull;
 
       if  ( (aOutputType == nsMimeOutput::nsMimeMessageDraftOrTemplate) ||
             (aOutputType == nsMimeOutput::nsMimeMessageEditorTemplate) )
       {
-        struct mime_draft_data *mdd = (struct mime_draft_data *)session->data_object;
+        mime_draft_data *mdd = (mime_draft_data *)session->data_object;
         if (mdd->options)
         {
           default_charset = &(mdd->options->default_charset);
           override_charset = &(mdd->options->override_charset);
           url_name = &(mdd->url_name);
         }
       }
       else
@@ -275,17 +275,17 @@ bridge_set_mime_stream_converter_listene
 {
   nsMIMESession *session = (nsMIMESession *)bridgeStream;
 
   if ( (session) && (session->data_object) )
   {
     if  ( (aOutputType == nsMimeOutput::nsMimeMessageDraftOrTemplate) ||
           (aOutputType == nsMimeOutput::nsMimeMessageEditorTemplate) )
     {
-      struct mime_draft_data *mdd = (struct mime_draft_data *)session->data_object;
+      mime_draft_data *mdd = (mime_draft_data *)session->data_object;
       if (mdd->options)
       {
         if (listener)
         {
           mdd->options->caller_need_root_headers = PR_TRUE;
           mdd->options->decompose_headers_info_fn = mime_headers_callback;
         }
         else
@@ -1053,17 +1053,17 @@ nsStreamConverter::OnStopRequest(nsIRequ
     if (mMimeStreamConverterListener)
     {
 
       MimeHeaders    **workHeaders = nsnull;
 
       if  ( (mOutputType == nsMimeOutput::nsMimeMessageDraftOrTemplate) ||
             (mOutputType == nsMimeOutput::nsMimeMessageEditorTemplate) )
       {
-        struct mime_draft_data *mdd = (struct mime_draft_data *)tSession->data_object;
+        mime_draft_data *mdd = (mime_draft_data *)tSession->data_object;
         if (mdd)
           workHeaders = &(mdd->headers);
       }
       else
       {
         struct mime_stream_data *msd = (struct mime_stream_data *)tSession->data_object;
         if (msd)
           workHeaders = &(msd->headers);