EmailHelper.mjs 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import emailAddresses from 'email-addresses'
  2. import { z } from '../../infrastructure/Validation.mjs'
  3. const { parseOneAddress } = emailAddresses
  4. // available for frontend in https://github.com/overleaf/internal/blob/19d432c70b173752ee7c6d8978dd6be16b042921/services/web/frontend/js/shared/utils/email.tsx#L4
  5. const EMAIL_REGEXP =
  6. // eslint-disable-next-line no-useless-escape
  7. /^([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
  8. const emailSchema = z
  9. .string()
  10. .transform(email => parseEmail(email))
  11. .refine(v => v !== null, { message: 'Invalid email address' })
  12. /**
  13. * @param {string} email
  14. * @return {string|null}
  15. */
  16. function getDomain(email) {
  17. email = parseEmail(email)
  18. return email ? email.split('@').pop() : null
  19. }
  20. /**
  21. * @param {string} email
  22. * @param {boolean} parseRfcAddress
  23. * @return {string|null}
  24. */
  25. function parseEmail(email, parseRfcAddress = false) {
  26. if (typeof email !== 'string' || !email) {
  27. return null
  28. }
  29. if (parseRfcAddress) {
  30. const result = parseOneAddress(email)
  31. if (!result?.address) {
  32. return null
  33. }
  34. email = result.address
  35. }
  36. if (email.length > 254) {
  37. return null
  38. }
  39. email = email.trim().toLowerCase()
  40. const matched = email.match(EMAIL_REGEXP)
  41. if (matched == null || matched[0] == null) {
  42. return null
  43. }
  44. return matched[0]
  45. }
  46. export default {
  47. emailSchema,
  48. getDomain,
  49. parseEmail,
  50. }