diff --git a/frontend/src/metabase/reducers-admin.js b/frontend/src/metabase/admin/admin.js
similarity index 67%
rename from frontend/src/metabase/reducers-admin.js
rename to frontend/src/metabase/admin/admin.js
index 5ee2bfab4bccf8b62087d475e3c959784e4ff6fa..3fafa57f7edcf894693e18488ea11c142ccd72e1 100644
--- a/frontend/src/metabase/reducers-admin.js
+++ b/frontend/src/metabase/admin/admin.js
@@ -6,10 +6,14 @@ import people from "metabase/admin/people/people";
 import databases from "metabase/admin/databases/database";
 import datamodel from "metabase/admin/datamodel/datamodel";
 import permissions from "metabase/admin/permissions/permissions";
+import settings from "metabase/admin/settings/settings";
 
-export default {
+import { combineReducers } from "metabase/lib/redux";
+
+export default combineReducers({
     databases,
-    datamodel: datamodel,
+    datamodel,
     people,
     permissions,
-};
+    settings
+})
diff --git a/frontend/src/metabase/admin/databases/selectors.js b/frontend/src/metabase/admin/databases/selectors.js
index 79a714068df40c20b5da3e0579fafdd89841ca46..e9371fb171f2463bf258134b5f7c2272a5f26e5d 100644
--- a/frontend/src/metabase/admin/databases/selectors.js
+++ b/frontend/src/metabase/admin/databases/selectors.js
@@ -5,7 +5,7 @@ import { createSelector } from 'reselect';
 
 
 // Database List
