Bug 790855, part 2: Implement nsIMimeConverter in JS, r=irving, a=me
authorJoshua Cranmer <Pidgeot18@gmail.com>
Wed, 04 Jun 2014 09:51:36 -0500
changeset 16281 8877b30a38c31bd79ef3cdde696a0392d3c5d95b
parent 16280 29d10e5f69abeb6109790c23b74a6e49c6755224
child 16282 2608fae8b13be280012b5561bbdab12824a8f95a
push id10173
push userPidgeot18@gmail.com
push dateWed, 04 Jun 2014 16:44:46 +0000
treeherdercomm-central@8877b30a38c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersirving, me
bugs790855
Bug 790855, part 2: Implement nsIMimeConverter in JS, r=irving, a=me
mailnews/build/nsMailModule.cpp
mailnews/compose/src/nsURLFetcher.cpp
mailnews/compose/test/unit/test_attachment.js
mailnews/mime/jsmime/jsmime.js
mailnews/mime/public/nsIMimeConverter.idl
mailnews/mime/public/nsMsgMimeCID.h
mailnews/mime/src/comi18n.cpp
mailnews/mime/src/comi18n.h
mailnews/mime/src/mimeJSComponents.js
mailnews/mime/src/mimei.cpp
mailnews/mime/src/mimemoz2.cpp
mailnews/mime/src/moz.build
mailnews/mime/src/msgMime.manifest
mailnews/mime/src/nsMimeConverter.cpp
mailnews/mime/src/nsMimeConverter.h
mailnews/mime/src/nsStreamConverter.cpp
mailnews/mime/test/unit/test_EncodeMimePartIIStr_UTF8.js
--- a/mailnews/build/nsMailModule.cpp
+++ b/mailnews/build/nsMailModule.cpp
@@ -232,17 +232,16 @@
 #include "nsImapMailDatabase.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // mime includes
 ///////////////////////////////////////////////////////////////////////////////
 #include "nsMsgMimeCID.h"
 #include "nsStreamConverter.h"
 #include "nsMimeObjectClassAccess.h"
-#include "nsMimeConverter.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // mime emitter includes
 ///////////////////////////////////////////////////////////////////////////////
 #include "nsMimeEmitterCID.h"
 #include "nsIMimeEmitter.h"
 #include "nsMimeHtmlEmitter.h"
 #include "nsMimeRawEmitter.h"
@@ -664,21 +663,19 @@ NS_DEFINE_NAMED_CID(NS_IMAPDB_CID);
 NS_DEFINE_NAMED_CID(NS_MSG_RETENTIONSETTINGS_CID);
 NS_DEFINE_NAMED_CID(NS_MSG_DOWNLOADSETTINGS_CID);
 NS_DEFINE_NAMED_CID(NS_MSGDB_SERVICE_CID);
 
 ////////////////////////////////////////////////////////////////////////////////
 // mime factories
 ////////////////////////////////////////////////////////////////////////////////
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimeObjectClassAccess)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimeConverter)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamConverter)
 
 NS_DEFINE_NAMED_CID(NS_MIME_OBJECT_CLASS_ACCESS_CID);
-NS_DEFINE_NAMED_CID(NS_MIME_CONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_MAILNEWS_MIME_STREAM_CONVERTER_CID);
 
 ////////////////////////////////////////////////////////////////////////////////
 // mime emitter factories
 ////////////////////////////////////////////////////////////////////////////////
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimeRawEmitter)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimeXmlEmitter)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimePlainEmitter)
@@ -995,17 +992,16 @@ const mozilla::Module::CIDEntry kMailNew
   { &kNS_MAILDB_CID, false, NULL, nsMailDatabaseConstructor },
   { &kNS_NEWSDB_CID, false, NULL, nsNewsDatabaseConstructor },
   { &kNS_IMAPDB_CID, false, NULL, nsImapMailDatabaseConstructor },
   { &kNS_MSG_RETENTIONSETTINGS_CID, false, NULL, nsMsgRetentionSettingsConstructor },
   { &kNS_MSG_DOWNLOADSETTINGS_CID, false, NULL, nsMsgDownloadSettingsConstructor },
   { &kNS_MSGDB_SERVICE_CID, false, NULL, nsMsgDBServiceConstructor },
   // Mime Entries
   { &kNS_MIME_OBJECT_CLASS_ACCESS_CID, false, NULL, nsMimeObjectClassAccessConstructor },
-  { &kNS_MIME_CONVERTER_CID, false, NULL, nsMimeConverterConstructor },
   { &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID, false, NULL, nsStreamConverterConstructor },
   { &kNS_HTML_MIME_EMITTER_CID, false, NULL, nsMimeHtmlDisplayEmitterConstructor},
   { &kNS_XML_MIME_EMITTER_CID, false, NULL, nsMimeXmlEmitterConstructor},
   { &kNS_PLAIN_MIME_EMITTER_CID, false, NULL, nsMimePlainEmitterConstructor},
   { &kNS_RAW_MIME_EMITTER_CID, false, NULL, nsMimeRawEmitterConstructor},
   // Fts 3
   { &kNS_FTS3TOKENIZER_CID, false, NULL, nsFts3TokenizerConstructor },
   // News Entries
@@ -1219,17 +1215,16 @@ const mozilla::Module::ContractIDEntry k
   { NS_MAILBOXDB_CONTRACTID, &kNS_MAILDB_CID },
   { NS_NEWSDB_CONTRACTID, &kNS_NEWSDB_CID },
   { NS_IMAPDB_CONTRACTID, &kNS_IMAPDB_CID },
   { NS_MSG_RETENTIONSETTINGS_CONTRACTID, &kNS_MSG_RETENTIONSETTINGS_CID },
   { NS_MSG_DOWNLOADSETTINGS_CONTRACTID, &kNS_MSG_DOWNLOADSETTINGS_CID },
   { NS_MSGDB_SERVICE_CONTRACTID, &kNS_MSGDB_SERVICE_CID },
   // Mime Entries
   { NS_MIME_OBJECT_CONTRACTID, &kNS_MIME_OBJECT_CLASS_ACCESS_CID },
-  { NS_MIME_CONVERTER_CONTRACTID, &kNS_MIME_CONVERTER_CID },
   { NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID, &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID },
   { NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID1, &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID },
   { NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID2, &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID },
   { NS_HTML_MIME_EMITTER_CONTRACTID, &kNS_HTML_MIME_EMITTER_CID },
   { NS_XML_MIME_EMITTER_CONTRACTID, &kNS_XML_MIME_EMITTER_CID },
   { NS_PLAIN_MIME_EMITTER_CONTRACTID, &kNS_PLAIN_MIME_EMITTER_CID },
   { NS_RAW_MIME_EMITTER_CONTRACTID, &kNS_RAW_MIME_EMITTER_CID },
   // FTS3
--- a/mailnews/compose/src/nsURLFetcher.cpp
+++ b/mailnews/compose/src/nsURLFetcher.cpp
@@ -6,17 +6,16 @@
 #include "nsURLFetcher.h"
 
 #include "msgCore.h" // for pre-compiled headers
 #include "nsCOMPtr.h"
 #include <stdio.h>
 #include "nscore.h"
 #include "nsIFactory.h"
 #include "nsISupports.h"
-#include "comi18n.h"
 #include "prmem.h"
 #include "plstr.h"
 #include "nsIComponentManager.h"
 #include "nsStringGlue.h"
 #include "nsIIOService.h"
 #include "nsIChannel.h"
 #include "nsNetUtil.h"
 #include "nsMimeTypes.h"
--- a/mailnews/compose/test/unit/test_attachment.js
+++ b/mailnews/compose/test/unit/test_attachment.js
@@ -14,68 +14,72 @@ const input0 = " !\"#$%&'()*+,-./0123456
     "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"+
     "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"+
     "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff.txt"
 
 // ascii only
 const input1 = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"+
     "`abcdefghijklmnopqrstuvwxyz{|}~.txt"
 
