diff --git a/src/ROUTES.js b/src/ROUTES.js
index 2cbe87a4361e..2412e7e42550 100644
--- a/src/ROUTES.js
+++ b/src/ROUTES.js
@@ -51,6 +51,8 @@ export default {
     SETTINGS_PERSONAL_DETAILS_DATE_OF_BIRTH: `${SETTINGS_PERSONAL_DETAILS}/date-of-birth`,
     SETTINGS_PERSONAL_DETAILS_ADDRESS: `${SETTINGS_PERSONAL_DETAILS}/address`,
     SETTINGS_CONTACT_METHODS,
+    SETTINGS_CONTACT_METHOD_DETAILS: `${SETTINGS_CONTACT_METHODS}/:contactMethod/details`,
+    getEditContactMethodRoute: contactMethod => `${SETTINGS_CONTACT_METHODS}/${encodeURIComponent(contactMethod)}/details`,
     NEW_GROUP: 'new/group',
     NEW_CHAT: 'new/chat',
     REPORT,
diff --git a/src/components/AvatarWithIndicator.js b/src/components/AvatarWithIndicator.js
index 4a04231c805e..93d6e3d82a73 100644
--- a/src/components/AvatarWithIndicator.js
+++ b/src/components/AvatarWithIndicator.js
@@ -16,17 +16,18 @@ import walletTermsPropTypes from '../pages/EnablePayments/walletTermsPropTypes';
 import * as PolicyUtils from '../libs/PolicyUtils';
 import * as PaymentMethods from '../libs/actions/PaymentMethods';
 import * as ReportUtils from '../libs/ReportUtils';
+import * as UserUtils from '../libs/UserUtils';
+import themeColors from '../styles/themes/default';
 
 const propTypes = {
     /** URL for the avatar */
     source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
 
-    /** Avatar size */
-    size: PropTypes.string,
-
     /** To show a tooltip on hover */
     tooltipText: PropTypes.string,
 
+    /* Onyx Props */
+
     /** The employee list of all policies (coming from Onyx) */
     policiesMemberList: PropTypes.objectOf(policyMemberPropType),
 
@@ -44,10 +45,18 @@ const propTypes = {
 
     /** Information about the user accepting the terms for payments */
     walletTerms: walletTermsPropTypes,
+
+    /** Login list for the user that is signed in */
+    loginList: PropTypes.shape({
+        /** Date login was validated, used to show info indicator status */
+        validatedDate: PropTypes.string,
+
+        /** Field-specific server side errors keyed by microtime */
+        errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+    }),
 };
 
 const defaultProps = {
-    size: 'default',
     tooltipText: '',
     policiesMemberList: {},
     policies: {},
@@ -55,45 +64,47 @@ const defaultProps = {
     cardList: {},
     userWallet: {},
     walletTerms: {},
+    loginList: {},
 };
 
 const AvatarWithIndicator = (props) => {
-    const isLarge = props.size === 'large';
-    const indicatorStyles = [
-        styles.alignItemsCenter,
-        styles.justifyContentCenter,
-        isLarge ? styles.statusIndicatorLarge : styles.statusIndicator,
-    ];
-
     // If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and
     // those should be cleaned out before doing any error checking
     const cleanPolicies = _.pick(props.policies, policy => policy);
     const cleanPolicyMembers = _.pick(props.policiesMemberList, member => member);
 
-    // All of the error-checking methods are put into an array. This is so that using _.some() will return
-    // early as soon as the first error is returned. This makes the error checking very efficient since
-    // we only care if a single error exists anywhere.
+    // All of the error & info-checking methods are put into an array. This is so that using _.some() will return
+    // early as soon as the first error / info condition is returned. This makes the checks very efficient since
+    // we only care if a single error / info condition exists anywhere.
     const errorCheckingMethods = [
         () => !_.isEmpty(props.userWallet.errors),
         () => PaymentMethods.hasPaymentMethodError(props.bankAccountList, props.cardList),
         () => _.some(cleanPolicies, PolicyUtils.hasPolicyError),
         () => _.some(cleanPolicies, PolicyUtils.hasCustomUnitsError),
         () => _.some(cleanPolicyMembers, PolicyUtils.hasPolicyMemberError),
+        () => UserUtils.hasLoginListError(props.loginList),
 
         // Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead)
         () => !_.isEmpty(props.walletTerms.errors) && !props.walletTerms.chatReportID,
     ];
-    const shouldShowIndicator = _.some(errorCheckingMethods, errorCheckingMethod => errorCheckingMethod());
+    const infoCheckingMethods = [
+        () => UserUtils.hasLoginListInfo(props.loginList),
+    ];
+    const shouldShowErrorIndicator = _.some(errorCheckingMethods, errorCheckingMethod => errorCheckingMethod());
+    const shouldShowInfoIndicator = !shouldShowErrorIndicator && _.some(infoCheckingMethods, infoCheckingMethod => infoCheckingMethod());
+
+    const indicatorColor = shouldShowErrorIndicator ? themeColors.danger : themeColors.success;
+    const indicatorStyles = [
+        styles.alignItemsCenter,
+        styles.justifyContentCenter,
+        styles.statusIndicator(indicatorColor),
+    ];
 
     return (
-        <View style={[isLarge ? styles.avatarLarge : styles.sidebarAvatar]}>
+        <View style={[styles.sidebarAvatar]}>
             <Tooltip text={props.tooltipText}>
-                <Avatar
-                    imageStyles={[isLarge ? styles.avatarLarge : null]}
-                    source={ReportUtils.getSmallSizeAvatar(props.source)}
-                    size={props.size}
-                />
-                {shouldShowIndicator && (
+                <Avatar source={ReportUtils.getSmallSizeAvatar(props.source)} />
+                {(shouldShowErrorIndicator || shouldShowInfoIndicator) && (
                     <View style={StyleSheet.flatten(indicatorStyles)} />
                 )}
             </Tooltip>
@@ -124,4 +135,7 @@ export default withOnyx({
     walletTerms: {
         key: ONYXKEYS.WALLET_TERMS,
     },
+    loginList: {
+        key: ONYXKEYS.LOGIN_LIST,
+    },
 })(AvatarWithIndicator);
diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js
index 2942f250ce83..653dd180c209 100644
--- a/src/components/MenuItem.js
+++ b/src/components/MenuItem.js
@@ -63,7 +63,7 @@ const MenuItem = (props) => {
     const descriptionTextStyle = StyleUtils.combineStyles([
         styles.textLabelSupporting,
         (props.icon ? styles.ml3 : undefined),
-        styles.breakAll,
+        styles.breakWord,
         styles.lineHeightNormal,
     ], props.style);
 
diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js
index 5c83dda89619..e47e101c3ea7 100644
--- a/src/components/ScreenWrapper/index.js
+++ b/src/components/ScreenWrapper/index.js
@@ -38,13 +38,7 @@ class ScreenWrapper extends React.Component {
             Navigation.dismissModal();
         }, shortcutConfig.descriptionKey, shortcutConfig.modifiers, true);
 
-        this.unsubscribeTransitionStart = this.props.navigation.addListener('transitionStart', () => {
-            Navigation.setIsNavigating(true);
-        });
-
         this.unsubscribeTransitionEnd = this.props.navigation.addListener('transitionEnd', (event) => {
-            Navigation.setIsNavigating(false);
-
             // Prevent firing the prop callback when user is exiting the page.
             if (lodashGet(event, 'data.closing')) {
                 return;
@@ -85,9 +79,6 @@ class ScreenWrapper extends React.Component {
         if (this.unsubscribeTransitionEnd) {
             this.unsubscribeTransitionEnd();
         }
-        if (this.unsubscribeTransitionStart) {
-            this.unsubscribeTransitionStart();
-        }
         if (this.beforeRemoveSubscription) {
             this.beforeRemoveSubscription();
         }
diff --git a/src/languages/en.js b/src/languages/en.js
index 765be98ed4dc..52c7abbf02f7 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -124,6 +124,8 @@ export default {
         youAppearToBeOffline: 'You appear to be offline.',
         thisFeatureRequiresInternet: 'This feature requires an active internet connection to be used.',
         areYouSure: 'Are you sure?',
+        verify: 'Verify',
+        yesContinue: 'Yes, continue',
         zipCodeExample: 'e.g. 12345, 12345-1234, 12345 1234',
         websiteExample: 'e.g. https://www.expensify.com',
     },
@@ -349,6 +351,20 @@ export default {
     contacts: {
         contactMethod: 'Contact method',
         contactMethods: 'Contact methods',
+        helpTextBeforeEmail: 'Add more ways for people to find you, and forward receipts to ',
+        helpTextAfterEmail: ' from multiple email addresses.',
+        pleaseVerify: 'Please verify this contact method',
+        getInTouch: "Whenever we need to get in touch with you, we'll use this contact method.",
+        enterMagicCode: ({contactMethod}) => `Please enter the magic code sent to ${contactMethod}`,
+        yourDefaultContactMethod: 'This is your current default contact method. You will not be able to delete this contact method until you set an alternative default by selecting another contact method and pressing “Set as default”.',
+        removeContactMethod: 'Remove contact method',
+        removeAreYouSure: 'Are you sure you want to remove this contact method? This action cannot be undone.',
+        resendMagicCode: 'Resend magic code',
+        genericFailureMessages: {
+            requestContactMethodValidateCode: 'Failed to send a new magic code. Please wait a bit and try again.',
+            validateSecondaryLogin: 'Failed to validate contact method with given magic code. Please request a new code and try again.',
+            deleteContactMethod: 'Failed to delete contact method. Please reach out to Concierge for help.',
+        },
     },
     pronouns: {
         coCos: 'Co / Cos',
diff --git a/src/languages/es.js b/src/languages/es.js
index f7012c3d6654..16760d305a94 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -123,6 +123,8 @@ export default {
         youAppearToBeOffline: 'Parece que estás desconectado.',
         thisFeatureRequiresInternet: 'Esta función requiere una conexión a Internet activa para ser utilizada.',
         areYouSure: '¿Estás seguro?',
+        verify: 'Verifique',
+        yesContinue: 'Sí, Continuar',
         zipCodeExample: 'p. ej. 12345, 12345-1234, 12345 1234',
         websiteExample: 'p. ej. https://www.expensify.com',
     },
@@ -348,6 +350,20 @@ export default {
     contacts: {
         contactMethod: 'Método de contacto',
         contactMethods: 'Métodos de contacto',
+        helpTextBeforeEmail: 'Añade más formas de que la gente te encuentre y reenvía los recibos a ',
+        helpTextAfterEmail: ' desde varias direcciones de correo electrónico.',
+        pleaseVerify: 'Por favor verifica este método de contacto',
+        getInTouch: 'Utilizaremos este método de contacto cuando necesitemos contactarte.',
+        enterMagicCode: ({contactMethod}) => `Por favor, introduce el código mágico enviado a ${contactMethod}`,
+        yourDefaultContactMethod: 'Este es tu método de contacto predeterminado. No podrás eliminarlo hasta que añadas otro método de contacto y lo marques como predeterminado pulsando "Establecer como predeterminado".',
+        removeContactMethod: 'Eliminar método de contacto',
+        removeAreYouSure: '¿Estás seguro de que quieres eliminar este método de contacto? Esta acción no se puede deshacer.',
+        resendMagicCode: 'Reenviar código mágico',
+        genericFailureMessages: {
+            requestContactMethodValidateCode: 'No se ha podido enviar un nuevo código mágico. Espera un rato y vuelve a intentarlo.',
+            validateSecondaryLogin: 'No se ha podido validar el método de contacto con el código mágico provisto. Solicita un nuevo código y vuelve a intentarlo.',
+            deleteContactMethod: 'No se ha podido eliminar el método de contacto. Por favor contacta con Concierge para obtener ayuda.',
+        },
     },
     pronouns: {
         coCos: 'Co / Cos',
diff --git a/src/libs/ErrorUtils.js b/src/libs/ErrorUtils.js
index 89d2029c7457..a51cd080fda9 100644
--- a/src/libs/ErrorUtils.js
+++ b/src/libs/ErrorUtils.js
@@ -1,4 +1,5 @@
 import _ from 'underscore';
+import lodashGet from 'lodash/get';
 import CONST from '../CONST';
 
 /**
@@ -54,6 +55,27 @@ function getLatestErrorMessage(onyxData) {
         .value();
 }
 
+/**
+ * @param {Object} onyxData
+ * @param {Object} onyxData.errorFields
+ * @param {String} fieldName
+ * @returns {Object}
+ */
+function getLatestErrorField(onyxData, fieldName) {
+    const errorsForField = lodashGet(onyxData, ['errorFields', fieldName], {});
+
+    if (_.isEmpty(errorsForField)) {
+        return {};
+    }
+    return _.chain(errorsForField)
+        .keys()
+        .sortBy()
+        .reverse()
+        .map(key => ({[key]: errorsForField[key]}))
+        .first()
+        .value();
+}
+
 /**
  * Method used to generate error message for given inputID
  * @param {Object} errors - An object containing current errors in the form
@@ -74,8 +96,8 @@ function addErrorMessage(errors, inputID, message) {
 }
 
 export {
-    // eslint-disable-next-line import/prefer-default-export
     getAuthenticateErrorMessage,
     getLatestErrorMessage,
+    getLatestErrorField,
     addErrorMessage,
 };
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
index 405ea6c6c332..7b46354e9391 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js
@@ -280,6 +280,13 @@ const SettingsModalStackNavigator = createModalStackNavigator([
         },
         name: 'Settings_ContactMethods',
     },
+    {
+        getComponent: () => {
+            const SettingsContactMethodDetailsPage = require('../../../pages/settings/Profile/Contacts/ContactMethodDetailsPage').default;
+            return SettingsContactMethodDetailsPage;
+        },
+        name: 'Settings_ContactMethodDetails',
+    },
     {
         getComponent: () => {
             const SettingsAddSecondaryLoginPage = require('../../../pages/settings/Profile/Contacts/AddSecondaryLoginPage').default;
diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js
index 7d1cacc07089..5e04c37546f3 100644
--- a/src/libs/Navigation/Navigation.js
+++ b/src/libs/Navigation/Navigation.js
@@ -30,7 +30,6 @@ let reportScreenIsReadyPromise = new Promise((resolve) => {
 
 let isLoggedIn = false;
 let pendingRoute = null;
-let isNavigating = false;
 
 Onyx.connect({
     key: ONYXKEYS.SESSION,
@@ -56,27 +55,13 @@ function setDidTapNotification() {
  * @returns {Boolean}
  */
 function canNavigate(methodName, params = {}) {
-    if (navigationRef.isReady() && !isNavigating) {
+    if (navigationRef.isReady()) {
         return true;
     }
-
-    if (isNavigating) {
-        Log.hmmm(`[Navigation] ${methodName} failed because navigation is progress`, params);
-        return false;
-    }
-
     Log.hmmm(`[Navigation] ${methodName} failed because navigation ref was not yet ready`, params);
     return false;
 }
 
-/**
- * Sets Navigation State
- * @param {Boolean} isNavigatingValue
- */
-function setIsNavigating(isNavigatingValue) {
-    isNavigating = isNavigatingValue;
-}
-
 /**
  * Opens the LHN drawer.
  * @private
@@ -129,7 +114,6 @@ function goBack(shouldOpenDrawer = true) {
         }
         return;
     }
-
     navigationRef.current.goBack();
 }
 
@@ -331,7 +315,6 @@ export default {
     resetDrawerIsReadyPromise,
     resetIsReportScreenReadyPromise,
     isDrawerRoute,
-    setIsNavigating,
     isReportScreenReady,
     setIsReportScreenIsReady,
 };
diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js
index 080b8d148cff..a096a7421867 100644
--- a/src/libs/Navigation/linkingConfig.js
+++ b/src/libs/Navigation/linkingConfig.js
@@ -124,6 +124,9 @@ export default {
                         path: ROUTES.SETTINGS_CONTACT_METHODS,
                         exact: true,
                     },
+                    Settings_ContactMethodDetails: {
+                        path: ROUTES.SETTINGS_CONTACT_METHOD_DETAILS,
+                    },
                     Settings_Add_Secondary_Login: {
                         path: ROUTES.SETTINGS_ADD_LOGIN,
                     },
diff --git a/src/libs/UserUtils.js b/src/libs/UserUtils.js
new file mode 100644
index 000000000000..748ad18dac69
--- /dev/null
+++ b/src/libs/UserUtils.js
@@ -0,0 +1,68 @@
+import _ from 'underscore';
+import lodashGet from 'lodash/get';
+import CONST from '../CONST';
+
+/**
+ * Searches through given loginList for any contact method / login with an error.
+ *
+ * Example that should return false:
+ * {{
+ *      test@test.com: {
+ *          errorFields: {
+ *              validateCodeSent: null
+ *          }
+ *      }
+ * }}
+ *
+ * Example that should return true:
+ * {{
+ *      test@test.com: {
+ *          errorFields: {
+ *              validateCodeSent: { 18092081290: 'An error' }
+ *          }
+ *      }
+ * }}
+ *
+ * @param {Object} loginList
+ * @param {Object} loginList.errorFields
+ * @returns {Boolean}
+ */
+function hasLoginListError(loginList) {
+    return _.some(loginList, login => _.some(lodashGet(login, 'errorFields', {}), field => !_.isEmpty(field)));
+}
+
+/**
+ * Searches through given loginList for any contact method / login that requires
+ * an Info brick road status indicator. Currently this only applies if the user
+ * has an unvalidated contact method.
+ *
+ * @param {Object} loginList
+ * @param {String} loginList.validatedDate
+ * @returns {Boolean}
+ */
+function hasLoginListInfo(loginList) {
+    return _.some(loginList, login => _.isEmpty(login.validatedDate));
+}
+
+/**
+ * Gets the appropriate brick road indicator status for a given loginList.
+ * Error status is higher priority, so we check for that first.
+ *
+ * @param {Object} loginList
+ * @returns {String}
+ */
+function getLoginListBrickRoadIndicator(loginList) {
+    if (hasLoginListError(loginList)) {
+        return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR;
+    }
+    if (hasLoginListInfo(loginList)) {
+        return CONST.BRICK_ROAD_INDICATOR_STATUS.INFO;
+    }
+    return '';
+}
+
+export {
+    hasLoginListError,
+    hasLoginListInfo,
+    getLoginListBrickRoadIndicator,
+};
diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js
index 7e7b51e93d3d..1c9a296c975e 100644
--- a/src/libs/actions/User.js
+++ b/src/libs/actions/User.js
@@ -19,6 +19,7 @@ import * as SequentialQueue from '../Network/SequentialQueue';
 import PusherUtils from '../PusherUtils';
 import * as Report from './Report';
 import * as ReportActionsUtils from '../ReportActionsUtils';
+import DateUtils from '../DateUtils';
 import * as Session from './Session';
 
 let currentUserAccountID = '';
@@ -100,6 +101,61 @@ function resendValidateCode(login) {
     Session.resendValidateCode(login);
 }
 
+/**
+ * Requests a new validate code be sent for the passed contact method
+ *
+ * @param {String} contactMethod - the new contact method that the user is trying to verify
+ */
+function requestContactMethodValidateCode(contactMethod) {
+    const optimisticData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                validateCodeSent: true,
+                errorFields: {
+                    validateCodeSent: null,
+                },
+                pendingFields: {
+                    validateCodeSent: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                },
+            },
+        },
+    }];
+    const successData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                pendingFields: {
+                    validateCodeSent: null,
+                },
+            },
+        },
+    }];
+    const failureData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                validateCodeSent: false,
+                errorFields: {
+                    validateCodeSent: {
+                        [DateUtils.getMicroseconds()]: Localize.translateLocal('contacts.genericFailureMessages.requestContactMethodValidateCode'),
+                    },
+                },
+                pendingFields: {
+                    validateCodeSent: null,
+                },
+            },
+        },
+    }];
+
+    API.write('RequestContactMethodValidateCode', {
+        email: contactMethod,
+    }, {optimisticData, successData, failureData});
+}
+
 /**
  * Sets whether or not the user is subscribed to Expensify news
  *
@@ -162,6 +218,78 @@ function setSecondaryLoginAndNavigate(login, password) {
     });
 }
 
+/**
+ * Delete a specific contact method
+ *
+ * @param {String} contactMethod - the contact method being deleted
+ * @param {Object} oldLoginData
+ */
+function deleteContactMethod(contactMethod, oldLoginData) {
+    const optimisticData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                partnerUserID: '',
+                errorFields: {
+                    deletedLogin: null,
+                },
+                pendingFields: {
+                    deletedLogin: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                },
+            },
+        },
+    }];
+    const successData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: null,
+        },
+    }];
+    const failureData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                ...oldLoginData,
+                errorFields: {
+                    deletedLogin: {
+                        [DateUtils.getMicroseconds()]: Localize.translateLocal('contacts.genericFailureMessages.deleteContactMethod'),
+                    },
+                },
+                pendingFields: {
+                    deletedLogin: null,
+                },
+            },
+        },
+    }];
+
+    API.write('DeleteContactMethod', {
+        partnerUserID: contactMethod,
+    }, {optimisticData, successData, failureData});
+    Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS);
+}
+
+/**
+ * Clears any possible stored errors for a specific field on a contact method
+ *
+ * @param {String} contactMethod
+ * @param {String} fieldName
+ */
+function clearContactMethodErrors(contactMethod, fieldName) {
+    Onyx.merge(ONYXKEYS.LOGIN_LIST, {
+        [contactMethod]: {
+            errorFields: {
+                [fieldName]: null,
+            },
+            pendingFields: {
+                [fieldName]: null,
+            },
+        },
+    });
+}
+
 /**
  * Validates a login given an accountID and validation code
  *
@@ -187,6 +315,62 @@ function validateLogin(accountID, validateCode) {
     Navigation.navigate(ROUTES.HOME);
 }
 
+/**
+ * Validates a secondary login / contact method
+ *
+ * @param {String} contactMethod - The contact method the user is trying to verify
+ * @param {String} validateCode
+ */
+function validateSecondaryLogin(contactMethod, validateCode) {
+    const optimisticData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                errorFields: {
+                    validateLogin: null,
+                },
+                pendingFields: {
+                    validateLogin: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                },
+            },
+        },
+    }];
+    const successData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                pendingFields: {
+                    validateLogin: null,
+                },
+            },
+        },
+    }];
+    const failureData = [{
+        onyxMethod: CONST.ONYX.METHOD.MERGE,
+        key: ONYXKEYS.LOGIN_LIST,
+        value: {
+            [contactMethod]: {
+                errorFields: {
+                    validateLogin: {
+                        [DateUtils.getMicroseconds()]: Localize.translateLocal('contacts.genericFailureMessages.validateSecondaryLogin'),
+                    },
+                },
+                pendingFields: {
+                    validateLogin: null,
+                },
+            },
+        },
+    }];
+
+    API.write('ValidateSecondaryLogin', {
+        partnerUserID: contactMethod,
+        validateCode,
+    }, {optimisticData, successData, failureData});
+    Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS);
+}
+
 /**
  * Checks the blockedFromConcierge object to see if it has an expiresAt key,
  * and if so whether the expiresAt date of a user's ban is before right now
@@ -474,9 +658,13 @@ export {
     updatePassword,
     closeAccount,
     resendValidateCode,
+    requestContactMethodValidateCode,
     updateNewsletterSubscription,
     setSecondaryLoginAndNavigate,
+    deleteContactMethod,
+    clearContactMethodErrors,
     validateLogin,
+    validateSecondaryLogin,
     isBlockedFromConcierge,
     subscribeToUserEvents,
     updatePreferredSkinTone,
diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js
index 1fe9a18a8260..0593c10e4fb6 100755
--- a/src/pages/settings/InitialSettingsPage.js
+++ b/src/pages/settings/InitialSettingsPage.js
@@ -34,6 +34,7 @@ import ConfirmModal from '../../components/ConfirmModal';
 import * as ReportUtils from '../../libs/ReportUtils';
 import * as Link from '../../libs/actions/Link';
 import OfflineWithFeedback from '../../components/OfflineWithFeedback';
+import * as UserUtils from '../../libs/UserUtils';
 import policyMemberPropType from '../policyMemberPropType';
 
 const propTypes = {
@@ -81,6 +82,15 @@ const propTypes = {
     /** Information about the user accepting the terms for payments */
     walletTerms: walletTermsPropTypes,
 