-export const databases         = state => state.databases.databases;
+export const databases         = state => state.admin.databases.databases;
 
 export const getDatabasesSorted = createSelector(
     [databases],
@@ -19,5 +19,5 @@ export const hasSampleDataset = createSelector(
 
 
 // Database Edit
-export const getEditingDatabase   = state => state.databases.editingDatabase;
-export const getFormState         = state => state.databases.formState;
+export const getEditingDatabase   = state => state.admin.databases.editingDatabase;
+export const getFormState         = state => state.admin.databases.formState;
diff --git a/frontend/src/metabase/admin/datamodel/datamodel.js b/frontend/src/metabase/admin/datamodel/datamodel.js
index dfed708e8e75b371139a1e46da5a759bb337dfe4..0dafaacccd0e8920d49e9681a8da04c7d02f370c 100644
--- a/frontend/src/metabase/admin/datamodel/datamodel.js
+++ b/frontend/src/metabase/admin/datamodel/datamodel.js
@@ -9,12 +9,15 @@ import { isFK } from "metabase/lib/types";
 
 import { MetabaseApi, SegmentApi, MetricApi, RevisionsApi } from "metabase/services";
 
+import { getEditingDatabase } from "./selectors";
+
 function loadDatabaseMetadata(databaseId) {
     return MetabaseApi.db_metadata({ 'dbId': databaseId });
 }
 
 // initializeMetadata
-export const initializeMetadata = createThunkAction("INITIALIZE_METADATA", function(databaseId, tableId) {
+export const INITIALIZE_METADATA = "metabase/admin/datamodel/INITIALIZE_METADATA";
+export const initializeMetadata = createThunkAction(INITIALIZE_METADATA, function(databaseId, tableId) {
     return async function(dispatch, getState) {
         let databases, database;
         try {
@@ -43,7 +46,8 @@ export const initializeMetadata = createThunkAction("INITIALIZE_METADATA", funct
 });
 
 // fetchDatabaseIdfields
-export const fetchDatabaseIdfields = createThunkAction("FETCH_IDFIELDS", function(databaseId) {
+export const FETCH_IDFIELDS = "metabase/admin/datamodel/FETCH_IDFIELDS";
+export const fetchDatabaseIdfields = createThunkAction(FETCH_IDFIELDS, function(databaseId) {
     return async function(dispatch, getState) {
         try {
             let idfields = await MetabaseApi.db_idfields({ 'dbId': databaseId });
@@ -58,7 +62,8 @@ export const fetchDatabaseIdfields = createThunkAction("FETCH_IDFIELDS", functio
 });
 
 // selectDatabase
-export const selectDatabase = createThunkAction("SELECT_DATABASE", function(db) {
+export const SELECT_DATABASE = "metabase/admin/datamodel/SELECT_DATABASE";
+export const selectDatabase = createThunkAction(SELECT_DATABASE, function(db) {
     return async function(dispatch, getState) {
         try {
             let database = await loadDatabaseMetadata(db.id);
@@ -76,7 +81,8 @@ export const selectDatabase = createThunkAction("SELECT_DATABASE", function(db)
 });
 
 // selectTable
-export const selectTable = createThunkAction("SELECT_TABLE", function(table) {
+export const SELECT_TABLE = "metabase/admin/datamodel/SELECT_TABLE";
+export const selectTable = createThunkAction(SELECT_TABLE, function(table) {
     return function(dispatch, getState) {
         // we also want to update our url to match our new state
         dispatch(push('/admin/datamodel/database/'+table.db_id+'/table/'+table.id));
@@ -86,7 +92,8 @@ export const selectTable = createThunkAction("SELECT_TABLE", function(table) {
 });
 
 // updateTable
-export const updateTable = createThunkAction("UPDATE_TABLE", function(table) {
+export const UPDATE_TABLE = "metabase/admin/datamodel/UPDATE_TABLE";
+export const updateTable = createThunkAction(UPDATE_TABLE, function(table) {
     return async function(dispatch, getState) {
         try {
             // make sure we don't send all the computed metadata
@@ -109,9 +116,10 @@ export const updateTable = createThunkAction("UPDATE_TABLE", function(table) {
 });
 
 // updateField
-export const updateField = createThunkAction("UPDATE_FIELD", function(field) {
+export const UPDATE_FIELD = "metabase/admin/datamodel/UPDATE_FIELD";
+export const updateField = createThunkAction(UPDATE_FIELD, function(field) {
     return async function(dispatch, getState) {
-        const { datamodel: { editingDatabase } } = getState();
+        const editingDatabase = getEditingDatabase(getState());
 
         try {
             // make sure we don't send all the computed metadata
@@ -138,7 +146,8 @@ export const updateField = createThunkAction("UPDATE_FIELD", function(field) {
 });
 
 // updateFieldSpecialType
-export const updateFieldSpecialType = createThunkAction("UPDATE_FIELD_SPECIAL_TYPE", function(field) {
+export const UPDATE_FIELD_SPECIAL_TYPE = "metabase/admin/datamodel/UPDATE_FIELD_SPECIAL_TYPE";
+export const updateFieldSpecialType = createThunkAction(UPDATE_FIELD_SPECIAL_TYPE, function(field) {
     return function(dispatch, getState) {
 
         // If we are changing the field from a FK to something else, we should delete any FKs present
@@ -157,7 +166,8 @@ export const updateFieldSpecialType = createThunkAction("UPDATE_FIELD_SPECIAL_TY
 });
 
 // updateFieldTarget
-export const updateFieldTarget = createThunkAction("UPDATE_FIELD_TARGET", function(field) {
+export const UPDATE_FIELD_TARGET = "metabase/admin/datamodel/UPDATE_FIELD_TARGET";
+export const updateFieldTarget = createThunkAction(UPDATE_FIELD_TARGET, function(field) {
     return function(dispatch, getState) {
         // This function notes a change in the target of the target of a foreign key
         dispatch(updateField(field));
@@ -167,9 +177,10 @@ export const updateFieldTarget = createThunkAction("UPDATE_FIELD_TARGET", functi
 });
 
 // retireSegment
-export const onRetireSegment = createThunkAction("RETIRE_SEGMENT", function(segment) {
+export const RETIRE_SEGMENT = "metabase/admin/datamodel/RETIRE_SEGMENT";
+export const onRetireSegment = createThunkAction(RETIRE_SEGMENT, function(segment) {
     return async function(dispatch, getState) {
-        const { datamodel: { editingDatabase } } = getState();
+        const editingDatabase = getEditingDatabase(getState());
 
         await SegmentApi.delete(segment);
         MetabaseAnalytics.trackEvent("Data Model", "Retire Segment");
@@ -179,9 +190,10 @@ export const onRetireSegment = createThunkAction("RETIRE_SEGMENT", function(segm
 });
 
 // retireMetric
-export const onRetireMetric = createThunkAction("RETIRE_METRIC", function(metric) {
+export const RETIRE_METRIC = "metabase/admin/datamodel/RETIRE_METRIC";
+export const onRetireMetric = createThunkAction(RETIRE_METRIC, function(metric) {
     return async function(dispatch, getState) {
-        const { datamodel: { editingDatabase } } = getState();
+        const editingDatabase = getEditingDatabase(getState());
 
         await MetricApi.delete(metric);
         MetabaseAnalytics.trackEvent("Data Model", "Retire Metric");
@@ -193,10 +205,10 @@ export const onRetireMetric = createThunkAction("RETIRE_METRIC", function(metric
 
 // SEGMENTS
 
-export const GET_SEGMENT = "GET_SEGMENT";
-export const CREATE_SEGMENT = "CREATE_SEGMENT";
-export const UPDATE_SEGMENT = "UPDATE_SEGMENT";
-export const DELETE_SEGMENT = "DELETE_SEGMENT";
+export const GET_SEGMENT = "metabase/admin/datamodel/GET_SEGMENT";
+export const CREATE_SEGMENT = "metabase/admin/datamodel/CREATE_SEGMENT";
+export const UPDATE_SEGMENT = "metabase/admin/datamodel/UPDATE_SEGMENT";
+export const DELETE_SEGMENT = "metabase/admin/datamodel/DELETE_SEGMENT";
 
 export const getSegment    = createAction(GET_SEGMENT, SegmentApi.get);
 export const createSegment = createAction(CREATE_SEGMENT, SegmentApi.create);
@@ -205,10 +217,10 @@ export const deleteSegment = createAction(DELETE_SEGMENT, SegmentApi.delete);
 
 // METRICS
 
-export const GET_METRIC = "GET_METRIC";
-export const CREATE_METRIC = "CREATE_METRIC";
-export const UPDATE_METRIC = "UPDATE_METRIC";
-export const DELETE_METRIC = "DELETE_METRIC";
+export const GET_METRIC = "metabase/admin/datamodel/GET_METRIC";
+export const CREATE_METRIC = "metabase/admin/datamodel/CREATE_METRIC";
+export const UPDATE_METRIC = "metabase/admin/datamodel/UPDATE_METRIC";
+export const DELETE_METRIC = "metabase/admin/datamodel/DELETE_METRIC";
 
 export const getMetric    = createAction(GET_METRIC, MetricApi.get);
 export const createMetric = createAction(CREATE_METRIC, MetricApi.create);
@@ -217,8 +229,8 @@ export const deleteMetric = createAction(DELETE_METRIC, MetricApi.delete);
 
 // SEGMENT DETAIL
 
-export const LOAD_TABLE_METADATA = "LOAD_TABLE_METADATA";
-export const UPDATE_PREVIEW_SUMMARY = "UPDATE_PREVIEW_SUMMARY";
+export const LOAD_TABLE_METADATA = "metabase/admin/datamodel/LOAD_TABLE_METADATA";
+export const UPDATE_PREVIEW_SUMMARY = "metabase/admin/datamodel/UPDATE_PREVIEW_SUMMARY";
 
 export const loadTableMetadata = createAction(LOAD_TABLE_METADATA, loadTableAndForeignKeys);
 export const updatePreviewSummary = createAction(UPDATE_PREVIEW_SUMMARY, async (query) => {
@@ -228,7 +240,7 @@ export const updatePreviewSummary = createAction(UPDATE_PREVIEW_SUMMARY, async (
 
 // REVISION HISTORY
 
-export const FETCH_REVISIONS = "FETCH_REVISIONS";
+export const FETCH_REVISIONS = "metabase/admin/datamodel/FETCH_REVISIONS";
 
 export const fetchRevisions = createThunkAction(FETCH_REVISIONS, ({ entity, id }) =>
     async (dispatch, getState) => {
@@ -250,23 +262,23 @@ export const fetchRevisions = createThunkAction(FETCH_REVISIONS, ({ entity, id }
 // reducers
 
 const databases = handleActions({
-    ["INITIALIZE_METADATA"]: { next: (state, { payload }) => payload.databases }
+    [INITIALIZE_METADATA]: { next: (state, { payload }) => payload.databases }
 }, []);
 
 const idfields = handleActions({
-    ["FETCH_IDFIELDS"]: { next: (state, { payload }) => payload ? payload : state }
+    [FETCH_IDFIELDS]: { next: (state, { payload }) => payload ? payload : state }
 }, []);
 
 const editingDatabase = handleActions({
-    ["INITIALIZE_METADATA"]: { next: (state, { payload }) => payload.database },
-    ["SELECT_DATABASE"]: { next: (state, { payload }) => payload ? payload : state },
-    ["RETIRE_SEGMENT"]: { next: (state, { payload }) => payload },
-    ["RETIRE_METRIC"]: { next: (state, { payload }) => payload }
+    [INITIALIZE_METADATA]: { next: (state, { payload }) => payload.database },
+    [SELECT_DATABASE]: { next: (state, { payload }) => payload ? payload : state },
+    [RETIRE_SEGMENT]: { next: (state, { payload }) => payload },
+    [RETIRE_METRIC]: { next: (state, { payload }) => payload }
 }, null);
 
 const editingTable = handleActions({
-    ["INITIALIZE_METADATA"]: { next: (state, { payload }) => payload.tableId || null },
-    ["SELECT_TABLE"]: { next: (state, { payload }) => payload }
+    [INITIALIZE_METADATA]: { next: (state, { payload }) => payload.tableId || null },
+    [SELECT_TABLE]: { next: (state, { payload }) => payload }
 }, null);
 
 const segments = handleActions({
diff --git a/frontend/src/metabase/admin/datamodel/selectors.js b/frontend/src/metabase/admin/datamodel/selectors.js
index 2d957762ac9adfe9ce8289576d1bbf41f2d72800..5e782bc986437b37540130591b33abfc89363087 100644
--- a/frontend/src/metabase/admin/datamodel/selectors.js
+++ b/frontend/src/metabase/admin/datamodel/selectors.js
@@ -3,12 +3,12 @@ import { createSelector } from 'reselect';
 import { computeMetadataStrength } from "metabase/lib/schema_metadata";
 
 
-const segmentsSelector         = (state, props) => state.datamodel.segments;
-const metricsSelector          = (state, props) => state.datamodel.metrics;
+const segmentsSelector         = (state, props) => state.admin.datamodel.segments;
+const metricsSelector          = (state, props) => state.admin.datamodel.metrics;
 
-const tableMetadataSelector    = (state, props) => state.datamodel.tableMetadata;
-const previewSummarySelector   = (state, props) => state.datamodel.previewSummary;
-const revisionObjectSelector   = (state, props) => state.datamodel.revisionObject;
+const tableMetadataSelector    = (state, props) => state.admin.datamodel.tableMetadata;
+const previewSummarySelector   = (state, props) => state.admin.datamodel.previewSummary;
+const revisionObjectSelector   = (state, props) => state.admin.datamodel.revisionObject;
 
 const idSelector               = (state, props) => props.params.id == null ? null : parseInt(props.params.id);
 const tableIdSelector          = (state, props) => props.location.query.table == null ? null : parseInt(props.location.query.table);
@@ -73,13 +73,14 @@ export const revisionHistorySelectors = createSelector(
 );
 
 
-export const getDatabases             = (state, props) => state.datamodel.databases;
-export const getDatabaseIdfields      = (state, props) => state.datamodel.idfields;
-export const getEditingTable          = (state, props) => state.datamodel.editingTable;
+export const getDatabases             = (state, props) => state.admin.datamodel.databases;
+export const getDatabaseIdfields      = (state, props) => state.admin.datamodel.idfields;
+export const getEditingTable          = (state, props) => state.admin.datamodel.editingTable;
+export const getEditingDatabase       = (state, props) => state.admin.datamodel.editingDatabase;
 
 
 export const getEditingDatabaseWithTableMetadataStrengths = createSelector(
-    state => state.datamodel.editingDatabase,
+    state => state.admin.datamodel.editingDatabase,
     (database) => {
         if (!database || !database.tables) {
             return null;
diff --git a/frontend/src/metabase/admin/people/selectors.js b/frontend/src/metabase/admin/people/selectors.js
index 4ee7eabd4483201d1a818e905a63ef06476d2fec..05398a59dbee38f1ffbd211bbd450abac0c96df6 100644
--- a/frontend/src/metabase/admin/people/selectors.js
+++ b/frontend/src/metabase/admin/people/selectors.js
@@ -2,14 +2,14 @@
 import { createSelector } from 'reselect';
 import _ from "underscore";
 
-export const getGroups = (state) => state.people.groups;
-export const getGroup  = (state) => state.people.group;
-export const getModal  = (state) => state.people.modal;
-export const getMemberships = (state) => state.people.memberships;
+export const getGroups = (state) => state.admin.people.groups;
+export const getGroup  = (state) => state.admin.people.group;
+export const getModal  = (state) => state.admin.people.modal;
+export const getMemberships = (state) => state.admin.people.memberships;
 
 export const getUsers  = createSelector(
-    (state) => state.people.users,
-    (state) => state.people.memberships,
+    (state) => state.admin.people.users,
+    (state) => state.admin.people.memberships,
     (users, memberships) =>
         users && _.mapObject(users, user => ({
             ...user,
diff --git a/frontend/src/metabase/admin/permissions/permissions.js b/frontend/src/metabase/admin/permissions/permissions.js
index 0973b926ca316cd9617c62bf029dfeeb9c29e524..6fdc64cfe41699c360e012c638e3764502feb375 100644
--- a/frontend/src/metabase/admin/permissions/permissions.js
+++ b/frontend/src/metabase/admin/permissions/permissions.js
@@ -34,7 +34,7 @@ export const loadGroups = createAction(LOAD_GROUPS, () => PermissionsApi.groups(
 const LOAD_PERMISSIONS = "metabase/admin/permissions/LOAD_PERMISSIONS";
 export const loadPermissions = createThunkAction(LOAD_PERMISSIONS, () =>
     async (dispatch, getState) => {
-        const { load } = getState().permissions;
+        const { load } = getState().admin.permissions;
         return load();
     }
 );
@@ -56,7 +56,7 @@ const SAVE_PERMISSIONS = "metabase/admin/permissions/SAVE_PERMISSIONS";
 export const savePermissions = createThunkAction(SAVE_PERMISSIONS, () =>
     async (dispatch, getState) => {
         MetabaseAnalytics.trackEvent("Permissions", "save");
-        const { permissions, revision, save } = getState().permissions;
+        const { permissions, revision, save } = getState().admin.permissions;
         let result = await save({
             revision: revision,
             groups: permissions
diff --git a/frontend/src/metabase/admin/permissions/selectors.js b/frontend/src/metabase/admin/permissions/selectors.js
index 85510bee59995fd0d021deae11d1dfd3e9201eef..efaad73d99df7353ee2fcb41a4ec6f042cffff39 100644
--- a/frontend/src/metabase/admin/permissions/selectors.js
+++ b/frontend/src/metabase/admin/permissions/selectors.js
@@ -27,14 +27,14 @@ import {
     diffPermissions,
 } from "metabase/lib/permissions";
 
-const getPermissions = (state) => state.permissions.permissions;
-const getOriginalPermissions = (state) => state.permissions.originalPermissions;
+const getPermissions = (state) => state.admin.permissions.permissions;
+const getOriginalPermissions = (state) => state.admin.permissions.originalPermissions;
 
 const getDatabaseId = (state, props) => props.params.databaseId ? parseInt(props.params.databaseId) : null
 const getSchemaName = (state, props) => props.params.schemaName
 
 const getMetadata = createSelector(
-    [(state) => state.permissions.databases],
+    [(state) => state.admin.permissions.databases],
     (databases) => databases && new Metadata(databases)
 );
 
@@ -53,7 +53,7 @@ function getTooltipForGroup(group) {
 }
 
 export const getGroups = createSelector(
-    (state) => state.permissions.groups,
+    (state) => state.admin.permissions.groups,
     (groups) => {
         let orderedGroups = groups ? [...groups] : [];
         for (let groupFilter of SPECIAL_GROUP_FILTERS) {
@@ -75,7 +75,7 @@ export const getIsDirty = createSelector(
         JSON.stringify(permissions) !== JSON.stringify(originalPermissions)
 )
 
-export const getSaveError = (state) => state.permissions.saveError;
+export const getSaveError = (state) => state.admin.permissions.saveError;
 
 
 // these are all the permission levels ordered by level of access
@@ -418,7 +418,7 @@ export const getDatabasesPermissionsGrid = createSelector(
     }
 );
 
-const getCollections = (state) => state.permissions.collections;
+const getCollections = (state) => state.admin.permissions.collections;
 const getCollectionPermission = (permissions, groupId, { collectionId }) =>
     getIn(permissions, [groupId, collectionId])
 
diff --git a/frontend/src/metabase/admin/settings/components/SettingsEmailForm.jsx b/frontend/src/metabase/admin/settings/components/SettingsEmailForm.jsx
index de3639693cb4af2697575517e404cb079693df46..a74be885760e404ad3e38bd688c978246895d7ae 100644
--- a/frontend/src/metabase/admin/settings/components/SettingsEmailForm.jsx
+++ b/frontend/src/metabase/admin/settings/components/SettingsEmailForm.jsx
@@ -31,12 +31,19 @@ export default class SettingsEmailForm extends Component {
 
     componentWillMount() {
         // this gives us an opportunity to load up our formData with any existing values for elements
+        this.updateFormData(this.props);
+    }
+
+    componentWillReceiveProps(nextProps) {
+        this.updateFormData(nextProps);
+    }
+
+    updateFormData(props) {
         let formData = {};
-        this.props.elements.forEach(function(element) {
+        for (const element of props.elements) {
             formData[element.key] = element.value;
-        });
-
-        this.setState({formData});
+        }
+        this.setState({ formData });
     }
 
     componentDidMount() {
diff --git a/frontend/src/metabase/admin/settings/components/SettingsSetting.jsx b/frontend/src/metabase/admin/settings/components/SettingsSetting.jsx
index 8e5498b759b80f4d52b3b19588a7084c33d1ccd3..998b5a826fcb82b286a77f46a6fc00e46c739f4c 100644
--- a/frontend/src/metabase/admin/settings/components/SettingsSetting.jsx
+++ b/frontend/src/metabase/admin/settings/components/SettingsSetting.jsx
@@ -45,6 +45,9 @@ export default class SettingsSetting extends Component {
                 { errorMessage &&
                     <div className="text-error text-bold pt1">{errorMessage}</div>
                 }
+                { setting.warning &&
+                    <div className="text-gold text-bold pt1">{setting.warning}</div>
+                }
             </li>
         );
     }
diff --git a/frontend/src/metabase/admin/settings/selectors.js b/frontend/src/metabase/admin/settings/selectors.js
index ae501e697ee409d3393db53d75673754fa40a973..1303d13df831c3ab32ca578b33f4285763d7cceb 100644
--- a/frontend/src/metabase/admin/settings/selectors.js
+++ b/frontend/src/metabase/admin/settings/selectors.js
@@ -95,7 +95,7 @@ const SECTIONS = [
                 display_name: "SMTP Security",
                 description: null,
                 type: "radio",
-                options: { none: "None", ssl: "SSL", tls: "TLS" },
+                options: { none: "None", ssl: "SSL", tls: "TLS", starttls: "STARTTLS" },
                 defaultValue: 'none'
             },
             {
@@ -270,7 +270,15 @@ for (const section of SECTIONS) {
     section.slug = slugify(section.name);
 }
 
-export const getSettings = state => state.settings.settings;
+export const getSettings = createSelector(
+    state => state.settings.settings,
+    state => state.admin.settings.warnings,
+    (settings, warnings) =>
+        settings.map(setting => warnings[setting.key] ?
+            { ...setting, warning: warnings[setting.key] } :
+            setting
+        )
+)
 
 export const getSettingValues = createSelector(
     getSettings,
diff --git a/frontend/src/metabase/admin/settings/settings.js b/frontend/src/metabase/admin/settings/settings.js
index fa9db3da3aeac235527426350ee8bb2fe171e1e3..cc63d4829c5fc1a0545b1fe181c2c951900b4cc2 100644
--- a/frontend/src/metabase/admin/settings/settings.js
+++ b/frontend/src/metabase/admin/settings/settings.js
@@ -1,12 +1,14 @@
 
-import { createThunkAction } from "metabase/lib/redux";
+import { createThunkAction, handleActions, combineReducers } from "metabase/lib/redux";
 
 import { SettingsApi, EmailApi, SlackApi } from "metabase/services";
 
 import { refreshSiteSettings } from "metabase/redux/settings";
 
-// initializeSettings
-export const initializeSettings = createThunkAction("INITIALIZE_SETTINGS", function() {
+// ACITON TYPES AND ACTION CREATORS
+
+export const INITIALIZE_SETTINGS = "metabase/admin/settings/INITIALIZE_SETTINGS";
+export const initializeSettings = createThunkAction(INITIALIZE_SETTINGS, function() {
     return async function(dispatch, getState) {
         try {
             await dispatch(refreshSiteSettings());
@@ -17,8 +19,8 @@ export const initializeSettings = createThunkAction("INITIALIZE_SETTINGS", funct
     };
 });
 
-// updateSetting
-export const updateSetting = createThunkAction("UPDATE_SETTING", function(setting) {
+export const UPDATE_SETTING = "metabase/admin/settings/UPDATE_SETTING";
+export const updateSetting = createThunkAction(UPDATE_SETTING, function(setting) {
     return async function(dispatch, getState) {
         try {
             await SettingsApi.put(setting);
@@ -30,12 +32,13 @@ export const updateSetting = createThunkAction("UPDATE_SETTING", function(settin
     };
 });
 
-// updateEmailSettings
-export const updateEmailSettings = createThunkAction("UPDATE_EMAIL_SETTINGS", function(settings) {
+export const UPDATE_EMAIL_SETTINGS = "metabase/admin/settings/UPDATE_EMAIL_SETTINGS";
+export const updateEmailSettings = createThunkAction(UPDATE_EMAIL_SETTINGS, function(settings) {
     return async function(dispatch, getState) {
         try {
-            await EmailApi.updateSettings(settings);
+            const result = await EmailApi.updateSettings(settings);
             await dispatch(refreshSiteSettings());
+            return result;
         } catch(error) {
             console.log("error updating email settings", settings, error);
             throw error;
@@ -43,8 +46,8 @@ export const updateEmailSettings = createThunkAction("UPDATE_EMAIL_SETTINGS", fu
     };
 });
 
-// sendTestEmail
-export const sendTestEmail = createThunkAction("SEND_TEST_EMAIL", function() {
+export const SEND_TEST_EMAIL = "metabase/admin/settings/SEND_TEST_EMAIL";
+export const sendTestEmail = createThunkAction(SEND_TEST_EMAIL, function() {
     return async function(dispatch, getState) {
         try {
             await EmailApi.sendTest();
@@ -55,8 +58,8 @@ export const sendTestEmail = createThunkAction("SEND_TEST_EMAIL", function() {
     };
 });
 
-// updateSlackSettings
-export const updateSlackSettings = createThunkAction("UPDATE_SLACK_SETTINGS", function(settings) {
+export const UPDATE_SLACK_SETTINGS = "metabase/admin/settings/UPDATE_SLACK_SETTINGS";
+export const updateSlackSettings = createThunkAction(UPDATE_SLACK_SETTINGS, function(settings) {
     return async function(dispatch, getState) {
         try {
             await SlackApi.updateSettings(settings);
@@ -68,8 +71,19 @@ export const updateSlackSettings = createThunkAction("UPDATE_SLACK_SETTINGS", fu
     };
 }, {});
 
-export const reloadSettings = createThunkAction("RELOAD_SETTINGS", function() {
+export const RELOAD_SETTINGS = "metabase/admin/settings/RELOAD_SETTINGS";
+export const reloadSettings = createThunkAction(RELOAD_SETTINGS, function() {
     return async function(dispatch, getState) {
         await dispatch(refreshSiteSettings());
     }
 });
+
+// REDUCERS
+
+export const warnings = handleActions({
+    [UPDATE_EMAIL_SETTINGS]: { next: (state, { payload }) => payload["with-corrections"] }
+}, {});
+
+export default combineReducers({
+    warnings
+});
diff --git a/frontend/src/metabase/reducers-main.js b/frontend/src/metabase/reducers-main.js
index f4b176268a108ea4e6c658c063b091db2aca6d8f..57c3faf8c3425649129f797c3722efbf60f8c803 100644
--- a/frontend/src/metabase/reducers-main.js
+++ b/frontend/src/metabase/reducers-main.js
@@ -7,7 +7,7 @@ import { combineReducers } from 'redux';
 import commonReducers from "./reducers-common";
 
 /* admin */
-import adminReducers from "./reducers-admin";
+import admin from "metabase/admin/admin";
 
 /* setup */
 import * as setup from "metabase/setup/reducers";
@@ -45,6 +45,5 @@ export default {
     reference,
     setup: combineReducers(setup),
     user: combineReducers(user),
-
-    ...adminReducers
+    admin
 };
diff --git a/src/metabase/api/email.clj b/src/metabase/api/email.clj
index e3452558f1a6064e179f7e120478142a2bef6c02..27f18663f986bab4e4efc3d99ba089503c1493ea 100644
--- a/src/metabase/api/email.clj
+++ b/src/metabase/api/email.clj
@@ -1,11 +1,15 @@
 (ns metabase.api.email
   "/api/email endpoints"
-  (:require [clojure.tools.logging :as log]
-            [clojure.set :as set]
-            [compojure.core :refer [GET PUT DELETE POST]]
+  (:require [clojure
+             [data :as data]
+             [set :as set]
+             [string :as string]]
+            [clojure.tools.logging :as log]
+            [compojure.core :refer [POST PUT]]
+            [metabase
+             [config :as config]
+             [email :as email]]
             [metabase.api.common :refer :all]
-            [metabase.config :as config]
-            [metabase.email :as email]
             [metabase.models.setting :as setting]
             [metabase.util.schema :as su]))
 
@@ -51,6 +55,16 @@
         #".*"
         {:message "Sorry, something went wrong.  Please try again."}))))
 
+(defn humanize-email-corrections
+  "formats warnings when security settings are autocorrected"
+  [corrections]
+  (into {}
+        (mapv (fn [[k v]]
+                [k (format "%s was autocorrected to %s"
+                           (name (mb-to-smtp-settings k))
+                           (string/upper-case v))])
+              corrections)))
+
 (defendpoint PUT "/"
   "Update multiple `Settings` values.  You must be a superuser to do this."
   [:as {settings :body}]
@@ -63,10 +77,15 @@
                          ;; in normal conditions, validate connection
                          (email/test-smtp-connection smtp-settings)
                          ;; for unit testing just respond with a success message
-                         {:error :SUCCESS})]
+                         {:error :SUCCESS})
+        tested-settings  (merge settings (select-keys response [:port :security]))
+        [_ corrections _] (data/diff settings tested-settings)
+        properly-named-corrections (set/rename-keys corrections (set/map-invert mb-to-smtp-settings))
+        corrected-settings (merge email-settings properly-named-corrections)]
     (if (= :SUCCESS (:error response))
       ;; test was good, save our settings
-      (setting/set-many! email-settings)
+      (assoc (setting/set-many! corrected-settings)
+        :with-corrections (humanize-email-corrections properly-named-corrections))
       ;; test failed, return response message
       {:status 500
        :body   (humanize-error-messages response)})))
diff --git a/src/metabase/email.clj b/src/metabase/email.clj
index 9731b50acdbdae802f760dda254ccf090546ef74..ef5a7dbbc4de044c74ad9db012e20ef7065393a8 100644
--- a/src/metabase/email.clj
+++ b/src/metabase/email.clj
@@ -15,11 +15,11 @@
 (defsetting email-smtp-password "SMTP password.")
 (defsetting email-smtp-port     "The port your SMTP server uses for outgoing emails.")
 (defsetting email-smtp-security
-  "SMTP secure connection protocol. (tls, ssl, or none)"
+  "SMTP secure connection protocol. (tls, ssl, starttls, or none)"
   :default "none"
   :setter  (fn [new-value]
              (when-not (nil? new-value)
-               (assert (contains? #{"tls" "ssl" "none"} new-value)))
+               (assert (contains? #{"tls" "ssl" "none" "starttls"} new-value)))
              (setting/set-string! :email-smtp-security new-value)))
 
 ;; ## PUBLIC INTERFACE
@@ -38,6 +38,8 @@
   (merge m (case (keyword ssl-setting)
              :tls {:tls true}
              :ssl {:ssl true}
+             :starttls {:starttls.enable true
+                        :starttls.required true}
              {})))
 
 (defn- smtp-settings []
@@ -85,27 +87,19 @@
       {:error   :ERROR
        :message (.getMessage e)})))
 
-
-(defn test-smtp-connection
-  "Test the connection to an SMTP server to determine if we can send emails.
-
-   Takes in a dictionary of properties such as:
-       {:host     \"localhost\"
-        :port     587
-        :user     \"bigbird\"
-        :pass     \"luckyme\"
-        :sender   \"foo@mycompany.com\"
-        :security \"tls\"}"
+(defn- run-smtp-test
+  "tests an SMTP configuration by attempting to connect and authenticate
+   if an authenticated method is passed in :security."
   [{:keys [host port user pass sender security] :as details}]
   {:pre [(string? host)
          (integer? port)]}
   (try
-    (let [ssl?    (= security "ssl")
-          proto   (if ssl? "smtps" "smtp")
+    (let [ssl?      (= security "ssl")
+          proto     (if ssl? "smtps" "smtp")
           details (-> details
                       (assoc :proto proto
                              :connectiontimeout "1000"
-                             :timeout "1000")
+                             :timeout "4000")
                       (add-ssl-settings security))
           session (doto (Session/getInstance (make-props sender details))
                     (.setDebug false))]
@@ -117,3 +111,42 @@
       (log/error "Error testing SMTP connection:" (.getMessage e))
       {:error   :ERROR
        :message (.getMessage e)})))
+
+(def ^:private email-security-order ["tls" "starttls" "ssl"])
+
+(defn- guess-smtp-security
+  "Attempts to use each of the security methods in security order with the same set of credentials.
+   This is used only when the initial connection attempt fails, so it won't overwrite a functioning
+   configuration. If this uses something other than the provided method, a warning gets printed on
+   the config page"
+  [details]
+  (loop [[security-type & more-to-try] email-security-order] ;; make sure this is not lazy, or chunking
+    (when security-type                                      ;; can cause some servers to block requests
+      (let [test-result (run-smtp-test (assoc details :security security-type))]
+        (if (not= :ERROR (:error test-result))
+          (assoc test-result :security security-type)
+          (do
+            (Thread/sleep 500) ;; try not to get banned from outlook.com
+            (recur more-to-try)))))))
+
+(defn test-smtp-connection
+  "Test the connection to an SMTP server to determine if we can send emails.
+
+   Takes in a dictionary of properties such as:
+       {:host     \"localhost\"
+        :port     587
+        :user     \"bigbird\"
+        :pass     \"luckyme\"
+        :sender   \"foo@mycompany.com\"
+        :security \"tls\"}"
+  [details]
+  (let [inital-attempt (run-smtp-test details)
+        it-worked?     (= :SUCCESS (:error inital-attempt))
+        attempted-fix  (if (not it-worked?)
+                         (guess-smtp-security details))
+        we-fixed-it?     (= :SUCCESS (:error attempted-fix))]
+    (if it-worked?
+      inital-attempt
+      (if we-fixed-it?
+        attempted-fix
+        inital-attempt))))