hechengjin 发表于 2016-3-23 16:02:24

读信页标题的解码

本帖最后由 hechengjin 于 2016-3-25 19:39 编辑

messageWindow.xul
messageWindow.jsonDisplayingMessage:
      function StandaloneMessageDisplayWidget_onDisplayingMessage(aMsgHdr) {
    this.__proto__.__proto__.onDisplayingMessage.call(this, aMsgHdr);

    // - set the window title to the message subject (and maybe the app name)
    let docTitle = aMsgHdr.mime2DecodedSubject;

    // If the tab hasn't got a title, or we're on Mac, don't display
    // the separator.
    if (docTitle && !Application.platformIsMac)
      docTitle += document.documentElement
                            .getAttribute("titlemenuseparator");

    // If we haven't got a title at this stage add the modifier, or if
    // we are on a non-mac platform, add the modifier.
    if (!docTitle || !Application.platformIsMac)
         docTitle += document.documentElement
                           .getAttribute("titlemodifier");

    document.title = docTitle;nsMsgI18N.cpp


jimu 发表于 2016-3-24 12:37:02

导入不标准邮件,对邮件标题按GB2312进行处理并编码,尽量保证不出现乱码
mailnews/local/src/nsParseMailbox.cpp
/mailnews/local/src/nsParseMailbox.hint nsParseMailMessageState::InternSubject (struct message_header *header)
{
char *key;
uint32_t L;

if (!header || header->length == 0)
{
    m_newMsgHdr->SetSubject("");
    return 0;
}

NS_ASSERTION (header->length == (short) strlen(header->value), "subject corrupt while parsing message");

key = (char *) header->value;/* #### const evilness */

L = header->length;


uint32_t flags;
(void)m_newMsgHdr->GetFlags(&flags);
/* strip "Re: " */
/**
      We trust the X-Mozilla-Status line to be the smartest in almost
      all things.One exception, however, is the HAS_RE flag.Since
         we just parsed the subject header anyway, we expect that parsing
         to be smartest.(After all, what if someone just went in and
      edited the subject line by hand?)
   */
nsCString modifiedSubject;
if (NS_MsgStripRE((const char **) &key, &L, getter_Copies(modifiedSubject)))
    flags |= nsMsgMessageFlags::HasRe;
else
    flags &= ~nsMsgMessageFlags::HasRe;
m_newMsgHdr->SetFlags(flags); // this *does not* update the mozilla-status header in the local folder

//if (!*key) return 0; /* To catch a subject of "Re:" */

// Condense the subject text into as few MIME-2 encoded words as possible.
#ifdef WE_CONDENSE_MIME_STRINGS
char *condensedKey = msg_condense_mime2_string(modifiedSubject.IsEmpty() ? key : modifiedSubject.get());
#else
char *condensedKey = nullptr;
#endif

// 如果导入的邮件标题不符合标准格式没有编码,自己按GB2312处理并编码
bool bStandard = IsStandardFormat(key, header->length);
if (!bStandard)// 按gb2312处理
{
          char *pszFixStr= FixStandardFormat(key, header->length);
          if (pszFixStr == nullptr)
          {
                  m_newMsgHdr->SetSubject(condensedKey ? condensedKey :
                          (modifiedSubject.IsEmpty() ? key : modifiedSubject.get()));
          }
          else
          {
                  m_newMsgHdr->SetSubject(condensedKey ? condensedKey :
                          (modifiedSubject.IsEmpty() ? pszFixStr : modifiedSubject.get()));
                  PR_FREEIF(pszFixStr);
          }
}
else // 正常处理
{
          m_newMsgHdr->SetSubject(condensedKey ? condensedKey :
                  (modifiedSubject.IsEmpty() ? key : modifiedSubject.get()));
}

PR_FREEIF(condensedKey);

return 0;
}

bool nsParseMailMessageState::IsStandardFormat(char *pszValue, uint32_t uiLen)
{
        for (uint32_t i = 0; i < uiLen; i++)
        {
                if (pszValue < 0x20 || pszValue > 0x7e)
                {
                        if (pszValue == 0x0d || pszValue == 0x0a)
                                continue;

                        return false;
                }
        }

        return true;
}

char* nsParseMailMessageState::FixStandardFormat(char *pszValue, uint32_t uiLen)
{
        nsCString UTF8Str;
        nsString UTF16Str;

        const char *pInternal = nullptr;
        ConvertToUnicode("gb2312", pszValue, UTF16Str);
        UTF8Str = NS_ConvertUTF16toUTF8(UTF16Str);
        uint32_t iLen = UTF8Str.GetData(&pInternal);

        char *pBase64 = PL_Base64Encode(pInternal, iLen, nullptr);
        if (pBase64 == nullptr)
                return nullptr;

        char *pszBuffer = (char *)PR_Malloc(PL_strlen(pBase64) + 12 + 10);
        if (pszBuffer == nullptr)
        {
                PR_Free(pBase64);
                return nullptr;
        }

        memset(pszBuffer, 0, PL_strlen(pBase64) + 12 + 10);
        PL_strcat(pszBuffer, "=?UTF-8?B?");
        PL_strcat(pszBuffer, pBase64);
        PL_strcat(pszBuffer, "?=");

        return pszBuffer;
}

class nsParseMailMessageState : public nsIMsgParseMailMsgState, public nsIDBChangeListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGPARSEMAILMSGSTATE
NS_DECL_NSIDBCHANGELISTENER

nsParseMailMessageState();
virtual               ~nsParseMailMessageState();

void                  Init(uint32_t fileposition);
virtual int32_t       ParseFolderLine(const char *line, uint32_t lineLength);
virtual int         StartNewEnvelope(const char *line, uint32_t lineLength);
int                   ParseHeaders();
int                   FinalizeHeaders();
int                   ParseEnvelope (const char *line, uint32_t line_size);
int                   InternSubject (struct message_header *header);

static bool    IsEnvelopeLine(const char *buf, int32_t buf_size);
static intmsg_UnHex(char C);

nsCOMPtr<nsIMsgHeaderParser> m_HeaderAddressParser;

nsCOMPtr<nsIMsgDBHdr> m_newMsgHdr; /* current message header we're building */
nsCOMPtr<nsIMsgDatabase>m_mailDB;
nsCOMPtr<nsIMsgDatabase> m_backupMailDB;

nsMailboxParseState   m_state;
int64_t            m_position;
uint64_t            m_envelope_pos;
uint64_t            m_headerstartpos;

nsByteArray         m_headers;

nsByteArray         m_envelope;

struct message_header m_message_id;
struct message_header m_references;
struct message_header m_date;
struct message_header m_delivery_date;
struct message_header m_from;
struct message_header m_sender;
struct message_header m_newsgroups;
struct message_header m_subject;
struct message_header m_status;
struct message_header m_mozstatus;
struct message_header m_mozstatus2;
struct message_header m_in_reply_to;
struct message_header m_replyTo;
struct message_header m_content_type;
struct message_header m_bccList;

// Support for having multiple To or Cc header lines in a message
nsVoidArray m_toList;
nsVoidArray m_ccList;
struct message_header *GetNextHeaderInAggregate (nsVoidArray &list);
void GetAggregateHeader (nsVoidArray &list, struct message_header *);
void ClearAggregateHeader (nsVoidArray &list);

struct message_header m_envelope_from;
struct message_header m_envelope_date;
struct message_header m_priority;
struct message_header m_account_key;
struct message_header m_keywords;
// Mdn support
struct message_header m_mdn_original_recipient;
struct message_header m_return_path;
struct message_header m_mdn_dnt; /* MDN Disposition-Notification-To: header */

PRTime m_receivedTime;
uint16_t            m_body_lines;

bool                  m_IgnoreXMozillaStatus;

// this enables extensions to add the values of particular headers to
// the .msf file as properties of nsIMsgHdr. It is initialized from a
// pref, mailnews.customDBHeaders
nsTArray<nsCString>   m_customDBHeaders;
struct message_header *m_customDBHeaderValues;

bool IsStandardFormat(char *pszValue, uint32_t uiLen);
char *FixStandardFormat(char *pszValue, uint32_t uiLen);

protected:
};