+    /** Login list for the user that is signed in */
+    loginList: PropTypes.shape({
+        /** Date login was validated, used to show brickroad info status */
+        validatedDate: PropTypes.string,
+
+        /** Field-specific server side errors keyed by microtime */
+        errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+    }),
+
     /** List of policy members */
     policyMembers: PropTypes.objectOf(policyMemberPropType),
 
@@ -98,6 +108,7 @@ const defaultProps = {
     walletTerms: {},
     bankAccountList: {},
     cardList: {},
+    loginList: {},
     policyMembers: {},
     ...withCurrentUserPersonalDetailsDefaultProps,
 };
@@ -152,6 +163,7 @@ class InitialSettingsPage extends React.Component {
             .filter(policy => policy && policy.type === CONST.POLICY.TYPE.FREE && policy.role === CONST.POLICY.ROLE.ADMIN)
             .find(policy => PolicyUtils.hasPolicyError(policy) || PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy, this.props.policyMembers))
             .value() ? 'error' : null;
+        const profileBrickRoadIndicator = UserUtils.getLoginListBrickRoadIndicator(this.props.loginList);
 
         return ([
             {
@@ -166,6 +178,7 @@ class InitialSettingsPage extends React.Component {
                 translationKey: 'common.profile',
                 icon: Expensicons.Profile,
                 action: () => { App.openProfile(); },
+                brickRoadIndicator: profileBrickRoadIndicator,
             },
             {
                 translationKey: 'common.preferences',
@@ -216,7 +229,6 @@ class InitialSettingsPage extends React.Component {
                 iconType={item.iconType}
                 onPress={item.action}
                 iconStyles={item.iconStyles}
-                iconFill={item.iconFill}
                 shouldShowRightIcon
                 iconRight={item.iconRight}
                 badgeText={this.getWalletBalance(isPaymentItem)}
@@ -349,6 +361,9 @@ export default compose(
         walletTerms: {
             key: ONYXKEYS.WALLET_TERMS,
         },
+        loginList: {
+            key: ONYXKEYS.LOGIN_LIST,
+        },
     }),
     withNetwork(),
 )(InitialSettingsPage);
diff --git a/src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js b/src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js
index 36571a14d4a6..48232251df5b 100755
--- a/src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js
+++ b/src/pages/settings/Profile/Contacts/AddSecondaryLoginPage.js
@@ -117,7 +117,7 @@ class AddSecondaryLoginPage extends Component {
                     onCloseButtonPress={() => Navigation.dismissModal()}
                 />
                 {/* We use keyboardShouldPersistTaps="handled" to prevent the keyboard from being hidden when switching focus on input fields  */}
-                <ScrollView style={styles.flex1} contentContainerStyle={styles.p5} keyboardShouldPersistTaps="handled">
+                <ScrollView style={styles.flex1} contentContainerStyle={[styles.ph5, styles.mv3]} keyboardShouldPersistTaps="handled">
                     <Text style={[styles.mb6]}>
                         {this.props.translate(this.formType === CONST.LOGIN_TYPE.PHONE
                             ? 'addSecondaryLoginPage.enterPreferredPhoneNumberToSendValidationLink'
@@ -134,6 +134,7 @@ class AddSecondaryLoginPage extends Component {
                             keyboardType={this.formType === CONST.LOGIN_TYPE.PHONE
                                 ? CONST.KEYBOARD_TYPE.PHONE_PAD : CONST.KEYBOARD_TYPE.EMAIL_ADDRESS}
                             returnKeyType="done"
+                            autoComplete={this.formType === CONST.LOGIN_TYPE.PHONE ? 'tel' : 'email'}
                         />
                     </View>
                     {!Permissions.canUsePasswordlessLogins(this.props.betas) && (
diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js
new file mode 100644
index 000000000000..eca350a4e691
--- /dev/null
+++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js
@@ -0,0 +1,261 @@
+import Str from 'expensify-common/lib/str';
+import lodashGet from 'lodash/get';
+import React, {Component} from 'react';
+import {View, ScrollView} from 'react-native';
+import PropTypes from 'prop-types';
+import {withOnyx} from 'react-native-onyx';
+import Navigation from '../../../../libs/Navigation/Navigation';
+import ROUTES from '../../../../ROUTES';
+import ScreenWrapper from '../../../../components/ScreenWrapper';
+import HeaderWithCloseButton from '../../../../components/HeaderWithCloseButton';
+import compose from '../../../../libs/compose';
+import ONYXKEYS from '../../../../ONYXKEYS';
+import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize';
+import MenuItem from '../../../../components/MenuItem';
+import styles from '../../../../styles/styles';
+import * as Expensicons from '../../../../components/Icon/Expensicons';
+import Text from '../../../../components/Text';
+import OfflineWithFeedback from '../../../../components/OfflineWithFeedback';
+import ConfirmModal from '../../../../components/ConfirmModal';
+import * as User from '../../../../libs/actions/User';
+import TextInput from '../../../../components/TextInput';
+import CONST from '../../../../CONST';
+import Icon from '../../../../components/Icon';
+import colors from '../../../../styles/colors';
+import Button from '../../../../components/Button';
+import * as ErrorUtils from '../../../../libs/ErrorUtils';
+import themeColors from '../../../../styles/themes/default';
+import NotFoundPage from '../../../ErrorPage/NotFoundPage';
+import * as ValidationUtils from '../../../../libs/ValidationUtils';
+
+const propTypes = {
+    /* Onyx Props */
+
+    /** Login list for the user that is signed in */
+    loginList: PropTypes.shape({
+        /** Value of partner name */
+        partnerName: PropTypes.string,
+
+        /** Phone/Email associated with user */
+        partnerUserID: PropTypes.string,
+
+        /** Date when login was validated */
+        validatedDate: PropTypes.string,
+
+        /** Field-specific server side errors keyed by microtime */
+        errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+
+        /** Field-specific pending states for offline UI status */
+        pendingFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+    }),
+
+    /** Current user session */
+    session: PropTypes.shape({
+        email: PropTypes.string.isRequired,
+    }),
+
+    /** Route params */
+    route: PropTypes.shape({
+        params: PropTypes.shape({
+            /** Passed via route /settings/profile/contact-methods/:contactMethod/details */
+            contactMethod: PropTypes.string,
+        }),
+    }),
+
+    ...withLocalizePropTypes,
+};
+
+const defaultProps = {
+    loginList: {},
+    session: {
+        email: null,
+    },
+    route: {
+        params: {
+            contactMethod: '',
+        },
+    },
+};
+
+class ContactMethodDetailsPage extends Component {
+    constructor(props) {
+        super(props);
+
+        this.toggleDeleteModal = this.toggleDeleteModal.bind(this);
+        this.confirmDeleteAndHideModal = this.confirmDeleteAndHideModal.bind(this);
+        this.resendValidateCode = this.resendValidateCode.bind(this);
+        this.getContactMethod = this.getContactMethod.bind(this);
+        this.validateAndSubmitCode = this.validateAndSubmitCode.bind(this);
+
+        this.state = {
+            formError: '',
+            isDeleteModalOpen: false,
+            validateCode: '',
+        };
+    }
+
+    /**
+     * Gets the current contact method from the route params
+     *
+     * @returns {string}
+     */
+    getContactMethod() {
+        return decodeURIComponent(lodashGet(this.props.route, 'params.contactMethod'));
+    }
+
+    /**
+     * Toggle delete confirm modal visibility
+     * @param {Boolean} isOpen
+     */
+    toggleDeleteModal(isOpen) {
+        this.setState({isDeleteModalOpen: isOpen});
+    }
+
+    /**
+     * Delete the contact method and hide the modal
+     */
+    confirmDeleteAndHideModal() {
+        this.toggleDeleteModal(false);
+        User.deleteContactMethod(this.getContactMethod());
+    }
+
+    /**
+     * Request a validate code / magic code be sent to verify this contact method
+     */
+    resendValidateCode() {
+        User.requestContactMethodValidateCode(this.getContactMethod());
+    }
+
+    /**
+     * Attempt to validate this contact method
+     */
+    validateAndSubmitCode() {
+        if (!this.state.validateCode) {
+            this.setState({formError: 'validateCodeForm.error.pleaseFillMagicCode'});
+        } else if (!ValidationUtils.isValidValidateCode(this.state.validateCode)) {
+            this.setState({formError: 'validateCodeForm.error.incorrectMagicCode'});
+        } else {
+            this.setState({formError: ''});
+            User.validateSecondaryLogin(this.getContactMethod(), this.state.validateCode);
+        }
+    }
+
+    render() {
+        const contactMethod = this.getContactMethod();
+        const loginData = this.props.loginList[contactMethod];
+        if (!contactMethod || !loginData) {
+            return <NotFoundPage />;
+        }
+
+        const isDefaultContactMethod = this.props.session.email === loginData.partnerUserID;
+        const hasMagicCodeBeenSent = lodashGet(this.props.loginList, [contactMethod, 'validateCodeSent'], false);
+        const formErrorText = this.state.formError ? this.props.translate(this.state.formError) : '';
+
+        return (
+            <ScreenWrapper>
+                <HeaderWithCloseButton
+                    title={Str.removeSMSDomain(contactMethod)}
+                    shouldShowBackButton
+                    onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHODS)}
+                    onCloseButtonPress={() => Navigation.dismissModal(true)}
+                />
+                <ScrollView keyboardShouldPersistTaps="handled">
+                    <ConfirmModal
+                        title={this.props.translate('contacts.removeContactMethod')}
+                        onConfirm={this.confirmDeleteAndHideModal}
+                        onCancel={() => this.toggleDeleteModal(false)}
+                        prompt={this.props.translate('contacts.removeAreYouSure')}
+                        confirmText={this.props.translate('common.yesContinue')}
+                        isVisible={this.state.isDeleteModalOpen}
+                        danger
+                    />
+                    {!loginData.validatedDate && (
+                        <View style={[styles.ph5, styles.mt3, styles.mb7]}>
+                            <View style={[styles.flexRow, styles.alignItemsCenter, styles.mb1]}>
+                                <Icon src={Expensicons.DotIndicator} fill={colors.green} />
+                                <View style={[styles.flex1, styles.ml4]}>
+                                    <Text>
+                                        {this.props.translate('contacts.enterMagicCode', {contactMethod})}
+                                    </Text>
+                                </View>
+                            </View>
+                            <TextInput
+                                label={this.props.translate('common.magicCode')}
+                                name="validateCode"
+                                value={this.state.validateCode}
+                                onChangeText={text => this.setState({validateCode: text})}
+                                keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD}
+                                errorText={formErrorText}
+                            />
+                            <OfflineWithFeedback
+                                pendingAction={lodashGet(loginData, 'pendingFields.validateCodeSent', null)}
+                                errors={ErrorUtils.getLatestErrorField(loginData, 'validateCodeSent')}
+                                errorRowStyles={[styles.mt2]}
+                                onClose={() => User.clearContactMethodErrors(contactMethod, 'validateCodeSent')}
+                            >
+                                <View
+                                    style={[styles.mt2, styles.dFlex, styles.flexRow]}
+                                >
+                                    <Text style={[styles.link, styles.mr1]} onPress={this.resendValidateCode}>
+                                        {this.props.translate('contacts.resendMagicCode')}
+                                    </Text>
+                                    {hasMagicCodeBeenSent && (
+                                        <Icon src={Expensicons.Checkmark} fill={colors.green} />
+                                    )}
+                                </View>
+                            </OfflineWithFeedback>
+                            <OfflineWithFeedback
+                                pendingAction={lodashGet(loginData, 'pendingFields.validateLogin', null)}
+                                errors={ErrorUtils.getLatestErrorField(loginData, 'validateLogin')}
+                                errorRowStyles={[styles.mt2]}
+                                onClose={() => User.clearContactMethodErrors(contactMethod, 'validateLogin')}
+                            >
+                                <Button
+                                    text={this.props.translate('common.verify')}
+                                    onPress={this.validateAndSubmitCode}
+                                    style={[styles.mt4]}
+                                    success
+                                    pressOnEnter
+                                />
+                            </OfflineWithFeedback>
+                        </View>
+                    )}
+                    {isDefaultContactMethod ? (
+                        <Text style={[styles.ph5, styles.mv3]}>
+                            {this.props.translate('contacts.yourDefaultContactMethod')}
+                        </Text>
+                    ) : (
+                        <OfflineWithFeedback
+                            pendingAction={lodashGet(loginData, 'pendingFields.deletedLogin', null)}
+                            errors={ErrorUtils.getLatestErrorField(loginData, 'deletedLogin')}
+                            errorRowStyles={[styles.mt6]}
+                            onClose={() => User.clearContactMethodErrors(contactMethod, 'deletedLogin')}
+                        >
+                            <MenuItem
+                                title={this.props.translate('common.remove')}
+                                icon={Expensicons.Trashcan}
+                                iconFill={themeColors.danger}
+                                onPress={() => this.toggleDeleteModal(true)}
+                            />
+                        </OfflineWithFeedback>
+                    )}
+                </ScrollView>
+            </ScreenWrapper>
+        );
+    }
+}
+
+ContactMethodDetailsPage.propTypes = propTypes;
+ContactMethodDetailsPage.defaultProps = defaultProps;
+
+export default compose(
+    withLocalize,
+    withOnyx({
+        loginList: {
+            key: ONYXKEYS.LOGIN_LIST,
+        },
+        session: {
+            key: ONYXKEYS.SESSION,
+        },
+    }),
+)(ContactMethodDetailsPage);
diff --git a/src/pages/settings/Profile/Contacts/ContactMethodsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodsPage.js
index edb998047c11..a205eb7da709 100644
--- a/src/pages/settings/Profile/Contacts/ContactMethodsPage.js
+++ b/src/pages/settings/Profile/Contacts/ContactMethodsPage.js
@@ -1,13 +1,13 @@
 import Str from 'expensify-common/lib/str';
 import lodashGet from 'lodash/get';
 import PropTypes from 'prop-types';
-import React, {Component} from 'react';
+import React from 'react';
+import {View} from 'react-native';
 import {ScrollView} from 'react-native-gesture-handler';
 import {withOnyx} from 'react-native-onyx';
 import _ from 'underscore';
 import HeaderWithCloseButton from '../../../../components/HeaderWithCloseButton';
 import ScreenWrapper from '../../../../components/ScreenWrapper';
-import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '../../../../components/withCurrentUserPersonalDetails';
 import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize';
 import CONST from '../../../../CONST';
 import compose from '../../../../libs/compose';
@@ -15,124 +15,157 @@ import Navigation from '../../../../libs/Navigation/Navigation';
 import ONYXKEYS from '../../../../ONYXKEYS';
 import ROUTES from '../../../../ROUTES';
 import LoginField from './LoginField';
+import MenuItem from '../../../../components/MenuItem';
+import Text from '../../../../components/Text';
+import styles from '../../../../styles/styles';
+import CopyTextToClipboard from '../../../../components/CopyTextToClipboard';
+import OfflineWithFeedback from '../../../../components/OfflineWithFeedback';
 
 const propTypes = {
     /* Onyx Props */
 
     /** Login list for the user that is signed in */
     loginList: PropTypes.shape({
-        /** Value of partner name */
+        /** The partner creating the account. It depends on the source: website, mobile, integrations, ... */
         partnerName: PropTypes.string,
 
         /** Phone/Email associated with user */
         partnerUserID: PropTypes.string,
 
-        /** Date of when login was validated */
+        /** The date when the login was validated, used to show the brickroad status */
         validatedDate: PropTypes.string,
+
+        /** Field-specific server side errors keyed by microtime */
+        errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+
+        /** Field-specific pending states for offline UI status */
+        pendingFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+    }),
+
+    /** Current user session */
+    session: PropTypes.shape({
+        email: PropTypes.string.isRequired,
     }),
 
     ...withLocalizePropTypes,
-    ...withCurrentUserPersonalDetailsPropTypes,
 };
 
 const defaultProps = {
     loginList: {},
-    ...withCurrentUserPersonalDetailsDefaultProps,
+    session: {
+        email: null,
+    },
 };
 
-class ContactMethodsPage extends Component {
-    constructor(props) {
-        super(props);
-
-        this.state = {
-            logins: this.getLogins(),
-        };
-
-        this.getLogins = this.getLogins.bind(this);
-    }
+const ContactMethodsPage = (props) => {
+    let hasPhoneNumberLogin = false;
+    let hasEmailLogin = false;
 
-    componentDidUpdate(prevProps) {
-        let stateToUpdate = {};
+    const loginMenuItems = _.map(props.loginList, (login, loginName) => {
+        const pendingAction = lodashGet(login, 'pendingFields.deletedLogin', null);
+        if (!login.partnerUserID && _.isEmpty(pendingAction)) {
+            return null;
+        }
 
-        // Recalculate logins if loginList has changed
-        if (_.keys(this.props.loginList).length !== _.keys(prevProps.loginList).length) {
-            stateToUpdate = {logins: this.getLogins()};
+        let description = '';
+        if (props.session.email === login.partnerUserID) {
+            description = props.translate('contacts.getInTouch');
+        } else if (!login.validatedDate) {
+            description = props.translate('contacts.pleaseVerify');
+        }
+        let indicator = null;
+        if (_.some(lodashGet(login, 'errorFields', {}), errorField => !_.isEmpty(errorField))) {
+            indicator = CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR;
+        } else if (!login.validatedDate) {
+            indicator = CONST.BRICK_ROAD_INDICATOR_STATUS.INFO;
         }
 
-        if (_.isEmpty(stateToUpdate)) {
-            return;
+        // Temporary checks to determine if we need to show specific LoginField
+        // components. This check will be removed soon by this follow up PR:
+        // https://github.com/Expensify/App/pull/15330
+        // Also we still use login.partnerUserID here even though it could have been
+        // deleted optimistically because if the deletion is pending, we want to show
+        // the option to add a new phone or email login, so we don't want to find
+        // that login type in the list here.
+        if (Str.isValidPhone(Str.removeSMSDomain(login.partnerUserID))) {
+            hasPhoneNumberLogin = true;
+        } else if (Str.isValidEmail(login.partnerUserID)) {
+            hasEmailLogin = true;
         }
 
-        // eslint-disable-next-line react/no-did-update-set-state
-        this.setState(stateToUpdate);
-    }
-
-    /**
-     * Get the most validated login of each type
-     *
-     * @returns {Object}
-     */
-    getLogins() {
-        return _.reduce(_.values(this.props.loginList), (logins, currentLogin) => {
-            const type = Str.isSMSLogin(currentLogin.partnerUserID) ? CONST.LOGIN_TYPE.PHONE : CONST.LOGIN_TYPE.EMAIL;
-            const login = Str.removeSMSDomain(currentLogin.partnerUserID);
-
-            // If there's already a login type that's validated and/or currentLogin isn't valid then return early
-            if ((login !== lodashGet(this.props.currentUserPersonalDetails, 'login')) && !_.isEmpty(logins[type])
-                && (logins[type].validatedDate || !currentLogin.validatedDate)) {
-                return logins;
-            }
-            return {
-                ...logins,
-                [type]: {
-                    ...currentLogin,
-                    type,
-                    partnerUserID: Str.removeSMSDomain(currentLogin.partnerUserID),
-                },
-            };
-        }, {
-            phone: {},
-            email: {},
-        });
-    }
-
-    render() {
+        // Default to using login key if we deleted login.partnerUserID optimistically
+        // but still need to show the pending login being deleted while offline.
+        const partnerUserID = login.partnerUserID || loginName;
         return (
-            <ScreenWrapper>
-                <HeaderWithCloseButton
-                    title={this.props.translate('contacts.contactMethods')}
-                    shouldShowBackButton
-                    onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_PROFILE)}
-                    onCloseButtonPress={() => Navigation.dismissModal(true)}
+            <OfflineWithFeedback
+                pendingAction={pendingAction}
+                key={partnerUserID}
+            >
+                <MenuItem
+                    title={Str.removeSMSDomain(partnerUserID)}
+                    description={description}
+                    onPress={() => Navigation.navigate(ROUTES.getEditContactMethodRoute(partnerUserID))}
+                    brickRoadIndicator={indicator}
+                    shouldShowBasicTitle
+                    shouldShowRightIcon
+                    disabled={!_.isEmpty(pendingAction)}
                 />
-                <ScrollView>
+            </OfflineWithFeedback>
+        );
+    });
+
+    return (
+        <ScreenWrapper>
+            <HeaderWithCloseButton
+                title={props.translate('contacts.contactMethods')}
+                shouldShowBackButton
+                onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_PROFILE)}
+                onCloseButtonPress={() => Navigation.dismissModal(true)}
+            />
+            <ScrollView>
+                <View style={[styles.ph5, styles.mv3, styles.flexRow, styles.flexWrap]}>
+                    <Text>
+                        {props.translate('contacts.helpTextBeforeEmail')}
+                        <CopyTextToClipboard
+                            text="receipts@expensify.com"
+                            textStyles={[styles.textBlue]}
+                        />
+                        <Text>{props.translate('contacts.helpTextAfterEmail')}</Text>
+                    </Text>
+                </View>
+                {loginMenuItems}
+                {/* The below fields will be removed soon, when we implement the new Add Contact Method page */}
+                {!hasEmailLogin && (
                     <LoginField
-                        label={this.props.translate('profilePage.emailAddress')}
-                        type="email"
-                        login={this.state.logins.email}
-                        defaultValue={this.state.logins.email}
+                        label={props.translate('profilePage.emailAddress')}
+                        type={CONST.LOGIN_TYPE.EMAIL}
+                        login={{}}
                     />
+                )}
+                {!hasPhoneNumberLogin && (
                     <LoginField
-                        label={this.props.translate('common.phoneNumber')}
-                        type="phone"
-                        login={this.state.logins.phone}
-                        defaultValue={this.state.logins.phone}
+                        label={props.translate('common.phoneNumber')}
+                        type={CONST.LOGIN_TYPE.PHONE}
+                        login={{}}
                     />
-                </ScrollView>
-            </ScreenWrapper>
-        );
-    }
-}
+                )}
+            </ScrollView>
+        </ScreenWrapper>
+    );
+};
 
 ContactMethodsPage.propTypes = propTypes;
 ContactMethodsPage.defaultProps = defaultProps;
+ContactMethodsPage.displayName = 'ContactMethodsPage';
 
 export default compose(
     withLocalize,
-    withCurrentUserPersonalDetails,
     withOnyx({
         loginList: {
             key: ONYXKEYS.LOGIN_LIST,
         },
+        session: {
+            key: ONYXKEYS.SESSION,
+        },
     }),
 )(ContactMethodsPage);
diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js
index 6672198dc7db..3ea4f9abb9f7 100755
--- a/src/pages/settings/Profile/ProfilePage.js
+++ b/src/pages/settings/Profile/ProfilePage.js
@@ -2,6 +2,8 @@ import Str from 'expensify-common/lib/str';
 import lodashGet from 'lodash/get';
 import React from 'react';
 import {View} from 'react-native';
+import PropTypes from 'prop-types';
+import {withOnyx} from 'react-native-onyx';
 import {ScrollView} from 'react-native-gesture-handler';
 import _ from 'underscore';
 import AvatarWithImagePicker from '../../../components/AvatarWithImagePicker';
@@ -20,13 +22,27 @@ import * as ReportUtils from '../../../libs/ReportUtils';
 import ROUTES from '../../../ROUTES';
 import styles from '../../../styles/styles';
 import * as Expensicons from '../../../components/Icon/Expensicons';
+import ONYXKEYS from '../../../ONYXKEYS';
+import * as UserUtils from '../../../libs/UserUtils';
 
 const propTypes = {
+    /* Onyx Props */
+
+    /** Login list for the user that is signed in */
+    loginList: PropTypes.shape({
+        /** Date login was validated, used to show brickroad info status */
+        validatedDate: PropTypes.string,
+
+        /** Field-specific server side errors keyed by microtime */
+        errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
+    }),
+
     ...withLocalizePropTypes,
     ...withCurrentUserPersonalDetailsPropTypes,
 };
 
 const defaultProps = {
+    loginList: {},
     ...withCurrentUserPersonalDetailsDefaultProps,
 };
 
@@ -39,6 +55,8 @@ const ProfilePage = (props) => {
         return lodashGet(props.translate('pronouns'), pronounsKey, props.translate('profilePage.selectYourPronouns'));
     };
     const currentUserDetails = props.currentUserPersonalDetails || {};
+    const contactMethodBrickRoadIndicator = UserUtils.getLoginListBrickRoadIndicator(props.loginList);
+
     const profileSettingsOptions = [
         {
             description: props.translate('displayNamePage.headerTitle'),
@@ -49,6 +67,7 @@ const ProfilePage = (props) => {
             description: props.translate('contacts.contactMethod'),
             title: Str.removeSMSDomain(lodashGet(currentUserDetails, 'login', '')),
             pageRoute: ROUTES.SETTINGS_CONTACT_METHODS,
+            brickRoadIndicator: contactMethodBrickRoadIndicator,
         },
         {
             description: props.translate('pronounsPage.pronouns'),
@@ -94,6 +113,7 @@ const ProfilePage = (props) => {
                             title={detail.title}
                             description={detail.description}
                             onPress={() => Navigation.navigate(detail.pageRoute)}
+                            brickRoadIndicator={detail.brickRoadIndicator}
                         />
                     ))}
                 </View>
@@ -115,4 +135,9 @@ ProfilePage.displayName = 'ProfilePage';
 export default compose(
     withLocalize,
     withCurrentUserPersonalDetails,
+    withOnyx({
+        loginList: {
+            key: ONYXKEYS.LOGIN_LIST,
+        },
+    }),
 )(ProfilePage);
diff --git a/src/styles/styles.js b/src/styles/styles.js
index fafa5d1267d0..344363a31be6 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -1064,49 +1064,18 @@ const styles = {
         width: variables.componentSizeNormal,
     },
 
-    statusIndicator: {
+    statusIndicator: (backgroundColor = themeColors.danger) => ({
         borderColor: themeColors.sidebar,
-        backgroundColor: themeColors.danger,
-        borderRadius: 6,
-        borderWidth: 2,
-        position: 'absolute',
-        right: -1,
-        bottom: -1,
-        height: 12,
-        width: 12,
-        zIndex: 10,
-    },
-
-    statusIndicatorLarge: {
-        borderColor: themeColors.componentBG,
-        backgroundColor: themeColors.danger,
+        backgroundColor,
         borderRadius: 8,
         borderWidth: 2,
         position: 'absolute',
-        right: 4,
-        bottom: 4,
+        right: -2,
+        top: -1,
         height: 16,
         width: 16,
         zIndex: 10,
-    },
-
-    statusIndicatorOnline: {
-        backgroundColor: themeColors.success,
-    },
-
-    avatarWithIndicator: {
-        errorDot: {
-            borderColor: themeColors.sidebar,
-            borderRadius: 6,
-            borderWidth: 2,
-            position: 'absolute',
-            right: -1,
-            bottom: -1,
-            height: 12,
-            width: 12,
-            zIndex: 10,
-        },
-    },
+    }),
 
     floatingActionButtonContainer: {
         position: 'absolute',
diff --git a/src/styles/utilities/spacing.js b/src/styles/utilities/spacing.js
index fd58de57c675..44cc709fe469 100644
--- a/src/styles/utilities/spacing.js
+++ b/src/styles/utilities/spacing.js
@@ -205,6 +205,10 @@ export default {
         marginBottom: 24,
     },
 
+    mb7: {
+        marginBottom: 28,
+    },
+
     mb8: {
         marginBottom: 32,
     },
