From f22d3f905fea4e49bf214117d445b0b0a44f8547 Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Wed, 5 Jan 2022 23:46:47 -0300 Subject: [PATCH] Chore: Replace `isEmail` with `validateEmail` (#24020) --- .../views/app/tabbar/visitorTranscript.js | 4 ++-- client/views/account/AccountProfileForm.js | 4 ++-- .../views/admin/emailInbox/EmailInboxForm.js | 8 +++---- client/views/admin/mailer/Mailer.js | 4 ++-- client/views/admin/users/InviteUsers.js | 4 ++-- client/views/admin/users/UserForm.js | 4 ++-- .../omnichannel/departments/EditDepartment.js | 8 +++---- .../contacts/contextualBar/ContactNewEdit.js | 8 +++---- .../ExportMessages/MailExportForm.js | 4 ++-- lib/utils/isEmail.ts | 21 ------------------- 10 files changed, 24 insertions(+), 45 deletions(-) delete mode 100644 lib/utils/isEmail.ts diff --git a/app/livechat/client/views/app/tabbar/visitorTranscript.js b/app/livechat/client/views/app/tabbar/visitorTranscript.js index 3b30fcb495c..c544dccdca0 100644 --- a/app/livechat/client/views/app/tabbar/visitorTranscript.js +++ b/app/livechat/client/views/app/tabbar/visitorTranscript.js @@ -5,9 +5,9 @@ import { Template } from 'meteor/templating'; import { dispatchToastMessage } from '../../../../../../client/lib/toast'; import { handleError } from '../../../../../../client/lib/utils/handleError'; import { t, roomTypes } from '../../../../../utils'; -import { isEmail } from '../../../../../../lib/utils/isEmail'; import { APIClient } from '../../../../../utils/client'; import './visitorTranscript.html'; +import { validateEmail } from '../../../../../../lib/emailValidator'; const validateTranscriptData = (instance) => { const subject = instance.$('[name="subject"]').val(); @@ -18,7 +18,7 @@ const validateTranscriptData = (instance) => { return false; } - if (!isEmail(email)) { + if (!validateEmail(email)) { instance.errorMessage.set(t('Mail_Message_Invalid_emails', email)); return false; } diff --git a/client/views/account/AccountProfileForm.js b/client/views/account/AccountProfileForm.js index 5980ff34b6f..c54e6729691 100644 --- a/client/views/account/AccountProfileForm.js +++ b/client/views/account/AccountProfileForm.js @@ -14,8 +14,8 @@ import { import { useDebouncedCallback, useSafely } from '@rocket.chat/fuselage-hooks'; import React, { useCallback, useMemo, useEffect, useState } from 'react'; +import { validateEmail } from '../../../lib/emailValidator'; import { getUserEmailAddress } from '../../../lib/getUserEmailAddress'; -import { isEmail } from '../../../lib/utils/isEmail'; import CustomFieldsForm from '../../components/CustomFieldsForm'; import { USER_STATUS_TEXT_MAX_LENGTH } from '../../components/UserStatus'; import UserStatusMenu from '../../components/UserStatusMenu'; @@ -80,7 +80,7 @@ function AccountProfileForm({ values, handlers, user, settings, onSaveStateChang () => (!password || !confirmationPassword || password === confirmationPassword ? undefined : t('Passwords_do_not_match')), [t, password, confirmationPassword], ); - const emailError = useMemo(() => (isEmail(email) ? undefined : 'error-invalid-email-address'), [email]); + const emailError = useMemo(() => (validateEmail(email) ? undefined : 'error-invalid-email-address'), [email]); const checkUsername = useDebouncedCallback( async (username) => { if (user.username === username) { diff --git a/client/views/admin/emailInbox/EmailInboxForm.js b/client/views/admin/emailInbox/EmailInboxForm.js index 267d813db8a..d3ab425bed9 100644 --- a/client/views/admin/emailInbox/EmailInboxForm.js +++ b/client/views/admin/emailInbox/EmailInboxForm.js @@ -13,7 +13,7 @@ import { import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import React, { useCallback, useState } from 'react'; -import { isEmail } from '../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../lib/emailValidator'; import AutoCompleteDepartment from '../../../components/AutoCompleteDepartment'; import GenericModal from '../../../components/GenericModal'; import Page from '../../../components/Page'; @@ -132,7 +132,7 @@ function EmailInboxForm({ id, data }) { const emailAlreadyExistsAction = useEndpoint('GET', `email-inbox.search?email=${email}`); useComponentDidUpdate(() => { - setEmailError(!isEmail(email) ? t('Validate_email_address') : null); + setEmailError(!validateEmail(email) ? t('Validate_email_address') : null); }, [t, email]); useComponentDidUpdate(() => { !email && setEmailError(null); @@ -203,7 +203,7 @@ function EmailInboxForm({ id, data }) { }); const checkEmailExists = useMutableCallback(async () => { - if (!email && !isEmail(email)) { + if (!email && !validateEmail(email)) { return; } const { emailInbox } = await emailAlreadyExistsAction(); @@ -217,7 +217,7 @@ function EmailInboxForm({ id, data }) { hasUnsavedChanges && name && email && - isEmail(email) && + validateEmail(email) && !emailError && smtpServer && smtpPort && diff --git a/client/views/admin/mailer/Mailer.js b/client/views/admin/mailer/Mailer.js index 77e932c90a1..5cdf62b8e6e 100644 --- a/client/views/admin/mailer/Mailer.js +++ b/client/views/admin/mailer/Mailer.js @@ -1,7 +1,7 @@ import { TextInput, TextAreaInput, Field, FieldGroup, CheckBox, Button, Icon, ButtonGroup } from '@rocket.chat/fuselage'; import React, { useState, useCallback } from 'react'; -import { isEmail } from '../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../lib/emailValidator'; import { isJSON } from '../../../../lib/utils/isJSON'; import Page from '../../../components/Page'; import { useTranslation } from '../../../contexts/TranslationContext'; @@ -43,7 +43,7 @@ export function Mailer({ sendMail = () => {} }) { onChange={(e) => { setFromEmail({ value: e.currentTarget.value, - error: !isEmail(e.currentTarget.value) ? t('Invalid_Email') : undefined, + error: !validateEmail(e.currentTarget.value) ? t('Invalid_Email') : undefined, }); }} /> diff --git a/client/views/admin/users/InviteUsers.js b/client/views/admin/users/InviteUsers.js index 34e78455df3..7e9470a9e8c 100644 --- a/client/views/admin/users/InviteUsers.js +++ b/client/views/admin/users/InviteUsers.js @@ -1,7 +1,7 @@ import { Box, Button, Icon, TextAreaInput } from '@rocket.chat/fuselage'; import React, { useCallback, useState } from 'react'; -import { isEmail } from '../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../lib/emailValidator'; import VerticalBar from '../../../components/VerticalBar'; import { useMethod } from '../../../contexts/ServerContext'; import { useToastMessageDispatch } from '../../../contexts/ToastMessagesContext'; @@ -12,7 +12,7 @@ export function InviteUsers({ data, ...props }) { const dispatchToastMessage = useToastMessageDispatch(); const [text, setText] = useState(''); const sendInvites = useMethod('sendInvitationEmail'); - const getEmails = useCallback((text) => text.split(/[\ ,;]+/i).filter((val) => isEmail(val)), []); + const getEmails = useCallback((text) => text.split(/[\ ,;]+/i).filter((val) => validateEmail(val)), []); const handleClick = async () => { try { await sendInvites(getEmails(text)); diff --git a/client/views/admin/users/UserForm.js b/client/views/admin/users/UserForm.js index 49b8db61565..7f8f25804d0 100644 --- a/client/views/admin/users/UserForm.js +++ b/client/views/admin/users/UserForm.js @@ -12,7 +12,7 @@ import { } from '@rocket.chat/fuselage'; import React, { useCallback, useMemo, useState } from 'react'; -import { isEmail } from '../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../lib/emailValidator'; import CustomFieldsForm from '../../../components/CustomFieldsForm'; import VerticalBar from '../../../components/VerticalBar'; import { useTranslation } from '../../../contexts/TranslationContext'; @@ -100,7 +100,7 @@ export default function UserForm({ formValues, formHandlers, availableRoles, app error={errors && errors.email} flexGrow={1} value={email} - error={!isEmail(email) && email.length > 0 ? 'error' : undefined} + error={!validateEmail(email) && email.length > 0 ? 'error' : undefined} onChange={handleEmail} addon={} /> diff --git a/client/views/omnichannel/departments/EditDepartment.js b/client/views/omnichannel/departments/EditDepartment.js index 8f6a40c3a21..db7c3eee2fe 100644 --- a/client/views/omnichannel/departments/EditDepartment.js +++ b/client/views/omnichannel/departments/EditDepartment.js @@ -16,7 +16,7 @@ import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks'; import React, { useMemo, useState, useRef } from 'react'; import { useSubscription } from 'use-subscription'; -import { isEmail } from '../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../lib/emailValidator'; import Page from '../../../components/Page'; import { useRoomsList } from '../../../components/RoomAutoComplete/hooks/useRoomsList'; import { useRoute } from '../../../contexts/RouterContext'; @@ -156,7 +156,7 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) { setEmailError(!email ? t('The_field_is_required', 'email') : ''); }, [t, email]); useComponentDidUpdate(() => { - setEmailError(!isEmail(email) ? t('Validate_email_address') : ''); + setEmailError(!validateEmail(email) ? t('Validate_email_address') : ''); }, [t, email]); useComponentDidUpdate(() => { setTagError(requestTagBeforeClosingChat && (!tags || tags.length === 0) ? t('The_field_is_required', 'name') : ''); @@ -173,7 +173,7 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) { setEmailError(t('The_field_is_required', 'email')); error = true; } - if (!isEmail(email)) { + if (!validateEmail(email)) { setEmailError(t('Validate_email_address')); error = true; } @@ -236,7 +236,7 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) { }); const invalidForm = - !name || !email || !isEmail(email) || !hasUnsavedChanges || (requestTagBeforeClosingChat && (!tags || tags.length === 0)); + !name || !email || !validateEmail(email) || !hasUnsavedChanges || (requestTagBeforeClosingChat && (!tags || tags.length === 0)); const formId = useUniqueId(); diff --git a/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.js b/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.js index fcd4a87ff9b..c8597c37b01 100644 --- a/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.js +++ b/client/views/omnichannel/directory/contacts/contextualBar/ContactNewEdit.js @@ -4,7 +4,7 @@ import React, { useState, useMemo } from 'react'; import { useSubscription } from 'use-subscription'; import { hasAtLeastOnePermission } from '../../../../../../app/authorization/client'; -import { isEmail } from '../../../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../../../lib/emailValidator'; import CustomFieldsForm from '../../../../../components/CustomFieldsForm'; import VerticalBar from '../../../../../components/VerticalBar'; import { useEndpoint } from '../../../../../contexts/ServerContext'; @@ -104,7 +104,7 @@ function ContactNewEdit({ id, data, close }) { const phoneAlreadyExistsAction = useEndpoint('GET', `omnichannel/contact.search?phone=${phone}`); const checkEmailExists = useMutableCallback(async () => { - if (!isEmail(email)) { + if (!validateEmail(email)) { return; } const { contact } = await emailAlreadyExistsAction(); @@ -131,7 +131,7 @@ function ContactNewEdit({ id, data, close }) { setNameError(!name ? t('The_field_is_required', t('Name')) : ''); }, [t, name]); useComponentDidUpdate(() => { - setEmailError(email && !isEmail(email) ? t('Validate_email_address') : null); + setEmailError(email && !validateEmail(email) ? t('Validate_email_address') : null); }, [t, email]); useComponentDidUpdate(() => { !phone && setPhoneError(null); @@ -144,7 +144,7 @@ function ContactNewEdit({ id, data, close }) { setNameError(t('The_field_is_required', 'name')); error = true; } - if (email && !isEmail(email)) { + if (email && !validateEmail(email)) { setEmailError(t('Validate_email_address')); error = true; } diff --git a/client/views/room/contextualBar/ExportMessages/MailExportForm.js b/client/views/room/contextualBar/ExportMessages/MailExportForm.js index c8d8fa4df44..d451f4ffd47 100644 --- a/client/views/room/contextualBar/ExportMessages/MailExportForm.js +++ b/client/views/room/contextualBar/ExportMessages/MailExportForm.js @@ -4,7 +4,7 @@ import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import React, { useState, useEffect } from 'react'; import { roomTypes } from '../../../../../app/utils/client'; -import { isEmail } from '../../../../../lib/utils/isEmail'; +import { validateEmail } from '../../../../../lib/emailValidator'; import UserAutoCompleteMultiple from '../../../../components/UserAutoCompleteMultiple'; import { useEndpoint } from '../../../../contexts/ServerContext'; import { useToastMessageDispatch } from '../../../../contexts/ToastMessagesContext'; @@ -85,7 +85,7 @@ const MailExportForm = ({ onCancel, rid }) => { setErrorMessage(t('Mail_Message_Missing_to')); return; } - if (additionalEmails !== '' && !isEmail(additionalEmails)) { + if (additionalEmails !== '' && !validateEmail(additionalEmails)) { setErrorMessage(t('Mail_Message_Invalid_emails', additionalEmails)); return; } diff --git a/lib/utils/isEmail.ts b/lib/utils/isEmail.ts deleted file mode 100644 index 8cb87c6ce5e..00000000000 --- a/lib/utils/isEmail.ts +++ /dev/null @@ -1,21 +0,0 @@ -const sQtext = '[^\\x0d\\x22\\x5c]'; -const sDtext = '[^\\x0d\\x5b-\\x5d]'; -const sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d]+'; -const sQuotedPair = '\\x5c[\\x00-\\x7f]'; -const sDomainLiteral = `\\x5b(${sDtext}|${sQuotedPair})*\\x5d`; -const sQuotedString = `\\x22(${sQtext}|${sQuotedPair})*\\x22`; -const sDomainRef = sAtom; -const sSubDomain = `(${sDomainRef}|${sDomainLiteral})`; -const sWord = `(${sAtom}|${sQuotedString})`; -const sDomain = `${sSubDomain}(\\x2e${sSubDomain})*`; -const sLocalPart = `${sWord}(\\x2e${sWord})*`; -const sAddrSpec = `${sLocalPart}\\x40${sDomain}`; -const sValidEmail = `^${sAddrSpec}$`; -const reg = new RegExp(sValidEmail); - -/* - * Code from https://github.com/dleitee/valid.js - * Checks for email - * @params email - */ -export const isEmail = (email: string): boolean => reg.test(email);