summaryrefslogtreecommitdiffstats
path: root/comm/mail/modules/DisplayNameUtils.jsm
blob: bee32796fd7139f121241b1d7ebc692f648c6b79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* 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/. */

const EXPORTED_SYMBOLS = ["DisplayNameUtils"];

const { MailServices } = ChromeUtils.import(
  "resource:///modules/MailServices.jsm"
);

var DisplayNameUtils = {
  formatDisplayName,
  formatDisplayNameList,
};

// XXX: Maybe the strings for this file should go in a separate bundle?
var gMessengerBundle = Services.strings.createBundle(
  "chrome://messenger/locale/messenger.properties"
);

function _getIdentityForAddress(aEmailAddress) {
  let emailAddress = aEmailAddress.toLowerCase();
  for (let identity of MailServices.accounts.allIdentities) {
    if (!identity.email) {
      continue;
    }
    if (emailAddress == identity.email.toLowerCase()) {
      return identity;
    }
  }
  return null;
}

/**
 * Take an email address and compose a sensible display name based on the
 * header display name and/or the display name from the address book. If no
 * appropriate name can be made (e.g. there is no card for this address),
 * returns |null|.
 *
 * @param {string} emailAddress - The email address to format.
 * @param {string} headerDisplayName - The display name from the header, if any.
 * @param {string} context - The field being formatted (e.g. "to", "from").
 * @returns The formatted display name, or null.
 */
function formatDisplayName(emailAddress, headerDisplayName, context) {
  let displayName = null;
  let identity = _getIdentityForAddress(emailAddress);
  let card = MailServices.ab.cardForEmailAddress(emailAddress);

  // If this address is one of the user's identities...
  if (identity) {
    if (
      MailServices.accounts.allIdentities.length == 1 &&
      (!headerDisplayName || identity.fullName == headerDisplayName)
    ) {
      // ...pick a localized version of the word "Me" appropriate to this
      // specific header; fall back to the version used by the "to" header
      // if nothing else is available.
      try {
        displayName = gMessengerBundle.GetStringFromName(
          `header${context}FieldMe`
        );
      } catch (e) {
        displayName = gMessengerBundle.GetStringFromName("headertoFieldMe");
      }
    } else {
      // Use the full address. It's not the expected name, maybe a customized
      //  one the user sent, or one the sender got wrong, or we have multiple
      // identities making the "Me" short string ambiguous.
      displayName = MailServices.headerParser
        .makeMailboxObject(headerDisplayName, emailAddress)
        .toString();
    }
  }

  // If we don't have a card, refuse to generate a display name. Places calling
  // this are then responsible for falling back to something else (e.g. the
  // value from the message header).
  if (card) {
    // getProperty may return a "1" or "0" string, we want a boolean
    if (card.getProperty("PreferDisplayName", "1") == "1") {
      displayName = card.displayName || null;
    }

    // Note: headerDisplayName is not used as a fallback as confusion could be
    // caused by a collected address using an e-mail address as display name.
  }

  return displayName;
}

/**
 * Format the display name from a list of addresses. First, try using
 * formatDisplayName, then fall back to the header's display name or the
 * address.
 *
 * @param aHeaderValue  The decoded header value (e.g. mime2DecodedAuthor).
 * @param aContext      The context of the header field (e.g. "to", "from").
 * @returns The formatted display name.
 */
function formatDisplayNameList(aHeaderValue, aContext) {
  let addresses = MailServices.headerParser.parseDecodedHeader(aHeaderValue);
  if (addresses.length > 0) {
    let displayName = formatDisplayName(
      addresses[0].email,
      addresses[0].name,
      aContext
    );
    let andOthersStr = "";
    if (addresses.length > 1) {
      andOthersStr = " " + gMessengerBundle.GetStringFromName("andOthers");
    }

    if (displayName) {
      return displayName + andOthersStr;
    }

    // Construct default display.
    if (addresses[0].email) {
      return (
        MailServices.headerParser
          .makeMailboxObject(addresses[0].name, addresses[0].email)
          .toString() + andOthersStr
      );
    }
  }

  // Something strange happened, just return the raw header value.
  return aHeaderValue;
}