// this should go in some utility class.
inline int nsParseMailMessageState::msg_UnHex(char C)
{
return ((C >= '0' && C <= '9') ? C - '0' :
    ((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
   ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)));
}

hechengjin 发表于 2016-4-5 16:11:44

http://www.firemail.wang/forum.php?mod=viewthread&tid=24&highlight=%B9%A4%BE%DF
先用函数base64_encode() — 使用 MIME base64 对数据进行编码
  标题字符串前加编码类型例如: =?UTF-8?B?
  标题字符串后加:?=

  例如:

  $subject = "=?UTF-8?B?".base64_encode($subject)."?=";

  将上面一句添加到代码之中,这样,发送的中文邮件标题就不是乱码了。

hechengjin 发表于 2016-4-8 10:23:33

本帖最后由 hechengjin 于 2016-4-8 13:59 编辑

(https://www.rfc-editor.org/rfc/pdfrfc/rfc1342.txt.pdf)for (let key in rowHeaderData) {
      let headers = []
      for (let header of rowHeaderData) {
      let headerItem = {
          headerName: header.headerName
      }
      // RFC 1342 - Representation of Non-ASCII Text in Internet Message Headers
      // (https://www.rfc-editor.org/rfc/pdfrfc/rfc1342.txt.pdf)
      // subject may be an encoded word with format: "=?charset?encoding?encodedText?="
      // if subject is not a encoded word, do not decode it.
      if (header.headerName.toLowerCase() === 'subject' &&
            header.headerValue.match(EncodingTextRegx) === null) {
          headerItem.headerValue = header.headerValue
      } else {
          headerItem.headerValue = this.decodeMimeHeaderValue(header.headerValue)
      }
      headers.push(headerItem)
      }
      currentHeaderData = headers
    }
页: [1]
查看完整版本: 读信页标题的解码