internationalizedemailaddress.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Copyright 2014 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Provides functions to parse and manipulate internationalized
  16. * email addresses. This is useful in the context of Email Address
  17. * Internationalization (EAI) as defined by RFC6530.
  18. *
  19. */
  20. goog.provide('goog.format.InternationalizedEmailAddress');
  21. goog.require('goog.format.EmailAddress');
  22. goog.require('goog.string');
  23. /**
  24. * Formats an email address string for display, and allows for extraction of
  25. * the individual components of the address.
  26. * @param {string=} opt_address The email address.
  27. * @param {string=} opt_name The name associated with the email address.
  28. * @constructor
  29. * @extends {goog.format.EmailAddress}
  30. */
  31. goog.format.InternationalizedEmailAddress = function(opt_address, opt_name) {
  32. goog.format.InternationalizedEmailAddress.base(
  33. this, 'constructor', opt_address, opt_name);
  34. };
  35. goog.inherits(
  36. goog.format.InternationalizedEmailAddress, goog.format.EmailAddress);
  37. /**
  38. * A string representing the RegExp for the local part of an EAI email address.
  39. * @private
  40. */
  41. goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ =
  42. '((?!\\s)[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~\u0080-\uFFFFFF-])+';
  43. /**
  44. * A string representing the RegExp for a label in the domain part of an EAI
  45. * email address.
  46. * @private
  47. */
  48. goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ =
  49. '(?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uFF0D\uFF0F-\uFF60\uFF62-\uFFFFFF-]';
  50. /**
  51. * A string representing the RegExp for the domain part of an EAI email address.
  52. * @private
  53. */
  54. goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ =
  55. // A unicode character (ASCII or Unicode excluding periods)
  56. '(' + goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ +
  57. // Such character 1+ times, followed by a Unicode period. All 1+ times.
  58. '+[\\.\\uFF0E\\u3002\\uFF61])+' +
  59. // And same thing but without a period in the end
  60. goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ +
  61. '{2,63}';
  62. /**
  63. * Match string for address separators. This list is the result of the
  64. * discussion in b/16241003.
  65. * @type {string}
  66. * @private
  67. */
  68. goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_ =
  69. ',' + // U+002C ( , ) COMMA
  70. ';' + // U+003B ( ; ) SEMICOLON
  71. '\u055D' + // ( ՝ ) ARMENIAN COMMA
  72. '\u060C' + // ( ، ) ARABIC COMMA
  73. '\u1363' + // ( ፣ ) ETHIOPIC COMMA
  74. '\u1802' + // ( ᠂ ) MONGOLIAN COMMA
  75. '\u1808' + // ( ᠈ ) MONGOLIAN MANCHU COMMA
  76. '\u2E41' + // ( ⹁ ) REVERSED COMMA
  77. '\u3001' + // ( 、 ) IDEOGRAPHIC COMMA
  78. '\uFF0C' + // ( , ) FULLWIDTH COMMA
  79. '\u061B' + // ( ‎؛‎ ) ARABIC SEMICOLON
  80. '\u1364' + // ( ፤ ) ETHIOPIC SEMICOLON
  81. '\uFF1B' + // ( ; ) FULLWIDTH SEMICOLON
  82. '\uFF64' + // ( 、 ) HALFWIDTH IDEOGRAPHIC COMMA
  83. '\u104A'; // ( ၊ ) MYANMAR SIGN LITTLE SECTION
  84. /**
  85. * Match string for characters that, when in a display name, require it to be
  86. * quoted.
  87. * @type {string}
  88. * @private
  89. */
  90. goog.format.InternationalizedEmailAddress.CHARS_REQUIRE_QUOTES_ =
  91. goog.format.EmailAddress.SPECIAL_CHARS +
  92. goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_;
  93. /**
  94. * A RegExp to match the local part of an EAI email address.
  95. * @private {!RegExp}
  96. */
  97. goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_ = new RegExp(
  98. '^' + goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ +
  99. '$');
  100. /**
  101. * A RegExp to match the domain part of an EAI email address.
  102. * @private {!RegExp}
  103. */
  104. goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_ = new RegExp(
  105. '^' +
  106. goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ +
  107. '$');
  108. /**
  109. * A RegExp to match an EAI email address.
  110. * @private {!RegExp}
  111. */
  112. goog.format.InternationalizedEmailAddress.EAI_EMAIL_ADDRESS_ = new RegExp(
  113. '^' + goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ +
  114. '@' +
  115. goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ +
  116. '$');
  117. /**
  118. * Checks if the provided string is a valid local part (part before the '@') of
  119. * an EAI email address.
  120. * @param {string} str The local part to check.
  121. * @return {boolean} Whether the provided string is a valid local part.
  122. */
  123. goog.format.InternationalizedEmailAddress.isValidLocalPartSpec = function(str) {
  124. if (!goog.isDefAndNotNull(str)) {
  125. return false;
  126. }
  127. return goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_.test(str);
  128. };
  129. /**
  130. * Checks if the provided string is a valid domain part (part after the '@') of
  131. * an EAI email address.
  132. * @param {string} str The domain part to check.
  133. * @return {boolean} Whether the provided string is a valid domain part.
  134. */
  135. goog.format.InternationalizedEmailAddress.isValidDomainPartSpec = function(
  136. str) {
  137. if (!goog.isDefAndNotNull(str)) {
  138. return false;
  139. }
  140. return goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_.test(str);
  141. };
  142. /** @override */
  143. goog.format.InternationalizedEmailAddress.prototype.isValid = function() {
  144. return goog.format.InternationalizedEmailAddress.isValidAddrSpec(
  145. this.address);
  146. };
  147. /**
  148. * Checks if the provided string is a valid email address. Supports both
  149. * simple email addresses (address specs) and addresses that contain display
  150. * names.
  151. * @param {string} str The email address to check.
  152. * @return {boolean} Whether the provided string is a valid address.
  153. */
  154. goog.format.InternationalizedEmailAddress.isValidAddress = function(str) {
  155. if (!goog.isDefAndNotNull(str)) {
  156. return false;
  157. }
  158. return goog.format.InternationalizedEmailAddress.parse(str).isValid();
  159. };
  160. /**
  161. * Checks if the provided string is a valid address spec (local@domain.com).
  162. * @param {string} str The email address to check.
  163. * @return {boolean} Whether the provided string is a valid address spec.
  164. */
  165. goog.format.InternationalizedEmailAddress.isValidAddrSpec = function(str) {
  166. if (!goog.isDefAndNotNull(str)) {
  167. return false;
  168. }
  169. // This is a fairly naive implementation, but it covers 99% of use cases.
  170. // For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
  171. return goog.format.InternationalizedEmailAddress.EAI_EMAIL_ADDRESS_.test(str);
  172. };
  173. /**
  174. * Parses a string containing email addresses of the form
  175. * "name" <address> into an array of email addresses.
  176. * @param {string} str The address list.
  177. * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
  178. */
  179. goog.format.InternationalizedEmailAddress.parseList = function(str) {
  180. return goog.format.EmailAddress.parseListInternal(
  181. str, goog.format.InternationalizedEmailAddress.parse,
  182. goog.format.InternationalizedEmailAddress.isAddressSeparator);
  183. };
  184. /**
  185. * Parses an email address of the form "name" &lt;address&gt; into
  186. * an email address.
  187. * @param {string} addr The address string.
  188. * @return {!goog.format.EmailAddress} The parsed address.
  189. */
  190. goog.format.InternationalizedEmailAddress.parse = function(addr) {
  191. return goog.format.EmailAddress.parseInternal(
  192. addr, goog.format.InternationalizedEmailAddress);
  193. };
  194. /**
  195. * @param {string} ch The character to test.
  196. * @return {boolean} Whether the provided character is an address separator.
  197. */
  198. goog.format.InternationalizedEmailAddress.isAddressSeparator = function(ch) {
  199. return goog.string.contains(
  200. goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_, ch);
  201. };
  202. /**
  203. * Return the address in a standard format:
  204. * - remove extra spaces.
  205. * - Surround name with quotes if it contains special characters.
  206. * @return {string} The cleaned address.
  207. * @override
  208. */
  209. goog.format.InternationalizedEmailAddress.prototype.toString = function() {
  210. return this.toStringInternal(
  211. goog.format.InternationalizedEmailAddress.CHARS_REQUIRE_QUOTES_);
  212. };