-const expectedCD0 = "Content-Disposition: attachment;\r\n"+
-    " filename*0*=ISO-8859-1''%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F;\r\n"+
-    " filename*1*=%30%31%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F%40%41%42%43;\r\n"+
-    " filename*2*=%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57;\r\n"+
-    " filename*3*=%58%59%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68%69%6A%6B;\r\n"+
-    " filename*4*=%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%A0;\r\n"+
-    " filename*5*=%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4;\r\n"+
-    " filename*6*=%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8;\r\n"+
-    " filename*7*=%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC;\r\n"+
-    " filename*8*=%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0;\r\n"+
-    " filename*9*=%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF%2E%74%78%74\r\n";
+const expectedCD0 = ["Content-Disposition: attachment;",
+  " filename*0*=UTF-8''%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31;",
+  " filename*1*=%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F%40%41%42%43%44%45;",
+  " filename*2*=%46%47%48%49%4A%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59;",
+  " filename*3*=%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D;",
+  " filename*4*=%6E%6F%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%C2%A0%C2;",
+  " filename*5*=%A1%C2%A2%C2%A3%C2%A4%C2%A5%C2%A6%C2%A7%C2%A8%C2%A9%C2%AA%C2;",
+  " filename*6*=%AB%C2%AC%C2%AD%C2%AE%C2%AF%C2%B0%C2%B1%C2%B2%C2%B3%C2%B4%C2;",
+  " filename*7*=%B5%C2%B6%C2%B7%C2%B8%C2%B9%C2%BA%C2%BB%C2%BC%C2%BD%C2%BE%C2;",
+  " filename*8*=%BF%C3%80%C3%81%C3%82%C3%83%C3%84%C3%85%C3%86%C3%87%C3%88%C3;",
+  " filename*9*=%89%C3%8A%C3%8B%C3%8C%C3%8D%C3%8E%C3%8F%C3%90%C3%91%C3%92%C3;",
+  " filename*10*=%93%C3%94%C3%95%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%9B%C3%9C;",
+  " filename*11*=%C3%9D%C3%9E%C3%9F%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3;",
+  " filename*12*=%A6%C3%A7%C3%A8%C3%A9%C3%AA%C3%AB%C3%AC%C3%AD%C3%AE%C3%AF;",
+  " filename*13*=%C3%B0%C3%B1%C3%B2%C3%B3%C3%B4%C3%B5%C3%B6%C3%B7%C3%B8%C3;",
+  " filename*14*=%B9%C3%BA%C3%BB%C3%BC%C3%BD%C3%BE%C3%BF%2E%74%78%74",
+  ""].join("\r\n");
 
 const expectedCD1 = "Content-Disposition: attachment;\r\n"+
     ' filename*0=" !\\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ";\r\n'+
     ' filename*1="[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.txt"\r\n';
 
 const ParamFoldingPref = {
   RFC2047: 0,
   RFC2047WithCRLF: 1,
   RFC2231: 2
 }
 
 const expectedCTList0 = {
   RFC2047: 'Content-Type: text/plain; charset=US-ASCII;\r\n'+
-           ' name=" =?ISO-8859-1?Q?!=22=23=24=25=26=27=28=29*+=2C-=2E/0123456789=3A=3B=3C=3D?='+
-           '=?ISO-8859-1?Q?=3E=3F=40ABCDEFGHIJKLMNOPQRSTUVWXYZ=5B=5C=5D=5E=5F=60abcd?='+
-           '=?ISO-8859-1?Q?efghijklmnopqrstuvwxyz=7B=7C=7D=7E=A0=A1=A2=A3=A4=A5=A6=A7?='+
-           '=?ISO-8859-1?Q?=A8=A9=AA=AB=AC=AD=AE=AF=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA?='+
-           '=?ISO-8859-1?Q?=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=C6=C7=C8=C9=CA=CB=CC=CD?='+
-           '=?ISO-8859-1?Q?=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=DF=E0?='+
-           '=?ISO-8859-1?Q?=E1=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3?='+
-           '=?ISO-8859-1?Q?=F4=F5=F6=F7=F8=F9=FA=FB=FC=FD=FE=FF=2Etxt?="\r\n',
+           ' name="=?UTF-8?Q?_!=22#$%&\'=28=29*+,-./0123456789:;<=3d>=3f@ABCDEFGHIJKLMNO?='+
+           '=?UTF-8?Q?PQRSTUVWXYZ[\\\\]^=5f`abcdefghijklmnopqrstuvwxyz{|}~=c2=a0?='+
+           '=?UTF-8?B?wqHCosKjwqTCpcKmwqfCqMKpwqrCq8Kswq3CrsKvwrDCscKywrPCtMK1?='+
+           '=?UTF-8?B?wrbCt8K4wrnCusK7wrzCvcK+wr/DgMOBw4LDg8OEw4XDhsOHw4jDicOK?='+
+           '=?UTF-8?B?w4vDjMONw47Dj8OQw5HDksOTw5TDlcOWw5fDmMOZw5rDm8Ocw53DnsOf?='+
+           '=?UTF-8?B?w6DDocOiw6PDpMOlw6bDp8Oow6nDqsOrw6zDrcOuw6/DsMOxw7LDs8O0?='+
+           '=?UTF-8?B?w7XDtsO3w7jDucO6w7vDvMO9w77Dvy50eHQ=?="\r\n',
 
   RFC2047WithCRLF: 'Content-Type: text/plain; charset=US-ASCII;\r\n'+
-                   ' name=" =?ISO-8859-1?Q?!=22=23=24=25=26=27=28=29*+=2C-=2E/0123456789=3A=3B=3C=3D?=\r\n'+
-                   ' =?ISO-8859-1?Q?=3E=3F=40ABCDEFGHIJKLMNOPQRSTUVWXYZ=5B=5C=5D=5E=5F=60abcd?=\r\n'+
-                   ' =?ISO-8859-1?Q?efghijklmnopqrstuvwxyz=7B=7C=7D=7E=A0=A1=A2=A3=A4=A5=A6=A7?=\r\n'+
-                   ' =?ISO-8859-1?Q?=A8=A9=AA=AB=AC=AD=AE=AF=B0=B1=B2=B3=B4=B5=B6=B7=B8=B9=BA?=\r\n'+
-                   ' =?ISO-8859-1?Q?=BB=BC=BD=BE=BF=C0=C1=C2=C3=C4=C5=C6=C7=C8=C9=CA=CB=CC=CD?=\r\n'+
-                   ' =?ISO-8859-1?Q?=CE=CF=D0=D1=D2=D3=D4=D5=D6=D7=D8=D9=DA=DB=DC=DD=DE=DF=E0?=\r\n'+
-                   ' =?ISO-8859-1?Q?=E1=E2=E3=E4=E5=E6=E7=E8=E9=EA=EB=EC=ED=EE=EF=F0=F1=F2=F3?=\r\n'+
-                   ' =?ISO-8859-1?Q?=F4=F5=F6=F7=F8=F9=FA=FB=FC=FD=FE=FF=2Etxt?="\r\n',
+                   ' name="=?UTF-8?Q?_!=22#$%&\'=28=29*+,-./0123456789:;<=3d>=3f@ABCDEFGHIJKLMNO?=\r\n'+
+                   ' =?UTF-8?Q?PQRSTUVWXYZ[\\\\]^=5f`abcdefghijklmnopqrstuvwxyz{|}~=c2=a0?=\r\n'+
+                   ' =?UTF-8?B?wqHCosKjwqTCpcKmwqfCqMKpwqrCq8Kswq3CrsKvwrDCscKywrPCtMK1?=\r\n'+
+                   ' =?UTF-8?B?wrbCt8K4wrnCusK7wrzCvcK+wr/DgMOBw4LDg8OEw4XDhsOHw4jDicOK?=\r\n'+
+                   ' =?UTF-8?B?w4vDjMONw47Dj8OQw5HDksOTw5TDlcOWw5fDmMOZw5rDm8Ocw53DnsOf?=\r\n'+
+                   ' =?UTF-8?B?w6DDocOiw6PDpMOlw6bDp8Oow6nDqsOrw6zDrcOuw6/DsMOxw7LDs8O0?=\r\n'+
+                   ' =?UTF-8?B?w7XDtsO3w7jDucO6w7vDvMO9w77Dvy50eHQ=?="\r\n',
 
   RFC2231: 'Content-Type: text/plain; charset=US-ASCII\r\n'
 }
 
 const expectedCTList1 = {
   RFC2047: 'Content-Type: text/plain; charset=US-ASCII;\r\n'+
-           ' name=" !\\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.txt"\r\n',
+           ' name="!\\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.txt"\r\n',
 
   RFC2047WithCRLF: 'Content-Type: text/plain; charset=US-ASCII;\r\n'+
-                   ' name=" !\\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.txt"\r\n',
+                   ' name="\r\n !\\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.txt"\r\n',
 
   RFC2231: 'Content-Type: text/plain; charset=US-ASCII\r\n'
 }
 
 function checkAttachment(expectedCD, expectedCT) {
   let msgData = mailTestUtils
     .loadMessageToString(gDraftFolder, mailTestUtils.firstMsgHdr(gDraftFolder));
   let pos = msgData.indexOf("Content-Disposition:");
@@ -126,21 +130,11 @@ function testInput1() {
 }
 
 var tests = [
   testInput0,
   testInput1
 ]
 
 function run_test() {
-  // This test assumes mailnews.send_default_charset ISO-8859-1...
-  let str = Components.classes["@mozilla.org/pref-localizedstring;1"]
-                      .createInstance(Components.interfaces.nsIPrefLocalizedString);
-  str.data = "ISO-8859-1";
-  Services.prefs.setComplexValue("mailnews.send_default_charset",
-                                 Components.interfaces.nsIPrefLocalizedString, str);
-  do_register_cleanup(function() {
-    Services.prefs.clearUserPref("mailnews.send_default_charset");
-  });
-
   localAccountUtils.loadLocalMailAccount();
   async_run_tests(tests);
 }
--- a/mailnews/mime/jsmime/jsmime.js
+++ b/mailnews/mime/jsmime/jsmime.js
@@ -2806,16 +2806,19 @@ HeaderEmitter.prototype.addAddresses = f
  * Add an unstructured header value to the output. This effectively means only
  * inserting line breaks were necessary, and using RFC 2047 encoding where
  * necessary.
  *
  * @public
  * @param {String} text The text to add to the output.
  */
 HeaderEmitter.prototype.addUnstructured = function (text) {
+  if (text.length == 0)
+    return;
+
   // Unstructured text is basically a phrase that can't be quoted. So, if we
   // have nothing in qchars, nothing should be quoted.
   this.addPhrase(text, "", false);
 };
 
 /**
  * Signal that the current header has been finished encoding.
  *
--- a/mailnews/mime/public/nsIMimeConverter.idl
+++ b/mailnews/mime/public/nsIMimeConverter.idl
@@ -6,43 +6,42 @@
 #include "nsISupports.idl"
 
 /**
  * Encode/decode mail headers (via libmime).
  */
 [scriptable, uuid(0d3f5531-2dbe-40d3-9280-f6ac45a6f5e0)]
 interface nsIMimeConverter : nsISupports {
   /**
-   * Suggested byte length limit for use when calling
-   * encodeMimePartIIStr(_UTF8).
+   * Suggested byte length limit for use when calling encodeMimePartIIStr_UTF8.
    */
   const long MIME_ENCODED_WORD_SIZE = 72;
   const long MAX_CHARSET_NAME_LENGTH = 64;
 
   /**
-   * Encode a UTF-8 CString into RFC 2047 form ("=?" charset "?" encoding "?"
-   * encoded-text "?=", where encoding is either "B" for BASE64 (RFC 2045) or
-   * "Q" for quoted-printable-ish (RFC 2045)).
+   * Encode a UTF-8 string into a form containing only ASCII characters using
+   * RFC 2047 encoded words where necessary.
+   *
+   * Note that, although allowed for the present time, encoding to charsets
+   * other than UTF-8 is considered deprecated.
    *
-   * @param header UTF-8 header to encode.
-   * @param structured Is the header's field-body a "structured" field?
-   *     (Encoded words are only allowed in comment/phrase portions of
-   *     structured field bodies.)
-   * @param mailCharset Charset name to convert (as an ASCII C string).
-   * @param fieldnamelen Header field name lengt (ex: "From: " = 6)
-   * @param encodedWordSize Byte length limit of the output, usually 72. (Use
-   *     MIME_ENCODED_WORD_SIZE.)
+   * @param aHeader           UTF-8 header to encode.
+   * @param aAddressingHeader Is the header a list of email addresses?
+   * @param aMailCharset      Charset to use when encoding (see above for note).
+   * @param aFieldNameLen     Header field name length (ex: "From: " = 6)
+   * @param aMaxLineLen       Maximum length of an individual line. Use
+   *                          MIME_ENCODED_WORD_SIZE for best results.
    *
-   * @return The encoded buffer (as a C string).
+   * @return                  The encoded header.
    */
-  AUTF8String encodeMimePartIIStr_UTF8(in AUTF8String header,
-                                       in boolean     structured,
-                                       in string      mailCharset,
-                                       in long        fieldnamelen,
-                                       in long        encodedWordSize);
+  AUTF8String encodeMimePartIIStr_UTF8(in AUTF8String aHeader,
+                                       in boolean     aAddressingHeader,
+                                       in string      aMailCharset,
+                                       in long        aFieldNameLen,
+                                       in long        aMaxLineLen);
 
   /**
    * Decode a MIME header to UTF-8 if conversion is required.  Marked as
    * noscript because the return value may contain non-ASCII characters.
    *
    * @param header A (possibly encoded) header to decode.
    * @param default_charset The charset to apply to un-labeled non-UTF-8 data.
    * @param override_charset If true, default_charset is used instead of any
--- a/mailnews/mime/public/nsMsgMimeCID.h
+++ b/mailnews/mime/public/nsMsgMimeCID.h
@@ -17,21 +17,16 @@
 
 #define NS_MAILNEWS_MIME_STREAM_CONVERTER_CID                    \
 { /* FAF4F9A6-60AD-11d3-989A-001083010E9B */         \
  0xfaf4f9a6, 0x60ad, 0x11d3, { 0x98, 0x9a, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b } }
 
 #define NS_MIME_CONVERTER_CONTRACTID \
   "@mozilla.org/messenger/mimeconverter;1"
 
-// {866A1E11-D0B9-11d2-B373-525400E2D63A}
-#define NS_MIME_CONVERTER_CID   \
-        { 0x866a1e11, 0xd0b9, 0x11d2,         \
-        { 0xb3, 0x73, 0x52, 0x54, 0x0, 0xe2, 0xd6, 0x3a } }
-
 // {403B0540-B7C3-11d2-B35E-525400E2D63A}
 #define NS_MIME_OBJECT_CLASS_ACCESS_CID   \
         { 0x403b0540, 0xb7c3, 0x11d2,         \
         { 0xb3, 0x5e, 0x52, 0x54, 0x0, 0xe2, 0xd6, 0x3a } }
 
 #define NS_MIME_OBJECT_CONTRACTID \
   "@mozilla.org/messenger/mimeobject;1"
 
--- a/mailnews/mime/src/comi18n.cpp
+++ b/mailnews/mime/src/comi18n.cpp
@@ -1,687 +1,24 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsICharsetConverterManager.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include "prmem.h"
-#include "prlog.h"
-#include "prprf.h"
-#include "plstr.h"
 #include "comi18n.h"
 #include "nsIStringCharsetDetector.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
 #include "nsMsgUtils.h"
-#include "mimebuf.h"
-#include "nsIMimeConverter.h"
-#include "nsMsgI18N.h"
-#include "nsMimeTypes.h"
 #include "nsICharsetConverterManager.h"
-#include "nsISaveAsCharset.h"
-#include "mimehdrs.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsNetCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsComponentManagerUtils.h"
-#include "nsMemory.h"
 
 
 ////////////////////////////////////////////////////////////////////////////////
-
-static char basis_64[] =
-   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-#define NO_Q_ENCODING_NEEDED(ch)  \
-  (((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') || \
-   ((ch) >= '0' && (ch) <= '9') ||  (ch) == '!' || (ch) == '*' ||  \
-    (ch) == '+' || (ch) == '-' || (ch) == '/')
-
-static const char hexdigits[] = "0123456789ABCDEF";
-
-static int32_t
-intlmime_encode_q(const unsigned char *src, int32_t srcsize, char *out)
-{
-  const unsigned char *in = (unsigned char *) src;
-  const unsigned char *end = in + srcsize;
-  char *head = out;
-
-  for (; in < end; in++) {
-    if (NO_Q_ENCODING_NEEDED(*in)) {
-      *out++ = *in;
-    }
-    else if (*in == ' ') {
-      *out++ = '_';
-    }
-    else {
-      *out++ = '=';
-      *out++ = hexdigits[*in >> 4];
-      *out++ = hexdigits[*in & 0xF];
-    }
-  }
-  *out = '\0';
-  return (out - head);
-}
-
-static void
-encodeChunk(const unsigned char* chunk, char* output)
-{
-  register int32_t offset;
-
-  offset = *chunk >> 2;
-  *output++ = basis_64[offset];
-
-  offset = ((*chunk << 4) & 0x30) + (*(chunk+1) >> 4);
-  *output++ = basis_64[offset];
-
-  if (*(chunk+1)) {
-    offset = ((*(chunk+1) & 0x0f) << 2) + ((*(chunk+2) & 0xc0) >> 6);
-    *output++ = basis_64[offset];
-  }
-  else
-    *output++ = '=';
-
-  if (*(chunk+2)) {
-    offset = *(chunk+2) & 0x3f;
-    *output++ = basis_64[offset];
-  }
-  else
-    *output++ = '=';
-}
-
-static int32_t
-intlmime_encode_b(const unsigned char* input, int32_t inlen, char* output)
-{
-  unsigned char  chunk[3];
-  int32_t   i, len;
-  char *head = output;
-
-  for (len = 0; inlen >=3 ; inlen -= 3) {
-    for (i = 0; i < 3; i++)
-      chunk[i] = *input++;
-    encodeChunk(chunk, output);
-    output += 4;
-    len += 4;
-  }
-
-  if (inlen > 0) {
-    for (i = 0; i < inlen; i++)
-      chunk[i] = *input++;
-    for (; i < 3; i++)
-      chunk[i] = 0;
-    encodeChunk(chunk, output);
-    output += 4;
-  }
-
-  *output = 0;
-  return (output - head);
-}
-
-
-/*      some utility function used by this file */
-static bool intlmime_only_ascii_str(const char *s)
-{
-  for(; *s; s++)
-    if(*s & 0x80)
-      return false;
-  return true;
-}
-
-
-#define IS_UTF8_HEADER(s, h) ((*(s) & (~(~(h) >> 1))) == (h))
-#define IS_UTF8_SUBBYTE(s) ((*(s) & 0xC0) == 0x80)
-static unsigned char * utf8_nextchar(unsigned char *str)
-{
-  if (*str < 0x80)
-    return (str + 1);
-  if (IS_UTF8_HEADER(str, 0xC0) &&
-      IS_UTF8_SUBBYTE(str + 1))
-    return (str + 2);
-  if (IS_UTF8_HEADER(str, 0xE0) &&
-      IS_UTF8_SUBBYTE(str + 1) &&
-      IS_UTF8_SUBBYTE(str + 2) )
-    return (str + 3);
-  if (IS_UTF8_HEADER(str, 0xF0) &&
-      IS_UTF8_SUBBYTE(str + 1) &&
-      IS_UTF8_SUBBYTE(str + 2) &&
-      IS_UTF8_SUBBYTE(str + 3) )
-    return (str + 4);
-  // error, return + 1 to avoid infinite loop
-  return (str + 1); 
-}
-#undef IS_UTF8_HEADER
-#undef IS_UTF8_SUBBYTE
-
-/* -------------- */
-
-static
-int32_t generate_encodedwords(char *pUTF8, const char *charset, char method, char *output, int32_t outlen, int32_t output_carryoverlen, int32_t foldlen, bool foldingonly)
-{
-  nsCOMPtr <nsISaveAsCharset> conv;
-  char16_t *_pUCS2 = nullptr, *pUCS2 = nullptr, *pUCS2Head = nullptr, cUCS2Tmp = 0;
-  char  *ibuf, *o = output;
-  char  encodedword_head[nsIMimeConverter::MAX_CHARSET_NAME_LENGTH+4+1];
-  nsAutoCString _charset;
-  char  *pUTF8Head = nullptr, cUTF8Tmp = 0;
-  int32_t   olen = 0, obufsize = outlen, offset, linelen = output_carryoverlen, convlen = 0;
-  int32_t   encodedword_headlen = 0, encodedword_taillen = foldingonly ? 0 : 2; // "?="
-  nsresult rv;
-
-  encodedword_head[0] = 0;
-
-  if (!foldingonly) {
-
-    // Deal with UCS2 pointer
-    pUCS2 = _pUCS2 = ToNewUnicode(NS_ConvertUTF8toUTF16(pUTF8));
-    if (!pUCS2)
-      return -1;
-
-    // Resolve charset alias
-    {
-      nsCOMPtr<nsICharsetConverterManager> ccm =
-        do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
-
-      if (NS_SUCCEEDED(rv)) {
-        charset = !PL_strcasecmp(charset, "us-ascii") ? "ISO-8859-1" : charset;
-        rv = ccm->GetCharsetAlias(charset, _charset);
-      }
-      if (NS_FAILED(rv)) {
-        if (_pUCS2)
-          nsMemory::Free(_pUCS2);
-        return -1;
-      }
-
-      // this is so nasty, but _charset won't be going away..
-      charset = _charset.get();
-    }
-
-    // Prepare MIME encoded-word head with official charset name
-    if (!PR_snprintf(encodedword_head, sizeof(encodedword_head)-1, "=?%s?%c?", charset, method)) {
-      if (_pUCS2)
-        nsMemory::Free(_pUCS2);
-      return -1;
-    }
-    encodedword_headlen = strlen(encodedword_head);
-
-    // Create an instance of charset converter and initialize it
-    conv = do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID, &rv);
-    if(NS_SUCCEEDED(rv)) {
-      rv = conv->Init(charset,
-                       nsISaveAsCharset::attr_FallbackQuestionMark + nsISaveAsCharset::attr_EntityAfterCharsetConv,
-                       nsIEntityConverter::transliterate);
-    }
-    if (NS_FAILED(rv)) {
-      if (_pUCS2)
-        nsMemory::Free(_pUCS2);
-      return -1;
-    }
-  } // if (!foldingonly)
-
-  /*
-     See if folding needs to happen.
-     If carried over length is already too long to hold
-     encoded-word header and trailer length, it's too obvious
-     that we need to fold.  So, don't waste time for calculation.
-  */
-  if (linelen + encodedword_headlen + encodedword_taillen < foldlen) {
-    if (foldingonly) {
-      offset = strlen(pUTF8Head = pUTF8);
-      pUTF8 += offset;
-    }
-    else {
-      rv = conv->Convert(pUCS2, &ibuf);
-      if (NS_FAILED(rv) || ibuf == nullptr) {
-        if (_pUCS2)
-          nsMemory::Free(_pUCS2);
-        return -1; //error
-      }
-      if (method == 'B') {
-        /* 4 / 3 = B encoding multiplier */
-        offset = strlen(ibuf) * 4 / 3;
-      }
-      else {
-        /* 3 = Q encoding multiplier */
-        offset = 0;
-        for (int32_t i = 0; *(ibuf+i); i++)
-          offset += NO_Q_ENCODING_NEEDED(*(ibuf+i)) ? 1 : 3;
-      }
-    }
-    if (linelen + encodedword_headlen + offset + encodedword_taillen > foldlen) {
-      /* folding has to happen */
-      if (foldingonly) {
-        pUTF8 = pUTF8Head;
-        pUTF8Head = nullptr;
-      }
-      else
-        PR_Free(ibuf);
-    }
-    else {
-      /* no folding needed, let's fall thru */
-      PL_strncpyz(o, encodedword_head, obufsize);
-      olen += encodedword_headlen;
-      linelen += encodedword_headlen;
-      obufsize -= encodedword_headlen;
-      o += encodedword_headlen;
-      if (!foldingonly)
-        *pUCS2 = 0;
-    }
-  }
-  else {
-    PL_strncpyz(o, "\r\n ", obufsize);
-    olen += 3;
-    o += 3;
-    obufsize -= 3;
-    linelen = 1;
-  }
-
-  /*
-    Let's do the nasty RFC-2047 & folding stuff
-  */
-
-  while ((foldingonly ? *pUTF8 : *pUCS2) && (olen < outlen)) {
-    PL_strncpyz(o, encodedword_head, obufsize);
-    olen += encodedword_headlen;
-    linelen += encodedword_headlen;
-    obufsize -= encodedword_headlen;
-    o += encodedword_headlen;
-    olen += encodedword_taillen;
-    if (foldingonly)
-      pUTF8Head = pUTF8;
-    else
-      pUCS2Head = pUCS2;
-
-    while ((foldingonly ? *pUTF8 : *pUCS2) && (olen < outlen)) {
-      if (foldingonly) {
-        ++pUTF8;
-        for (;;) {
-          if (*pUTF8 == ' ' || *pUTF8 == '\t' || !*pUTF8) {
-            offset = pUTF8 - pUTF8Head;
-            cUTF8Tmp = *pUTF8;
-            *pUTF8 = 0;
-            break;
-          }
-          ++pUTF8;
-        }
-      }
-      else {
-        convlen = ++pUCS2 - pUCS2Head;
-        cUCS2Tmp = *(pUCS2Head + convlen);
-        *(pUCS2Head + convlen) = 0;
-        rv = conv->Convert(pUCS2Head, &ibuf);
-        *(pUCS2Head + convlen) = cUCS2Tmp;
-        if (NS_FAILED(rv) || ibuf == nullptr) {
-          if (_pUCS2)
-            nsMemory::Free(_pUCS2);
-          return -1; //error
-        }
-        if (method == 'B') {
-          /* 4 / 3 = B encoding multiplier */
-          offset = strlen(ibuf) * 4 / 3;
-        }
-        else {
-          /* 3 = Q encoding multiplier */
-          offset = 0;
-          for (int32_t i = 0; *(ibuf+i); i++)
-            offset += NO_Q_ENCODING_NEEDED(*(ibuf+i)) ? 1 : 3;
-        }
-      }
-      if (linelen + offset > foldlen) {
-process_lastline:
-        int32_t enclen;
-        if (foldingonly) {
-          PL_strncpyz(o, pUTF8Head, obufsize);
-          enclen = strlen(o);
-          obufsize -= enclen;
-          o += enclen;
-          *pUTF8 = cUTF8Tmp;
-        }
-        else {
-          if (method == 'B')
-            enclen = intlmime_encode_b((const unsigned char *)ibuf, strlen(ibuf), o);
-          else
-            enclen = intlmime_encode_q((const unsigned char *)ibuf, strlen(ibuf), o);
-          PR_Free(ibuf);
-          o += enclen;
-          obufsize -= enclen;
-          PL_strncpyz(o, "?=", obufsize);
-        }
-        o += encodedword_taillen;
-        obufsize -= encodedword_taillen;
-        olen += enclen;
-        if (foldingonly ? *pUTF8 : *pUCS2) { /* not last line */
-          PL_strncpyz(o, "\r\n ", obufsize);
-          obufsize -= 3;
-          o += 3;
-          olen += 3;
-          linelen = 1;
-          if (foldingonly) {
-            pUTF8Head = nullptr;
-            if (*pUTF8 == ' ' || *pUTF8 == '\t') {
-              ++pUTF8;
-              if (!*pUTF8)
-                return 0;
-            }
-          }
-        }
-        else {
-          if (_pUCS2)
-            nsMemory::Free(_pUCS2);
-          return linelen + enclen + encodedword_taillen;
-        }
-        break;
-      }
-      else {
-        if (foldingonly)
-          *pUTF8 = cUTF8Tmp;
-        else {
-          if (*pUCS2)
-            PR_Free(ibuf);
-        }
-      }
-    }
-  }
-
-  goto process_lastline;
-}
-
-typedef struct _RFC822AddressList {
-  char        *displayname;
-  bool        asciionly;
-  char        *addrspec;
-  struct _RFC822AddressList *next;
-} RFC822AddressList;
-
-static
-void destroy_addresslist(RFC822AddressList *p)
-{
-  if (p->next)
-    destroy_addresslist(p->next);
-  PR_FREEIF(p->displayname);
-  PR_FREEIF(p->addrspec);
-  PR_Free(p);
-  return;
-}
-
-static
-RFC822AddressList * construct_addresslist(char *s)
-{
-  bool    quoted = false, angle_addr = false;
-  int32_t  comment = 0;
-  char *displayname = nullptr, *addrspec = nullptr;
-  static RFC822AddressList  listinit;
-  RFC822AddressList  *listhead = (RFC822AddressList *)PR_Malloc(sizeof(RFC822AddressList));
-  RFC822AddressList  *list = listhead;
-
-  if (!list)
-    return nullptr;
-
-  while (*s == ' ' || *s == '\t')
-    ++s;
-
-  for (*list = listinit; *s; ++s) {
-    if (*s == '\\') {
-      if (quoted || comment) {
-        ++s;
-        continue;
-      }
-    }
-    else if (*s == '(' || *s == ')') {
-      if (!quoted) {
-        if (*s == '(') {
-          if (comment++ == 0)
-            displayname = s + 1;
-        }
-        else {
-          if (--comment == 0) {
-            *s = '\0';
-            PR_FREEIF(list->displayname);
-            list->displayname = displayname ? strdup(displayname) : nullptr;
-            list->asciionly = intlmime_only_ascii_str(displayname);
-            *s = ')';
-          }
-        }
-        continue;
-      }
-    }
-    else if (*s == '"') {
-      if (!comment && !angle_addr) {
-        quoted = !quoted;
-        if (quoted)
-          displayname = s;
-        else {
-          char tmp = *(s+1);
-          *(s+1) = '\0';
-          PR_FREEIF(list->displayname);
-          list->displayname = displayname ? strdup(displayname) : nullptr;
-          list->asciionly = intlmime_only_ascii_str(displayname);
-          *(s+1) = tmp;
-        }
-        continue;
-      }
-    }
-    else if (*s == '<' || *s == '>') {
-      if (!quoted && !comment) {
-        if (*s == '<') {
-          angle_addr = true;
-          addrspec = s;
-          if (displayname) {
-            char *e = s - 1, tmp;
-            while (*e == '\t' || *e == ' ')
-              --e;
-            tmp = *++e;
-            *e = '\0';
-            PR_FREEIF(list->displayname);
-            list->displayname = displayname ? strdup(displayname) : nullptr;
-            list->asciionly = intlmime_only_ascii_str(displayname);
-            *e = tmp;
-          }
-        }
-        else {
-          char tmp;
-          angle_addr = false;
-          tmp = *(s+1);
-          *(s+1) = '\0';
-          PR_FREEIF(list->addrspec);
-          list->addrspec = addrspec ? strdup(addrspec) : nullptr;
-          *(s+1) = tmp;
-        }
-        continue;
-      }
-    }
-    if (!quoted && !comment && !angle_addr) {
-      /* address-list separator. end of this address */
-      if (*s == ',') {
-        /* deal with addr-spec only address */
-        if (!addrspec && displayname) {
-          *s = '\0';
-          list->addrspec = strdup(displayname);
-          /* and don't forget to free the display name in the list, in that case it's bogus */
-          PR_FREEIF(list->displayname);
-        }
-        /* prepare for next address */
-        addrspec = displayname = nullptr;
-        list->next = (RFC822AddressList *)PR_Malloc(sizeof(RFC822AddressList));
-        list = list->next;
-        *list = listinit;
-        /* eat spaces */
-        ++s;
-        while (*s == ' ' || *s == '\t')
-          ++s;
-        if (*s == '\r' && *(s+1) == '\n' && (*(s+2) == ' ' || *(s+2) == '\t'))
-          s += 2;
-        else
-          --s;
-      }
-      else if (!displayname && *s != ' ' && *s != '\t')
-        displayname = s;
-    }
-  }
-
-  /* deal with addr-spec only address comes at last */
-  if (!addrspec && displayname)
-  {
-    list->addrspec = strdup(displayname);
-    /* and don't forget to free the display name in the list, in that case it's bogus */
-    PR_FREEIF(list->displayname);
-  }
-
-  return listhead;
-}
-
-static
-char * apply_rfc2047_encoding(const char *_src, bool structured, const char *charset, int32_t cursor, int32_t foldlen)
-{
-  RFC822AddressList  *listhead, *list;
-  int32_t   outputlen, usedlen;
-  char  *src, *src_head, *output, *outputtail;
-  char  method = nsMsgI18Nmultibyte_charset(charset) ? 'B' : 'Q';
-
-  if (!_src)
-    return nullptr;
-
-  //<TAB>=?<charset>?<B/Q>?...?=<CRLF>
-  int32_t perLineOverhead = strlen(charset) + 10;
-
-  if (perLineOverhead >= foldlen || (src = src_head = strdup(_src)) == nullptr)
-    return nullptr;
-
-  /* allocate enough buffer for conversion, this way it can avoid
-     do another memory allocation which is expensive
-   */
-  int32_t encodedCharsPerLine = foldlen - perLineOverhead;
-  int32_t maxNumLines = (strlen(src) * 4 / encodedCharsPerLine) + 1;
-  outputlen = strlen(src) * 4 + (maxNumLines * perLineOverhead) + 20 /* fudge */;
-  if ((outputtail = output = (char *)PR_Malloc(outputlen)) == nullptr) {
-    PR_Free(src_head);
-    return nullptr;
-  }
-
-  if (structured) {
-    listhead = list = construct_addresslist(src);
-    if (!list) {
-      PR_Free(output);
-      output = nullptr;
-    }
-    else {
-      for (; list && (outputlen > 0); list = list->next) {
-        if (list->displayname) {
-          if (list->asciionly && list->addrspec) {
-            int32_t len = cursor + strlen(list->displayname) + strlen(list->addrspec);
-            if (foldlen < len && len < 998) { /* see RFC 2822 for magic number 998 */
-              if (!PR_snprintf(outputtail, outputlen - 1, 
-                              (list == listhead || cursor == 1) ? "%s %s%s" : "\r\n %s %s%s", 
-                              list->displayname, list->addrspec, list->next ? ",\r\n " : ""))
-              {
-                PR_Free(output);
-                return nullptr;
-              }
-              usedlen = strlen(outputtail);
-              outputtail += usedlen;
-              outputlen -= usedlen;
-              cursor = 1;
-              continue;
-            }
-          }
-          cursor = generate_encodedwords(list->displayname, charset, method, outputtail, outputlen, cursor, foldlen, list->asciionly);
-          if (cursor < 0) {
-            PR_Free(output);
-            output = nullptr;
-            break;
-          }
-          usedlen = strlen(outputtail);
-          outputtail += usedlen;
-          outputlen -= usedlen;
-        }
-        if (list->addrspec) {
-          usedlen = strlen(list->addrspec);
-          if (cursor + usedlen > foldlen) {
-            if (!PR_snprintf(outputtail, outputlen - 1, "\r\n %s", list->addrspec)) {
-              PR_Free(output);
-              destroy_addresslist(listhead);
-              return nullptr;
-            }
-            usedlen += 3;         /* FWS + addr-spec */
-            cursor = usedlen - 2; /* \r\n */
-          }
-          else {
-            if (!PR_snprintf(outputtail, outputlen - 1, list->displayname ? " %s" : "%s", list->addrspec)) {
-              PR_Free(output);
-              destroy_addresslist(listhead);
-              return nullptr;
-            }
-            if (list->displayname)
-              usedlen++;
-            cursor += usedlen;
-          }
-          outputtail += usedlen;
-          outputlen -= usedlen;
-        }
-        else {
-          PR_Free(output);
-          output = nullptr;
-          break;
-        }
-        if (list->next) {
-          PL_strncpyz(outputtail, ", ", outputlen);
-          cursor += 2;
-          outputtail += 2;
-          outputlen -= 2;
-        }
-      }
-      destroy_addresslist(listhead);
-    }
-  }
-  else {
-    char *spacepos = nullptr, *org_output = output;
-    /* show some mercy to stupid ML systems which don't know
-       how to respect MIME encoded subject */
-    for (char *p = src; *p && !(*p & 0x80); p++) {
-      if (*p == 0x20 || *p == '\t')
-        spacepos = p;
-    }
-    if (spacepos) {
-      char head[nsIMimeConverter::MAX_CHARSET_NAME_LENGTH+4+1];
-      int32_t  overhead, skiplen;
-      if (!PR_snprintf(head, sizeof(head) - 1, "=?%s?%c?", charset, method)) {
-        PR_Free(output);
-        return nullptr;
-      }
-      overhead = strlen(head) + 2 + 4; // 2 : "?=", 4 : a B-encoded chunk
-      skiplen = spacepos + 1 - src;
-      if (cursor + skiplen + overhead < foldlen) {
-        char tmp = *(spacepos + 1);
-        *(spacepos + 1) = '\0';
-        PL_strncpyz(output, src, outputlen);
-        output += skiplen;
-        outputlen -= skiplen;
-        cursor += skiplen;
-        src += skiplen;
-        *src = tmp;
-      }
-    }
-    bool asciionly = intlmime_only_ascii_str(src);
-    if (generate_encodedwords(src, charset, method, output, outputlen, cursor, foldlen, asciionly) < 0) {
-      PR_Free(org_output);
-      org_output = nullptr;
-    }
-    output = org_output;
-  }
-
-  PR_Free(src_head);
-
-  return output;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // BEGIN PUBLIC INTERFACE
 extern "C" {
 
 
 void MIME_DecodeMimeHeader(const char *header, const char *default_charset,
                            bool override_charset, bool eatContinuations,
                            nsACString &result)
 {
@@ -691,28 +28,17 @@ void MIME_DecodeMimeHeader(const char *h
   {
     result.Truncate();
     return;
   }
   mimehdrpar->DecodeRFC2047Header(header, default_charset, override_charset,
                                   eatContinuations, result);
 }
 
-char *MIME_EncodeMimePartIIStr(const char* header, bool structured, const char* mailCharset, const int32_t fieldNameLen, const int32_t encodedWordSize)
-{
-  return apply_rfc2047_encoding(header, structured, mailCharset, fieldNameLen, encodedWordSize);
-}
-
 // UTF-8 utility functions.
-
-char * NextChar_UTF8(char *str)
-{
-  return (char *) utf8_nextchar((unsigned char *) str);
-}
-
 //detect charset soly based on aBuf. return in aCharset
 nsresult
 MIME_detect_charset(const char *aBuf, int32_t aLength, const char** aCharset)
 {
   nsresult res = NS_ERROR_UNEXPECTED;
   nsString detector_name;
   *aCharset = nullptr;
 
--- a/mailnews/mime/src/comi18n.h
+++ b/mailnews/mime/src/comi18n.h
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _COMI18N_LOADED_H_
 #define _COMI18N_LOADED_H_
 
 #include "msgCore.h"
 
 class nsIUnicodeDecoder;
 class nsIUnicodeEncoder;
-class nsIStringCharsetDetector;
 
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
 /**
  * Decode MIME header to UTF-8.
@@ -26,42 +25,16 @@ extern "C" {
  * @param override_charset    [IN] If true, default_charset used instead of any charset labeling other than UTF-8
  * @param eatContinuations    [IN] If true, unfold headers
  * @param result      [OUT] Decoded buffer
  */
 void MIME_DecodeMimeHeader(const char *header, const char *default_charset,
                            bool override_charset, bool eatContinuations,
                            nsACString &result);
 
-/**
- * Encode an input string into RFC 2047 form.
- * This is a replacement for INTL_EncodeMimePartIIStr.
- * Unlike INTL_EncodeMimePartIIStr, this does not apply any charset conversion.
- * Use MIME_ConvertCharset in advance if the encoding string needs a conversion.
- *
- *
- * @param header          [IN] A header to encode (utf-8 Cstring).
- * @param structured      [IN] A boolean to swtich between structured field body and non-structured field body.
- * @param mailCharset     [IN] Charset name (in C string) to convert.
- * @param fieldNameLen    [IN] Header field name length (e.g. "From: " -> 6)
- * @param encodedWordSize [IN] Byte length limit of the output, ususally 72 (use kMIME_ENCODED_WORD_SIZE).
- * @return            Encoded buffer (in C string) or NULL in case of error.
- */
-char *MIME_EncodeMimePartIIStr(const char *header, bool structured, const char* mailCharset, const int32_t fieldNameLen, const int32_t encodedWordSize);
-
-/**
- * Get a next character position in an UTF-8 string.
- * Example: s = NextChar_UTF8(s);  // get a pointer for the next character
- *
- *
- * @param str          [IN] An input C string (UTF-8).
- * @return             A pointer to the next character.
- */
-char * NextChar_UTF8(char *str);
-
 nsresult MIME_detect_charset(const char *aBuf, int32_t aLength, const char** aCharset);
 nsresult MIME_get_unicode_decoder(const char* aInputCharset, nsIUnicodeDecoder **aDecoder);
 nsresult MIME_get_unicode_encoder(const char* aOutputCharset, nsIUnicodeEncoder **aEncoder);
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
 
--- a/mailnews/mime/src/mimeJSComponents.js
+++ b/mailnews/mime/src/mimeJSComponents.js
@@ -1,16 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+Components.utils.import("resource:///modules/Deprecated.jsm");
 Components.utils.import("resource:///modules/jsmime.jsm");
 Components.utils.import("resource:///modules/mimeParser.jsm");
 Components.utils.import("resource:///modules/XPCOMUtils.jsm");
 
+function HeaderHandler() {
+  this.value = "";
+  this.deliverData = function (str) { this.value += str; };
+  this.deliverEOF = function () {};
+}
+
 function MimeHeaders() {
 }
 MimeHeaders.prototype = {
   classDescription: "Mime headers implementation",
   classID: Components.ID("d1258011-f391-44fd-992e-c6f4b461a42f"),
   contractID: "@mozilla.org/messenger/mimeheaders;1",
   QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIMimeHeaders]),
 
@@ -48,19 +55,17 @@ var EmailGroup = {
   toString: function () {
     return this.name + ": " + [x.toString() for (x of this.group)].join(", ");
   }
 };
 
 function MimeAddressParser() {
 }
 MimeAddressParser.prototype = {
-  classDescription: "Mime message header parser implementation",
   classID: Components.ID("96bd8769-2d0e-4440-963d-22b97fb3ba77"),
-  contractID: "@mozilla.org/messenger/headerparser;1",
   QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIMsgHeaderParser]),
 
   parseEncodedHeader: function (aHeader, aCharset, aPreserveGroups, count) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(aHeader,
       MimeParser.HEADER_ADDRESS | MimeParser.HEADER_OPTION_ALL_I18N, aCharset);
     return this._fixArray(value, aPreserveGroups, count);
   },
@@ -106,21 +111,17 @@ MimeAddressParser.prototype = {
   makeMimeHeader: function (addresses, length) {
     // Don't output any necessary continuations, so make line length as large as
     // possible first.
     let options = {
       softMargin: 900,
       hardMargin: 900,
       useASCII: false // We don't want RFC 2047 encoding here.
     };
-    let handler = {
-      value: "",
-      deliverData: function (str) { this.value += str; },
-      deliverEOF: function () {}
-    };
+    let handler = new HeaderHandler();
     let emitter = new jsmime.headeremitter.makeStreamingEmitter(handler,
       options);
     emitter.addAddresses(addresses);
     emitter.finish(true);
     return handler.value.replace(/\r\n( |$)/g, '');
   },
 
   extractFirstName: function (aHeader) {
@@ -255,11 +256,83 @@ MimeAddressParser.prototype = {
   },
 
   makeMimeAddress: function (aName, aEmail) {
     let object = this.makeMailboxObject(aName, aEmail);
     return this.makeMimeHeader([object]);
   },
 };
 
+function MimeConverter() {
+}
+MimeConverter.prototype = {
+  classID: Components.ID("93f8c049-80ed-4dda-9000-94ad8daba44c"),
+  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIMimeConverter]),
 
-var components = [MimeHeaders, MimeAddressParser];
+  encodeMimePartIIStr_UTF8: function (aHeader, aStructured, aCharset,
+      aFieldNameLen, aLineLength) {
+    // The JSMime encoder only works in UTF-8, so if someone requests to not do
+    // it, they need to change their code.
+    if (aCharset.toLowerCase() != "utf-8") {
+      Deprecated.warning("Encoding to non-UTF-8 values is obsolete",
+        "http://bugzilla.mozilla.org/show_bug.cgi?id=790855");
+    }
+
+    // Compute the encoding options. The way our API is structured in this
+    // method is really horrendous and does not align with the way that JSMime
+    // handles it. Instead, we'll need to create a fake header to take into
+    // account the aFieldNameLen parameter.
+    let fakeHeader = '*'.repeat(aFieldNameLen);
+    let options = {
+      softMargin: aLineLength,
+      useASCII: true,
+    };
+    let handler = new HeaderHandler();
+    let emitter = new jsmime.headeremitter.makeStreamingEmitter(handler,
+      options);
+
+    // Add the text to the be encoded.
+    emitter.addHeaderName(fakeHeader);
+    if (aStructured) {
+      // Structured really means "this is an addressing header"
+      let addresses = MimeParser.parseHeaderField(aHeader,
+        MimeParser.HEADER_ADDRESS);
+      // This happens in one of our tests if there is a "bare" email but no
+      // @ sign. Without it, the result disappears since our emission code
+      // assumes that an empty email is not worth emitting.
+      if (addresses.length === 1 && addresses[0].email === "" &&
+          addresses[0].name !== "") {
+        addresses[0].email = addresses[0].name;
+        addresses[0].name = "";
+      }
+      emitter.addAddresses(addresses);
+    } else {
+      emitter.addUnstructured(aHeader);
+    }
+
+    // Compute the output. We need to strip off the fake prefix added earlier
+    // and the extra CRLF at the end.
+    emitter.finish(true);
+    let value = handler.value;
+    value = value.substring(value.indexOf(': ') + 2);
+    return value.substring(0, value.length - 2);
+  },
+
+  decodeMimeHeader: function (aHeader, aDefaultCharset, aOverride, aUnfold) {
+    let value = MimeParser.parseHeaderField(aHeader,
+      MimeParser.HEADER_UNSTRUCTURED | MimeParser.HEADER_OPTION_ALL_I18N,
+      aDefaultCharset);
+    if (aUnfold) {
+      value = value.replace(/[\r\n]\t/g, ' ')
+                   .replace(/[\r\n]/g, '');
+    }
+    return value;
+  },
+
+  // This is identical to the above, except for factors that are handled by the
+  // xpconnect conversion process
+  decodeMimeHeaderToUTF8: function () {
+    return this.decodeMimeHeader.apply(this, arguments);
+  },
+};
+
+var components = [MimeHeaders, MimeAddressParser, MimeConverter];
 var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/mailnews/mime/src/mimei.cpp
+++ b/mailnews/mime/src/mimei.cpp
@@ -51,17 +51,16 @@
 #include "prenv.h"
 #include "plstr.h"
 #include "prlink.h"
 #include "prprf.h"
 #include "mimecth.h"
 #include "mimebuf.h"
 #include "nsIServiceManager.h"
 #include "mimemoz2.h"
-#include "comi18n.h"
 #include "nsIMimeContentTypeHandler.h"
 #include "nsIComponentManager.h"
 #include "nsCategoryManagerUtils.h"
 #include "nsXPCOMCID.h"
 #include "nsISimpleMimeConverter.h"
 #include "nsSimpleMimeConverterStub.h"
 #include "nsVoidArray.h"
 #include "nsMimeStringResources.h"
--- a/mailnews/mime/src/mimemoz2.cpp
+++ b/mailnews/mime/src/mimemoz2.cpp
@@ -19,17 +19,16 @@
 #include "mimebuf.h"
 #include "prmem.h"
 #include "plstr.h"
 #include "prmem.h"
 #include "mimemoz2.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
-#include "comi18n.h"
 #include "nsIStringBundle.h"
 #include "nsStringGlue.h"
 #include "nsMimeStringResources.h"
 #include "nsStreamConverter.h"
 #include "nsIMsgSend.h"
 #include "nsIMsgMailNewsUrl.h"
 #include "mozITXTToHTMLConv.h"
 #include "nsCExternalHandlerService.h"
--- a/mailnews/mime/src/moz.build
+++ b/mailnews/mime/src/moz.build
@@ -1,15 +1,14 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
-    'comi18n.h',
     'mimecont.h',
     'mimecryp.h',
     'mimecth.h',
     'mimehdrs.h',
     'mimei.h',
     'mimeleaf.h',
     'mimemoz2.h',
     'mimemsig.h',
@@ -58,17 +57,16 @@ SOURCES += [
     'mimetext.cpp',
     'mimethpl.cpp',
     'mimethsa.cpp',
     'mimethtm.cpp',
     'mimetpfl.cpp',
     'mimetpla.cpp',
     'mimetric.cpp',
     'mimeunty.cpp',
-    'nsMimeConverter.cpp',
     'nsMimeObjectClassAccess.cpp',
     'nsSimpleMimeConverterStub.cpp',
     'nsStreamConverter.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'mimeJSComponents.js',
     'msgMime.manifest',
--- a/mailnews/mime/src/msgMime.manifest
+++ b/mailnews/mime/src/msgMime.manifest
@@ -1,4 +1,6 @@
 component {d1258011-f391-44fd-992e-c6f4b461a42f} mimeJSComponents.js
 component {96bd8769-2d0e-4440-963d-22b97fb3ba77} mimeJSComponents.js
+component {93f8c049-80ed-4dda-9000-94ad8daba44c} mimeJSComponents.js
 contract @mozilla.org/messenger/mimeheaders;1 {d1258011-f391-44fd-992e-c6f4b461a42f}
+contract @mozilla.org/messenger/mimeconverter;1 {93f8c049-80ed-4dda-9000-94ad8daba44c}
 contract @mozilla.org/messenger/headerparser;1 {96bd8769-2d0e-4440-963d-22b97fb3ba77}
deleted file mode 100644
--- a/mailnews/mime/src/nsMimeConverter.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include <stdio.h>
-#include "mimecom.h"
-#include "modmimee.h"
-#include "nscore.h"
-#include "nsMimeConverter.h"
-#include "comi18n.h"
-#include "nsMsgI18N.h"
-#include "prmem.h"
-#include "plstr.h"
-
-NS_IMPL_ISUPPORTS(nsMimeConverter, nsIMimeConverter)
-
-/*
- * nsMimeConverter definitions....
- */
-
-/* 
- * Inherited methods for nsMimeConverter
- */
-nsMimeConverter::nsMimeConverter()
-{
-}
-
-nsMimeConverter::~nsMimeConverter()
-{
-}
-
-nsresult
-nsMimeConverter::DecodeMimeHeaderToUTF8(const nsACString &header,
-                                        const char *default_charset,
-                                        bool override_charset,
-                                        bool eatContinuations,
-                                        nsACString &result)
-{
-  MIME_DecodeMimeHeader(PromiseFlatCString(header).get(), default_charset,
-                        override_charset, eatContinuations, result);
-  return NS_OK;
-}
-
-// Decode routine (also converts output to unicode)
-nsresult
-nsMimeConverter::DecodeMimeHeader(const char *header,
-                                  const char *default_charset,
-                                  bool override_charset,
-                                  bool eatContinuations,
-                                  nsAString& decodedString)
-{
-  NS_ENSURE_ARG_POINTER(header);
-
-  // apply MIME decode.
-  nsCString decodedCString;
-  MIME_DecodeMimeHeader(header, default_charset, override_charset,
-                        eatContinuations, decodedCString);
-  CopyUTF8toUTF16(decodedCString.IsEmpty() ? nsDependentCString(header)
-                                           : decodedCString,
-                  decodedString);
-  return NS_OK;
-}
-
-nsresult
-nsMimeConverter::EncodeMimePartIIStr_UTF8(const nsACString &header,
-                                          bool             structured,
-                                          const char       *mailCharset,
-                                          int32_t          fieldnamelen,
-                                          int32_t          encodedWordSize,
-                                          nsACString       &encodedString)
-{
-  encodedString.Adopt(MIME_EncodeMimePartIIStr(PromiseFlatCString(header).get(),
-                                               structured, mailCharset,
-                                               fieldnamelen, encodedWordSize));
-  return encodedString.IsVoid() ? NS_ERROR_FAILURE : NS_OK;
-}
deleted file mode 100644
--- a/mailnews/mime/src/nsMimeConverter.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- * This Original Code has been modified by IBM Corporation. Modifications made by IBM 
- * described herein are Copyright (c) International Business Machines Corporation, 2000.
- * Modifications to Mozilla code or documentation identified per MPL Section 3.3
- *
- * Date             Modified by     Description of modification
- * 04/20/2000       IBM Corp.      OS/2 VisualAge build.
- */
- 
-/*
- * This interface is implemented by libmime. This interface is used by 
- * a Content-Type handler "Plug In" (i.e. vCard) for accessing various 
- * internal information about the object class system of libmime. When 
- * libmime progresses to a C++ object class, this would probably change.
- */
-#ifndef nsMimeConverter_h_
-#define nsMimeConverter_h_
-
-#include "nsISupports.h"
-#include "nsIMimeConverter.h"
-#include "nsICharsetConverterManager.h"
-#include "nsCOMPtr.h"
-
-class nsMimeConverter : public nsIMimeConverter {
-public:
-  nsMimeConverter();
-  virtual ~nsMimeConverter();
-
-  /* this macro defines QueryInterface, AddRef and Release for this class */
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIMIMECONVERTER
-};
-
-#endif /* nsMimeConverter_h_ */
--- a/mailnews/mime/src/nsStreamConverter.cpp
+++ b/mailnews/mime/src/nsStreamConverter.cpp
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "nsCOMPtr.h"
 #include <stdio.h>
 #include "mimecom.h"
 #include "modmimee.h"
 #include "nscore.h"
 #include "nsStreamConverter.h"
-#include "comi18n.h"
 #include "prmem.h"
 #include "prprf.h"
 #include "prlog.h"
 #include "plstr.h"
 #include "mimemoz2.h"
 #include "nsMimeTypes.h"
 #include "nsIComponentManager.h"
 #include "nsIURL.h"
--- a/mailnews/mime/test/unit/test_EncodeMimePartIIStr_UTF8.js
+++ b/mailnews/mime/test/unit/test_EncodeMimePartIIStr_UTF8.js
@@ -10,17 +10,17 @@ function run_test() {
   var i;
 
   var checks =
   [
     ["", false, ""],
     ["\u0436", false, "=?UTF-8?B?0LY=?="], //CYRILLIC SMALL LETTER ZHE
     ["IamASCII", false, "IamASCII"],
     // Although an invalid email, we shouldn't crash on it (bug 479206)
-    ["crash test@foo.invalid>", true, "crash test@foo.invalid>"],
+    ["crash test@foo.invalid>", true, "\"crash test\"@foo.invalid"],
   ];
 
   for (i = 0; i < checks.length; ++i)
   {
     do_check_eq(
       MailServices.mimeConverter.encodeMimePartIIStr_UTF8(checks[i][0], checks[i][1], "UTF-8", 0, 72),
       checks[i][2]);
   }