UX: Use a dropdown for SSL mode for group SMTP (#27932)
Our old group SMTP SSL option was a checkbox, but this was not ideal because there are actually 3 different ways SSL can be used when sending SMTP: * None * SSL/TLS * STARTTLS We got around this before with specific overrides for Gmail, but it's not flexible enough and now people want to use other providers. It's best to be clear, though it is a technical detail. We provide a way to test the SMTP settings before saving them so there should be little chance of messing this up. This commit also converts GroupEmailSettings to a glimmer component.
This commit is contained in:
parent
9a0e8fc100
commit
48d13cb231
|
@ -17,6 +17,7 @@
|
||||||
<GroupSmtpEmailSettings
|
<GroupSmtpEmailSettings
|
||||||
@group={{this.group}}
|
@group={{this.group}}
|
||||||
@smtpSettingsValid={{this.smtpSettingsValid}}
|
@smtpSettingsValid={{this.smtpSettingsValid}}
|
||||||
|
@onChangeSmtpSettingsValid={{this.onChangeSmtpSettingsValid}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,11 @@ export default Component.extend({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
onChangeSmtpSettingsValid(valid) {
|
||||||
|
this.set("smtpSettingsValid", valid);
|
||||||
|
},
|
||||||
|
|
||||||
@action
|
@action
|
||||||
smtpEnabledChange(event) {
|
smtpEnabledChange(event) {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -0,0 +1,308 @@
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { fn } from "@ember/helper";
|
||||||
|
import { on } from "@ember/modifier";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { LinkTo } from "@ember/routing";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import { isEmpty } from "@ember/utils";
|
||||||
|
import { TrackedObject } from "@ember-compat/tracked-built-ins";
|
||||||
|
import { or } from "truth-helpers";
|
||||||
|
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
|
||||||
|
import DButton from "discourse/components/d-button";
|
||||||
|
import formatDate from "discourse/helpers/format-date";
|
||||||
|
import withEventValue from "discourse/helpers/with-event-value";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
import { GROUP_SMTP_SSL_MODES } from "discourse/lib/constants";
|
||||||
|
import emailProviderDefaultSettings from "discourse/lib/email-provider-default-settings";
|
||||||
|
import dIcon from "discourse-common/helpers/d-icon";
|
||||||
|
import i18n from "discourse-common/helpers/i18n";
|
||||||
|
import I18n from "I18n";
|
||||||
|
import ComboBox from "select-kit/components/combo-box";
|
||||||
|
|
||||||
|
export default class GroupSmtpEmailSettings extends Component {
|
||||||
|
@service currentUser;
|
||||||
|
|
||||||
|
@tracked smtpSettingsValid = false;
|
||||||
|
@tracked testingSettings = false;
|
||||||
|
|
||||||
|
form = new TrackedObject({
|
||||||
|
email_username: this.args.group.email_username,
|
||||||
|
email_password: this.args.group.email_password,
|
||||||
|
email_from_alias: this.args.group.email_from_alias,
|
||||||
|
smtp_server: this.args.group.smtp_server,
|
||||||
|
smtp_port: (this.args.group.smtp_port || "").toString(),
|
||||||
|
smtp_ssl_mode: this.args.group.smtp_ssl_mode || GROUP_SMTP_SSL_MODES.none,
|
||||||
|
});
|
||||||
|
|
||||||
|
get sslModes() {
|
||||||
|
return Object.keys(GROUP_SMTP_SSL_MODES).map((key) => {
|
||||||
|
return {
|
||||||
|
value: GROUP_SMTP_SSL_MODES[key],
|
||||||
|
name: I18n.t(`groups.manage.email.ssl_modes.${key}`),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get missingSettings() {
|
||||||
|
if (!this.form) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
this.form.email_username,
|
||||||
|
this.form.email_password,
|
||||||
|
this.form.smtp_server,
|
||||||
|
this.form.smtp_port,
|
||||||
|
].some((value) => isEmpty(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
changeSmtpSettingsValid(newValidValue) {
|
||||||
|
this.smtpSettingsValid = newValidValue;
|
||||||
|
this.args.onChangeSmtpSettingsValid(newValidValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onChangeSslMode(newMode) {
|
||||||
|
this.form.smtp_ssl_mode = newMode;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
changeEmailUsername(newValue) {
|
||||||
|
this.form.email_username = newValue;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
changeEmailPassword(newValue) {
|
||||||
|
this.form.email_password = newValue;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
changeEmailFromAlias(newValue) {
|
||||||
|
this.form.email_from_alias = newValue;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
changeSmtpServer(newValue) {
|
||||||
|
this.form.smtp_server = newValue;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
changeSmtpPort(newValue) {
|
||||||
|
this.form.smtp_port = newValue;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
prefillSettings(provider, event) {
|
||||||
|
event?.preventDefault();
|
||||||
|
Object.assign(this.form, emailProviderDefaultSettings(provider, "smtp"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
testSmtpSettings() {
|
||||||
|
const settings = {
|
||||||
|
host: this.form.smtp_server,
|
||||||
|
port: this.form.smtp_port,
|
||||||
|
ssl_mode: this.form.smtp_ssl_mode,
|
||||||
|
username: this.form.email_username,
|
||||||
|
password: this.form.email_password,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.testingSettings = true;
|
||||||
|
this.changeSmtpSettingsValid(false);
|
||||||
|
|
||||||
|
return ajax(`/groups/${this.args.group.id}/test_email_settings`, {
|
||||||
|
type: "POST",
|
||||||
|
data: Object.assign(settings, { protocol: "smtp" }),
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.changeSmtpSettingsValid(true);
|
||||||
|
this.args.group.setProperties({
|
||||||
|
smtp_server: this.form.smtp_server,
|
||||||
|
smtp_port: this.form.smtp_port,
|
||||||
|
smtp_ssl_mode: this.form.smtp_ssl_mode,
|
||||||
|
email_username: this.form.email_username,
|
||||||
|
email_from_alias: this.form.email_from_alias,
|
||||||
|
email_password: this.form.email_password,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(popupAjaxError)
|
||||||
|
.finally(() => (this.testingSettings = false));
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="group-smtp-email-settings">
|
||||||
|
<form class="groups-form form-horizontal group-smtp-form">
|
||||||
|
<div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="username">{{i18n
|
||||||
|
"groups.manage.email.credentials.username"
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="username"
|
||||||
|
class="group-smtp-form__smtp-username"
|
||||||
|
value={{this.form.email_username}}
|
||||||
|
tabindex="1"
|
||||||
|
{{on "input" (withEventValue this.changeEmailUsername)}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="smtp_server">{{i18n
|
||||||
|
"groups.manage.email.credentials.smtp_server"
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="smtp_server"
|
||||||
|
class="group-smtp-form__smtp-server"
|
||||||
|
value={{this.form.smtp_server}}
|
||||||
|
tabindex="4"
|
||||||
|
{{on "input" (withEventValue this.changeSmtpServer)}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="smtp_ssl_mode">
|
||||||
|
{{i18n "groups.manage.email.credentials.smtp_ssl_mode"}}
|
||||||
|
</label>
|
||||||
|
<ComboBox
|
||||||
|
@content={{this.sslModes}}
|
||||||
|
@valueProperty="value"
|
||||||
|
@value={{this.form.smtp_ssl_mode}}
|
||||||
|
name="smtp_ssl_mode"
|
||||||
|
class="group-smtp-form__smtp-ssl-mode"
|
||||||
|
tabindex="6"
|
||||||
|
@onChange={{this.onChangeSslMode}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="password">{{i18n
|
||||||
|
"groups.manage.email.credentials.password"
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
class="group-smtp-form__smtp-password"
|
||||||
|
value={{this.form.email_password}}
|
||||||
|
tabindex="2"
|
||||||
|
{{on "input" (withEventValue this.changeEmailPassword)}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="smtp_port">{{i18n
|
||||||
|
"groups.manage.email.credentials.smtp_port"
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="smtp_port"
|
||||||
|
class="group-smtp-form__smtp-port"
|
||||||
|
value={{this.form.smtp_port}}
|
||||||
|
tabindex="5"
|
||||||
|
{{on "input" (withEventValue this.changeSmtpPort)}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="from_alias">{{i18n
|
||||||
|
"groups.manage.email.settings.from_alias"
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="from_alias"
|
||||||
|
class="group-smtp-form__smtp-from-alias"
|
||||||
|
id="from_alias"
|
||||||
|
value={{this.form.email_from_alias}}
|
||||||
|
{{on "input" (withEventValue this.changeEmailFromAlias)}}
|
||||||
|
tabindex="3"
|
||||||
|
/>
|
||||||
|
<p>{{i18n "groups.manage.email.settings.from_alias_hint"}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="group-smtp-prefill-options">
|
||||||
|
{{i18n "groups.manage.email.prefill.title"}}
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="prefill_smtp_gmail"
|
||||||
|
href
|
||||||
|
{{on "click" (fn this.prefillSettings "gmail")}}
|
||||||
|
>{{i18n "groups.manage.email.prefill.gmail"}}</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="prefill_smtp_outlook"
|
||||||
|
href
|
||||||
|
{{on "click" (fn this.prefillSettings "outlook")}}
|
||||||
|
>{{i18n "groups.manage.email.prefill.outlook"}}</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="prefill_smtp_office365"
|
||||||
|
href
|
||||||
|
{{on "click" (fn this.prefillSettings "office365")}}
|
||||||
|
>{{i18n "groups.manage.email.prefill.office365"}}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group buttons">
|
||||||
|
<DButton
|
||||||
|
@disabled={{or this.missingSettings this.testingSettings}}
|
||||||
|
@action={{this.testSmtpSettings}}
|
||||||
|
@icon="cog"
|
||||||
|
@label="groups.manage.email.test_settings"
|
||||||
|
@title="groups.manage.email.settings_required"
|
||||||
|
tabindex="7"
|
||||||
|
class="btn-primary group-smtp-form__test-smtp-settings"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ConditionalLoadingSpinner
|
||||||
|
@size="small"
|
||||||
|
@condition={{this.testingSettings}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{{#if @smtpSettingsValid}}
|
||||||
|
<span class="group-smtp-form__smtp-settings-ok">
|
||||||
|
{{dIcon "check-circle"}}
|
||||||
|
{{i18n "groups.manage.email.smtp_settings_valid"}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if @group.smtp_updated_at}}
|
||||||
|
<div class=".group-smtp-form__last-updated-details">
|
||||||
|
<small>
|
||||||
|
{{i18n "groups.manage.email.last_updated"}}
|
||||||
|
<strong>{{formatDate
|
||||||
|
@group.smtp_updated_at
|
||||||
|
leaveAgo="true"
|
||||||
|
}}</strong>
|
||||||
|
{{i18n "groups.manage.email.last_updated_by"}}
|
||||||
|
<LinkTo
|
||||||
|
@route="user"
|
||||||
|
@model={{@group.smtp_updated_by.username}}
|
||||||
|
>{{@group.smtp_updated_by.username}}</LinkTo>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
|
@ -1,139 +0,0 @@
|
||||||
<div class="group-smtp-email-settings">
|
|
||||||
<form class="groups-form form-horizontal">
|
|
||||||
<div>
|
|
||||||
<div class="control-group">
|
|
||||||
<label for="username">{{i18n
|
|
||||||
"groups.manage.email.credentials.username"
|
|
||||||
}}</label>
|
|
||||||
<Input
|
|
||||||
@type="text"
|
|
||||||
name="username"
|
|
||||||
@value={{this.form.email_username}}
|
|
||||||
tabindex="1"
|
|
||||||
{{on "change" (action "resetSettingsValid")}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label for="smtp_server">{{i18n
|
|
||||||
"groups.manage.email.credentials.smtp_server"
|
|
||||||
}}</label>
|
|
||||||
<Input
|
|
||||||
@type="text"
|
|
||||||
name="smtp_server"
|
|
||||||
@value={{this.form.smtp_server}}
|
|
||||||
tabindex="4"
|
|
||||||
{{on "change" (action "resetSettingsValid")}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label for="enable_ssl" class="groups-form__enable-ssl">
|
|
||||||
<Input
|
|
||||||
@type="checkbox"
|
|
||||||
@checked={{this.form.smtp_ssl}}
|
|
||||||
id="enable_ssl"
|
|
||||||
tabindex="6"
|
|
||||||
{{on "change" (action "resetSettingsValid")}}
|
|
||||||
/>
|
|
||||||
{{i18n "groups.manage.email.credentials.smtp_ssl"}}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="control-group">
|
|
||||||
<label for="password">{{i18n
|
|
||||||
"groups.manage.email.credentials.password"
|
|
||||||
}}</label>
|
|
||||||
<Input
|
|
||||||
@type="password"
|
|
||||||
name="password"
|
|
||||||
@value={{this.form.email_password}}
|
|
||||||
tabindex="2"
|
|
||||||
{{on "change" (action "resetSettingsValid")}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label for="smtp_port">{{i18n
|
|
||||||
"groups.manage.email.credentials.smtp_port"
|
|
||||||
}}</label>
|
|
||||||
<Input
|
|
||||||
@type="text"
|
|
||||||
name="smtp_port"
|
|
||||||
@value={{this.form.smtp_port}}
|
|
||||||
tabindex="5"
|
|
||||||
{{on "change" (action "resetSettingsValid" this.form.smtp_port)}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="control-group">
|
|
||||||
<label for="from_alias">{{i18n
|
|
||||||
"groups.manage.email.settings.from_alias"
|
|
||||||
}}</label>
|
|
||||||
<Input
|
|
||||||
@type="text"
|
|
||||||
name="from_alias"
|
|
||||||
id="from_alias"
|
|
||||||
@value={{this.form.email_from_alias}}
|
|
||||||
{{on "change" (action "resetSettingsValid")}}
|
|
||||||
tabindex="3"
|
|
||||||
/>
|
|
||||||
<p>{{i18n "groups.manage.email.settings.from_alias_hint"}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<div class="group-smtp-prefill-options">
|
|
||||||
{{i18n "groups.manage.email.prefill.title"}}
|
|
||||||
<a
|
|
||||||
id="prefill_smtp_gmail"
|
|
||||||
href
|
|
||||||
{{on "click" (fn this.prefillSettings "gmail")}}
|
|
||||||
>{{i18n "groups.manage.email.prefill.gmail"}}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group buttons">
|
|
||||||
<DButton
|
|
||||||
@disabled={{or this.missingSettings this.testingSettings}}
|
|
||||||
@action={{this.testSmtpSettings}}
|
|
||||||
@icon="cog"
|
|
||||||
@label="groups.manage.email.test_settings"
|
|
||||||
@title="groups.manage.email.settings_required"
|
|
||||||
tabindex="7"
|
|
||||||
class="btn-primary test-smtp-settings"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConditionalLoadingSpinner
|
|
||||||
@size="small"
|
|
||||||
@condition={{this.testingSettings}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{{#if this.smtpSettingsValid}}
|
|
||||||
<span class="smtp-settings-ok">
|
|
||||||
{{d-icon "check-circle"}}
|
|
||||||
{{i18n "groups.manage.email.smtp_settings_valid"}}
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if this.group.smtp_updated_at}}
|
|
||||||
<div class="group-email-last-updated-details for-smtp">
|
|
||||||
<small>
|
|
||||||
{{i18n "groups.manage.email.last_updated"}}
|
|
||||||
<strong>{{format-date
|
|
||||||
this.group.smtp_updated_at
|
|
||||||
leaveAgo="true"
|
|
||||||
}}</strong>
|
|
||||||
{{i18n "groups.manage.email.last_updated_by"}}
|
|
||||||
<LinkTo
|
|
||||||
@route="user"
|
|
||||||
@model={{this.group.smtp_updated_by.username}}
|
|
||||||
>{{this.group.smtp_updated_by.username}}</LinkTo>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
|
@ -1,82 +0,0 @@
|
||||||
import Component from "@ember/component";
|
|
||||||
import EmberObject, { action } from "@ember/object";
|
|
||||||
import { isEmpty } from "@ember/utils";
|
|
||||||
import { ajax } from "discourse/lib/ajax";
|
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
|
||||||
import emailProviderDefaultSettings from "discourse/lib/email-provider-default-settings";
|
|
||||||
import discourseComputed, { on } from "discourse-common/utils/decorators";
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: "",
|
|
||||||
form: null,
|
|
||||||
|
|
||||||
@discourseComputed(
|
|
||||||
"form.email_username",
|
|
||||||
"form.email_password",
|
|
||||||
"form.smtp_server",
|
|
||||||
"form.smtp_port"
|
|
||||||
)
|
|
||||||
missingSettings(email_username, email_password, smtp_server, smtp_port) {
|
|
||||||
return [email_username, email_password, smtp_server, smtp_port].some(
|
|
||||||
(value) => isEmpty(value)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
resetSettingsValid() {
|
|
||||||
this.set("smtpSettingsValid", false);
|
|
||||||
},
|
|
||||||
|
|
||||||
@on("init")
|
|
||||||
_fillForm() {
|
|
||||||
this.set(
|
|
||||||
"form",
|
|
||||||
EmberObject.create({
|
|
||||||
email_username: this.group.email_username,
|
|
||||||
email_password: this.group.email_password,
|
|
||||||
email_from_alias: this.group.email_from_alias,
|
|
||||||
smtp_server: this.group.smtp_server,
|
|
||||||
smtp_port: (this.group.smtp_port || "").toString(),
|
|
||||||
smtp_ssl: this.group.smtp_ssl,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
prefillSettings(provider, event) {
|
|
||||||
event?.preventDefault();
|
|
||||||
this.form.setProperties(emailProviderDefaultSettings(provider, "smtp"));
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
testSmtpSettings() {
|
|
||||||
const settings = {
|
|
||||||
host: this.form.smtp_server,
|
|
||||||
port: this.form.smtp_port,
|
|
||||||
ssl: this.form.smtp_ssl,
|
|
||||||
username: this.form.email_username,
|
|
||||||
password: this.form.email_password,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.set("testingSettings", true);
|
|
||||||
this.set("smtpSettingsValid", false);
|
|
||||||
|
|
||||||
return ajax(`/groups/${this.group.id}/test_email_settings`, {
|
|
||||||
type: "POST",
|
|
||||||
data: Object.assign(settings, { protocol: "smtp" }),
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.set("smtpSettingsValid", true);
|
|
||||||
this.group.setProperties({
|
|
||||||
smtp_server: this.form.smtp_server,
|
|
||||||
smtp_port: this.form.smtp_port,
|
|
||||||
smtp_ssl: this.form.smtp_ssl,
|
|
||||||
email_username: this.form.email_username,
|
|
||||||
email_from_alias: this.form.email_from_alias,
|
|
||||||
email_password: this.form.email_password,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(popupAjaxError)
|
|
||||||
.finally(() => this.set("testingSettings", false));
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -69,6 +69,8 @@ export const AUTO_GROUPS = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const GROUP_SMTP_SSL_MODES = { none: 0, ssl_tls: 1, starttls: 2 };
|
||||||
|
|
||||||
export const MAX_NOTIFICATIONS_LIMIT_PARAMS = 60;
|
export const MAX_NOTIFICATIONS_LIMIT_PARAMS = 60;
|
||||||
|
|
||||||
export const TOPIC_VISIBILITY_REASONS = {
|
export const TOPIC_VISIBILITY_REASONS = {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { GROUP_SMTP_SSL_MODES } from "discourse/lib/constants";
|
||||||
|
|
||||||
const GMAIL = {
|
const GMAIL = {
|
||||||
imap: {
|
imap: {
|
||||||
imap_server: "imap.gmail.com",
|
imap_server: "imap.gmail.com",
|
||||||
|
@ -7,7 +9,23 @@ const GMAIL = {
|
||||||
smtp: {
|
smtp: {
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
smtp_port: "587",
|
smtp_port: "587",
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: GROUP_SMTP_SSL_MODES.starttls,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const OUTLOOK = {
|
||||||
|
smtp: {
|
||||||
|
smtp_server: "smtp-mail.outlook.com",
|
||||||
|
smtp_port: "587",
|
||||||
|
smtp_ssl_mode: GROUP_SMTP_SSL_MODES.starttls,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const OFFICE365 = {
|
||||||
|
smtp: {
|
||||||
|
smtp_server: "smtp.office365.com",
|
||||||
|
smtp_port: "587",
|
||||||
|
smtp_ssl_mode: GROUP_SMTP_SSL_MODES.starttls,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,5 +36,9 @@ export default function emailProviderDefaultSettings(provider, protocol) {
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case "gmail":
|
case "gmail":
|
||||||
return GMAIL[protocol];
|
return GMAIL[protocol];
|
||||||
|
case "office365":
|
||||||
|
return OFFICE365[protocol];
|
||||||
|
case "outlook":
|
||||||
|
return OUTLOOK[protocol];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -344,7 +344,7 @@ export default class Group extends RestModel {
|
||||||
incoming_email: this.incoming_email,
|
incoming_email: this.incoming_email,
|
||||||
smtp_server: this.smtp_server,
|
smtp_server: this.smtp_server,
|
||||||
smtp_port: this.smtp_port,
|
smtp_port: this.smtp_port,
|
||||||
smtp_ssl: this.smtp_ssl,
|
smtp_ssl_mode: this.smtp_ssl_mode,
|
||||||
smtp_enabled: this.smtp_enabled,
|
smtp_enabled: this.smtp_enabled,
|
||||||
imap_server: this.imap_server,
|
imap_server: this.imap_server,
|
||||||
imap_port: this.imap_port,
|
imap_port: this.imap_port,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { click, currentRouteName, fillIn, visit } from "@ember/test-helpers";
|
import { click, currentRouteName, fillIn, visit } from "@ember/test-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
|
import { GROUP_SMTP_SSL_MODES } from "discourse/lib/constants";
|
||||||
import {
|
import {
|
||||||
acceptance,
|
acceptance,
|
||||||
exists,
|
exists,
|
||||||
|
@ -85,22 +86,23 @@ acceptance(
|
||||||
|
|
||||||
await click("#prefill_smtp_gmail");
|
await click("#prefill_smtp_gmail");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query("input[name='smtp_server']").value,
|
query(".group-smtp-form__smtp-server").value,
|
||||||
"smtp.gmail.com",
|
"smtp.gmail.com",
|
||||||
"prefills SMTP server settings for gmail"
|
"prefills SMTP server settings for gmail"
|
||||||
);
|
);
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query("input[name='smtp_port']").value,
|
query(".group-smtp-form__smtp-port").value,
|
||||||
"587",
|
"587",
|
||||||
"prefills SMTP port settings for gmail"
|
"prefills SMTP port settings for gmail"
|
||||||
);
|
);
|
||||||
assert.ok(
|
assert.strictEqual(
|
||||||
exists("#enable_ssl:checked"),
|
selectKit(".group-smtp-form__smtp-ssl-mode").header().value(),
|
||||||
"prefills SMTP ssl settings for gmail"
|
GROUP_SMTP_SSL_MODES.starttls.toString(),
|
||||||
|
"prefills SSL mode to STARTTLS for gmail"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists(".test-smtp-settings:disabled"),
|
exists(".group-smtp-form__test-smtp-settings:disabled"),
|
||||||
"does not allow testing settings if not all fields are filled"
|
"does not allow testing settings if not all fields are filled"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -108,9 +110,12 @@ acceptance(
|
||||||
await fillIn('input[name="password"]', "password@gmail.com");
|
await fillIn('input[name="password"]', "password@gmail.com");
|
||||||
await fillIn("#from_alias", "akasomegroup@example.com");
|
await fillIn("#from_alias", "akasomegroup@example.com");
|
||||||
|
|
||||||
await click(".test-smtp-settings");
|
await click(".group-smtp-form__test-smtp-settings");
|
||||||
|
|
||||||
assert.ok(exists(".smtp-settings-ok"), "tested settings are ok");
|
assert.ok(
|
||||||
|
exists(".group-smtp-form__smtp-settings-ok"),
|
||||||
|
"tested settings are ok"
|
||||||
|
);
|
||||||
|
|
||||||
await click(".group-manage-save");
|
await click(".group-manage-save");
|
||||||
|
|
||||||
|
@ -141,7 +146,7 @@ acceptance(
|
||||||
await click("#prefill_smtp_gmail");
|
await click("#prefill_smtp_gmail");
|
||||||
await fillIn('input[name="username"]', "myusername@gmail.com");
|
await fillIn('input[name="username"]', "myusername@gmail.com");
|
||||||
await fillIn('input[name="password"]', "password@gmail.com");
|
await fillIn('input[name="password"]', "password@gmail.com");
|
||||||
await click(".test-smtp-settings");
|
await click(".group-smtp-form__test-smtp-settings");
|
||||||
await click(".group-manage-save");
|
await click(".group-manage-save");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
|
@ -168,7 +173,7 @@ acceptance(
|
||||||
"prefills IMAP port settings for gmail"
|
"prefills IMAP port settings for gmail"
|
||||||
);
|
);
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists("#enable_ssl:checked"),
|
exists("#enable_ssl_imap:checked"),
|
||||||
"prefills IMAP ssl settings for gmail"
|
"prefills IMAP ssl settings for gmail"
|
||||||
);
|
);
|
||||||
await click(".test-imap-settings");
|
await click(".test-imap-settings");
|
||||||
|
@ -239,7 +244,7 @@ acceptance(
|
||||||
message_count: 2,
|
message_count: 2,
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: GROUP_SMTP_SSL_MODES.starttls,
|
||||||
smtp_enabled: true,
|
smtp_enabled: true,
|
||||||
smtp_updated_at: "2021-06-16T02:58:12.739Z",
|
smtp_updated_at: "2021-06-16T02:58:12.739Z",
|
||||||
smtp_updated_by: {
|
smtp_updated_by: {
|
||||||
|
@ -324,13 +329,6 @@ acceptance(
|
||||||
),
|
),
|
||||||
"shows last updated imap details"
|
"shows last updated imap details"
|
||||||
);
|
);
|
||||||
assert.ok(exists(".group-email-last-updated-details.for-smtp"));
|
|
||||||
assert.ok(
|
|
||||||
regex.test(
|
|
||||||
query(".group-email-last-updated-details.for-smtp").innerText.trim()
|
|
||||||
),
|
|
||||||
"shows last updated smtp details"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -359,7 +357,7 @@ acceptance(
|
||||||
await click("#prefill_smtp_gmail");
|
await click("#prefill_smtp_gmail");
|
||||||
await fillIn('input[name="username"]', "myusername@gmail.com");
|
await fillIn('input[name="username"]', "myusername@gmail.com");
|
||||||
await fillIn('input[name="password"]', "password@gmail.com");
|
await fillIn('input[name="password"]', "password@gmail.com");
|
||||||
await click(".test-smtp-settings");
|
await click(".group-smtp-form__test-smtp-settings");
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query(".dialog-body").innerText.trim(),
|
query(".dialog-body").innerText.trim(),
|
||||||
|
|
|
@ -269,6 +269,25 @@ table.group-category-permissions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-smtp-prefill-options {
|
||||||
|
ul {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "|";
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child:before {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.group-smtp-email-settings,
|
.group-smtp-email-settings,
|
||||||
.group-imap-email-settings {
|
.group-imap-email-settings {
|
||||||
background-color: var(--primary-very-low);
|
background-color: var(--primary-very-low);
|
||||||
|
@ -289,10 +308,6 @@ table.group-category-permissions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.groups-form__enable-ssl {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-manage-email-additional-settings-wrapper {
|
.group-manage-email-additional-settings-wrapper {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -715,7 +715,6 @@ class GroupsController < ApplicationController
|
||||||
params.require(:host)
|
params.require(:host)
|
||||||
params.require(:username)
|
params.require(:username)
|
||||||
params.require(:password)
|
params.require(:password)
|
||||||
params.require(:ssl)
|
|
||||||
|
|
||||||
group = Group.find(params[:group_id])
|
group = Group.find(params[:group_id])
|
||||||
guardian.ensure_can_edit!(group)
|
guardian.ensure_can_edit!(group)
|
||||||
|
@ -723,7 +722,6 @@ class GroupsController < ApplicationController
|
||||||
RateLimiter.new(current_user, "group_test_email_settings", 5, 1.minute).performed!
|
RateLimiter.new(current_user, "group_test_email_settings", 5, 1.minute).performed!
|
||||||
|
|
||||||
settings = params.except(:group_id, :protocol)
|
settings = params.except(:group_id, :protocol)
|
||||||
enable_tls = settings[:ssl] == "true"
|
|
||||||
email_host = params[:host]
|
email_host = params[:host]
|
||||||
|
|
||||||
if !%w[smtp imap].include?(params[:protocol])
|
if !%w[smtp imap].include?(params[:protocol])
|
||||||
|
@ -734,13 +732,19 @@ class GroupsController < ApplicationController
|
||||||
begin
|
begin
|
||||||
case params[:protocol]
|
case params[:protocol]
|
||||||
when "smtp"
|
when "smtp"
|
||||||
enable_starttls_auto = false
|
raise Discourse::InvalidParameters if params[:ssl_mode].blank?
|
||||||
settings.delete(:ssl)
|
|
||||||
|
settings.delete(:ssl_mode)
|
||||||
|
|
||||||
|
if params[:ssl_mode].blank? ||
|
||||||
|
!Group.smtp_ssl_modes.values.include?(params[:ssl_mode].to_i)
|
||||||
|
raise Discourse::InvalidParameters.new("SSL mode must be present and valid")
|
||||||
|
end
|
||||||
|
|
||||||
final_settings =
|
final_settings =
|
||||||
settings.merge(
|
settings.merge(
|
||||||
enable_tls: enable_tls,
|
enable_tls: params[:ssl_mode].to_i == Group.smtp_ssl_modes[:ssl_tls],
|
||||||
enable_starttls_auto: enable_starttls_auto,
|
enable_starttls_auto: params[:ssl_mode].to_i == Group.smtp_ssl_modes[:starttls],
|
||||||
).permit(:host, :port, :username, :password, :enable_tls, :enable_starttls_auto, :debug)
|
).permit(:host, :port, :username, :password, :enable_tls, :enable_starttls_auto, :debug)
|
||||||
EmailSettingsValidator.validate_as_user(
|
EmailSettingsValidator.validate_as_user(
|
||||||
current_user,
|
current_user,
|
||||||
|
@ -748,8 +752,17 @@ class GroupsController < ApplicationController
|
||||||
**final_settings.to_h.symbolize_keys,
|
**final_settings.to_h.symbolize_keys,
|
||||||
)
|
)
|
||||||
when "imap"
|
when "imap"
|
||||||
|
raise Discourse::InvalidParameters if params[:ssl].blank?
|
||||||
|
|
||||||
final_settings =
|
final_settings =
|
||||||
settings.merge(ssl: enable_tls).permit(:host, :port, :username, :password, :ssl, :debug)
|
settings.merge(ssl: settings[:ssl] == "true").permit(
|
||||||
|
:host,
|
||||||
|
:port,
|
||||||
|
:username,
|
||||||
|
:password,
|
||||||
|
:ssl,
|
||||||
|
:debug,
|
||||||
|
)
|
||||||
EmailSettingsValidator.validate_as_user(
|
EmailSettingsValidator.validate_as_user(
|
||||||
current_user,
|
current_user,
|
||||||
"imap",
|
"imap",
|
||||||
|
@ -812,7 +825,7 @@ class GroupsController < ApplicationController
|
||||||
:incoming_email,
|
:incoming_email,
|
||||||
:smtp_server,
|
:smtp_server,
|
||||||
:smtp_port,
|
:smtp_port,
|
||||||
:smtp_ssl,
|
:smtp_ssl_mode,
|
||||||
:smtp_enabled,
|
:smtp_enabled,
|
||||||
:smtp_updated_by,
|
:smtp_updated_by,
|
||||||
:smtp_updated_at,
|
:smtp_updated_at,
|
||||||
|
@ -890,7 +903,7 @@ class GroupsController < ApplicationController
|
||||||
|
|
||||||
if should_clear_smtp
|
if should_clear_smtp
|
||||||
attributes[:smtp_server] = nil
|
attributes[:smtp_server] = nil
|
||||||
attributes[:smtp_ssl] = false
|
attributes[:smtp_ssl_mode] = false
|
||||||
attributes[:smtp_port] = nil
|
attributes[:smtp_port] = nil
|
||||||
attributes[:email_username] = nil
|
attributes[:email_username] = nil
|
||||||
attributes[:email_password] = nil
|
attributes[:email_password] = nil
|
||||||
|
|
|
@ -18,7 +18,8 @@ class GroupSmtpMailer < ActionMailer::Base
|
||||||
# NOTE: Might be better at some point to store this authentication method in the database
|
# NOTE: Might be better at some point to store this authentication method in the database
|
||||||
# against the group.
|
# against the group.
|
||||||
authentication: SmtpProviderOverrides.authentication_override(from_group.smtp_server),
|
authentication: SmtpProviderOverrides.authentication_override(from_group.smtp_server),
|
||||||
enable_starttls_auto: from_group.smtp_ssl,
|
enable_starttls_auto: from_group.smtp_ssl_mode == Group.smtp_ssl_modes[:starttls],
|
||||||
|
enable_ssl: from_group.smtp_ssl_mode == Group.smtp_ssl_modes[:ssl_tls],
|
||||||
return_response: true,
|
return_response: true,
|
||||||
open_timeout: GlobalSetting.group_smtp_open_timeout,
|
open_timeout: GlobalSetting.group_smtp_open_timeout,
|
||||||
read_timeout: GlobalSetting.group_smtp_read_timeout,
|
read_timeout: GlobalSetting.group_smtp_read_timeout,
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
require "net/imap"
|
require "net/imap"
|
||||||
|
|
||||||
class Group < ActiveRecord::Base
|
class Group < ActiveRecord::Base
|
||||||
self.ignored_columns = %w[flair_url] # TODO: Remove when 20240212034010_drop_deprecated_columns has been promoted to pre-deploy
|
# TODO: Remove flair_url when 20240212034010_drop_deprecated_columns has been promoted to pre-deploy
|
||||||
|
# TODO: Remove smtp_ssl when db/post_migrate/20240717053710_drop_groups_smtp_ssl has been promoted to pre-deploy
|
||||||
|
self.ignored_columns = %w[flair_url smtp_ssl]
|
||||||
|
|
||||||
include HasCustomFields
|
include HasCustomFields
|
||||||
include AnonCacheInvalidator
|
include AnonCacheInvalidator
|
||||||
|
@ -145,6 +147,10 @@ class Group < ActiveRecord::Base
|
||||||
@visibility_levels = Enum.new(public: 0, logged_on_users: 1, members: 2, staff: 3, owners: 4)
|
@visibility_levels = Enum.new(public: 0, logged_on_users: 1, members: 2, staff: 3, owners: 4)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.smtp_ssl_modes
|
||||||
|
@visibility_levels = Enum.new(none: 0, ssl_tls: 1, starttls: 2)
|
||||||
|
end
|
||||||
|
|
||||||
def self.auto_groups_between(lower, upper)
|
def self.auto_groups_between(lower, upper)
|
||||||
lower_group = Group::AUTO_GROUPS[lower.to_sym]
|
lower_group = Group::AUTO_GROUPS[lower.to_sym]
|
||||||
upper_group = Group::AUTO_GROUPS[upper.to_sym]
|
upper_group = Group::AUTO_GROUPS[upper.to_sym]
|
||||||
|
@ -1292,7 +1298,6 @@ end
|
||||||
# mentionable_level :integer default(0)
|
# mentionable_level :integer default(0)
|
||||||
# smtp_server :string
|
# smtp_server :string
|
||||||
# smtp_port :integer
|
# smtp_port :integer
|
||||||
# smtp_ssl :boolean
|
|
||||||
# imap_server :string
|
# imap_server :string
|
||||||
# imap_port :integer
|
# imap_port :integer
|
||||||
# imap_ssl :boolean
|
# imap_ssl :boolean
|
||||||
|
@ -1316,6 +1321,7 @@ end
|
||||||
# imap_updated_at :datetime
|
# imap_updated_at :datetime
|
||||||
# imap_updated_by_id :integer
|
# imap_updated_by_id :integer
|
||||||
# email_from_alias :string
|
# email_from_alias :string
|
||||||
|
# smtp_ssl_mode :integer default(0), not null
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -24,7 +24,7 @@ class GroupShowSerializer < BasicGroupSerializer
|
||||||
admin_attributes :automatic_membership_email_domains,
|
admin_attributes :automatic_membership_email_domains,
|
||||||
:smtp_server,
|
:smtp_server,
|
||||||
:smtp_port,
|
:smtp_port,
|
||||||
:smtp_ssl,
|
:smtp_ssl_mode,
|
||||||
:smtp_enabled,
|
:smtp_enabled,
|
||||||
:smtp_updated_at,
|
:smtp_updated_at,
|
||||||
:smtp_updated_by,
|
:smtp_updated_by,
|
||||||
|
|
|
@ -62,9 +62,6 @@ class EmailSettingsValidator
|
||||||
# Attempts to start an SMTP session and if that raises an error then it is
|
# Attempts to start an SMTP session and if that raises an error then it is
|
||||||
# assumed the credentials or other settings are wrong.
|
# assumed the credentials or other settings are wrong.
|
||||||
#
|
#
|
||||||
# For Gmail, the port should be 587, enable_starttls_auto should be true,
|
|
||||||
# and enable_tls should be false.
|
|
||||||
#
|
|
||||||
# @param domain [String] - Used for HELO, should be the FQDN of the server sending the mail
|
# @param domain [String] - Used for HELO, should be the FQDN of the server sending the mail
|
||||||
# localhost can be used in development mode.
|
# localhost can be used in development mode.
|
||||||
# See https://datatracker.ietf.org/doc/html/rfc788#section-4
|
# See https://datatracker.ietf.org/doc/html/rfc788#section-4
|
||||||
|
@ -83,9 +80,6 @@ class EmailSettingsValidator
|
||||||
debug: Rails.env.development?
|
debug: Rails.env.development?
|
||||||
)
|
)
|
||||||
begin
|
begin
|
||||||
port, enable_tls, enable_starttls_auto =
|
|
||||||
SmtpProviderOverrides.ssl_override(host, port, enable_tls, enable_starttls_auto)
|
|
||||||
|
|
||||||
if enable_tls && enable_starttls_auto
|
if enable_tls && enable_starttls_auto
|
||||||
raise ArgumentError, "TLS and STARTTLS are mutually exclusive"
|
raise ArgumentError, "TLS and STARTTLS are mutually exclusive"
|
||||||
end
|
end
|
||||||
|
|
|
@ -873,11 +873,17 @@ en:
|
||||||
prefill:
|
prefill:
|
||||||
title: "Prefill with settings for:"
|
title: "Prefill with settings for:"
|
||||||
gmail: "Gmail"
|
gmail: "Gmail"
|
||||||
|
outlook: "Outlook.com"
|
||||||
|
office365: "Microsoft 365"
|
||||||
|
ssl_modes:
|
||||||
|
none: "None"
|
||||||
|
ssl_tls: "SSL/TLS"
|
||||||
|
starttls: "STARTTLS"
|
||||||
credentials:
|
credentials:
|
||||||
title: "Credentials"
|
title: "Credentials"
|
||||||
smtp_server: "SMTP Server"
|
smtp_server: "SMTP Server"
|
||||||
smtp_port: "SMTP Port"
|
smtp_port: "SMTP Port"
|
||||||
smtp_ssl: "Use SSL for SMTP"
|
smtp_ssl_mode: "SSL Mode"
|
||||||
imap_server: "IMAP Server"
|
imap_server: "IMAP Server"
|
||||||
imap_port: "IMAP Port"
|
imap_port: "IMAP Port"
|
||||||
imap_ssl: "Use SSL for IMAP"
|
imap_ssl: "Use SSL for IMAP"
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
class AddSmtpSslModeToGroups < ActiveRecord::Migration[7.1]
|
||||||
|
def up
|
||||||
|
add_column :groups, :smtp_ssl_mode, :integer, default: 0, null: false
|
||||||
|
|
||||||
|
execute <<~SQL
|
||||||
|
UPDATE groups SET smtp_ssl_mode = (CASE WHEN smtp_ssl THEN 2 ELSE 0 END)
|
||||||
|
SQL
|
||||||
|
|
||||||
|
Migration::ColumnDropper.mark_readonly(:groups, :smtp_ssl)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
Migration::ColumnDropper.drop_readonly(:groups, :smtp_ssl)
|
||||||
|
remove_column :groups, :smtp_ssl_mode
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropGroupsSmtpSsl < ActiveRecord::Migration[7.1]
|
||||||
|
DROPPED_COLUMNS ||= { groups: %i[smtp_ssl] }
|
||||||
|
|
||||||
|
def up
|
||||||
|
DROPPED_COLUMNS.each { |table, columns| Migration::ColumnDropper.execute_drop(table, columns) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,20 +9,4 @@ class SmtpProviderOverrides
|
||||||
return "login" if %w[smtp.office365.com smtp-mail.outlook.com].include?(host)
|
return "login" if %w[smtp.office365.com smtp-mail.outlook.com].include?(host)
|
||||||
GlobalSetting.smtp_authentication
|
GlobalSetting.smtp_authentication
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.ssl_override(host, port, enable_tls, enable_starttls_auto)
|
|
||||||
# Certain mail servers act weirdly if you do not use the correct combinations of
|
|
||||||
# TLS settings based on the port, we clean these up here for the user.
|
|
||||||
if %w[smtp.gmail.com smtp.office365.com smtp-mail.outlook.com].include?(host)
|
|
||||||
if port.to_i == 587
|
|
||||||
enable_starttls_auto = true
|
|
||||||
enable_tls = false
|
|
||||||
elsif port.to_i == 465
|
|
||||||
enable_starttls_auto = false
|
|
||||||
enable_tls = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
[port, enable_tls, enable_starttls_auto]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -154,6 +154,8 @@ task "javascript:update_constants" => :environment do
|
||||||
|
|
||||||
export const AUTO_GROUPS = #{auto_groups.to_json};
|
export const AUTO_GROUPS = #{auto_groups.to_json};
|
||||||
|
|
||||||
|
export const GROUP_SMTP_SSL_MODES = #{Group.smtp_ssl_modes.to_json};
|
||||||
|
|
||||||
export const MAX_NOTIFICATIONS_LIMIT_PARAMS = #{NotificationsController::INDEX_LIMIT};
|
export const MAX_NOTIFICATIONS_LIMIT_PARAMS = #{NotificationsController::INDEX_LIMIT};
|
||||||
|
|
||||||
export const TOPIC_VISIBILITY_REASONS = #{Topic.visibility_reasons.to_json};
|
export const TOPIC_VISIBILITY_REASONS = #{Topic.visibility_reasons.to_json};
|
||||||
|
|
|
@ -164,7 +164,7 @@ describe "PMCreated" do
|
||||||
incoming_email: "team@somesmtpaddress.com|suppor+team@bar.com",
|
incoming_email: "team@somesmtpaddress.com|suppor+team@bar.com",
|
||||||
smtp_server: "smtp.test.com",
|
smtp_server: "smtp.test.com",
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_enabled: true,
|
smtp_enabled: true,
|
||||||
)
|
)
|
||||||
SiteSetting.email_in = true
|
SiteSetting.email_in = true
|
||||||
|
|
|
@ -10,7 +10,7 @@ end
|
||||||
Fabricator(:imap_group, from: :group) do
|
Fabricator(:imap_group, from: :group) do
|
||||||
smtp_server "smtp.ponyexpress.com"
|
smtp_server "smtp.ponyexpress.com"
|
||||||
smtp_port 587
|
smtp_port 587
|
||||||
smtp_ssl true
|
smtp_ssl_mode Group.smtp_ssl_modes[:starttls]
|
||||||
smtp_enabled true
|
smtp_enabled true
|
||||||
imap_server "imap.ponyexpress.com"
|
imap_server "imap.ponyexpress.com"
|
||||||
imap_port 993
|
imap_port 993
|
||||||
|
@ -26,7 +26,7 @@ end
|
||||||
Fabricator(:smtp_group, from: :group) do
|
Fabricator(:smtp_group, from: :group) do
|
||||||
smtp_server "smtp.ponyexpress.com"
|
smtp_server "smtp.ponyexpress.com"
|
||||||
smtp_port 587
|
smtp_port 587
|
||||||
smtp_ssl true
|
smtp_ssl_mode Group.smtp_ssl_modes[:starttls]
|
||||||
smtp_enabled true
|
smtp_enabled true
|
||||||
email_username "discourseteam@ponyexpress.com"
|
email_username "discourseteam@ponyexpress.com"
|
||||||
email_password "test"
|
email_password "test"
|
||||||
|
|
|
@ -1223,7 +1223,7 @@ RSpec.describe Email::Receiver do
|
||||||
incoming_email: "team@somesmtpaddress.com|support+team@bar.com",
|
incoming_email: "team@somesmtpaddress.com|support+team@bar.com",
|
||||||
smtp_server: "smtp.test.com",
|
smtp_server: "smtp.test.com",
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_enabled: true,
|
smtp_enabled: true,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -1318,7 +1318,7 @@ RSpec.describe Email::Receiver do
|
||||||
incoming_email: "team@somesmtpaddress.com|suppor+team@bar.com",
|
incoming_email: "team@somesmtpaddress.com|suppor+team@bar.com",
|
||||||
smtp_server: "smtp.test.com",
|
smtp_server: "smtp.test.com",
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_enabled: true,
|
smtp_enabled: true,
|
||||||
)
|
)
|
||||||
process(:email_to_group_email_username_1)
|
process(:email_to_group_email_username_1)
|
||||||
|
|
|
@ -10,7 +10,7 @@ RSpec.describe GroupSmtpMailer do
|
||||||
full_name: "Testers Group",
|
full_name: "Testers Group",
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_enabled: true,
|
smtp_enabled: true,
|
||||||
imap_server: "imap.gmail.com",
|
imap_server: "imap.gmail.com",
|
||||||
imap_port: 993,
|
imap_port: 993,
|
||||||
|
@ -128,6 +128,7 @@ RSpec.describe GroupSmtpMailer do
|
||||||
password: "super$secret$password",
|
password: "super$secret$password",
|
||||||
authentication: GlobalSetting.smtp_authentication,
|
authentication: GlobalSetting.smtp_authentication,
|
||||||
enable_starttls_auto: true,
|
enable_starttls_auto: true,
|
||||||
|
enable_ssl: false,
|
||||||
return_response: true,
|
return_response: true,
|
||||||
open_timeout: GlobalSetting.group_smtp_open_timeout,
|
open_timeout: GlobalSetting.group_smtp_open_timeout,
|
||||||
read_timeout: GlobalSetting.group_smtp_read_timeout,
|
read_timeout: GlobalSetting.group_smtp_read_timeout,
|
||||||
|
|
|
@ -1397,7 +1397,7 @@ RSpec.describe Group do
|
||||||
it "enables smtp and records the change" do
|
it "enables smtp and records the change" do
|
||||||
group.update(
|
group.update(
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
email_username: "test@gmail.com",
|
email_username: "test@gmail.com",
|
||||||
email_password: "password",
|
email_password: "password",
|
||||||
|
@ -1414,7 +1414,7 @@ RSpec.describe Group do
|
||||||
it "records the change for singular setting changes" do
|
it "records the change for singular setting changes" do
|
||||||
group.update(
|
group.update(
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
email_username: "test@gmail.com",
|
email_username: "test@gmail.com",
|
||||||
email_password: "password",
|
email_password: "password",
|
||||||
|
@ -1448,7 +1448,7 @@ RSpec.describe Group do
|
||||||
it "disables smtp and records the change" do
|
it "disables smtp and records the change" do
|
||||||
group.update(
|
group.update(
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
email_username: "test@gmail.com",
|
email_username: "test@gmail.com",
|
||||||
email_password: "password",
|
email_password: "password",
|
||||||
|
@ -1460,7 +1460,7 @@ RSpec.describe Group do
|
||||||
|
|
||||||
group.update(
|
group.update(
|
||||||
smtp_port: nil,
|
smtp_port: nil,
|
||||||
smtp_ssl: false,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:none],
|
||||||
smtp_server: nil,
|
smtp_server: nil,
|
||||||
email_username: nil,
|
email_username: nil,
|
||||||
email_password: nil,
|
email_password: nil,
|
||||||
|
|
|
@ -170,9 +170,9 @@
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"smtp_ssl": {
|
"smtp_ssl_mode": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"integer",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -363,7 +363,7 @@
|
||||||
"automatic_membership_email_domains",
|
"automatic_membership_email_domains",
|
||||||
"smtp_server",
|
"smtp_server",
|
||||||
"smtp_port",
|
"smtp_port",
|
||||||
"smtp_ssl",
|
"smtp_ssl_mode",
|
||||||
"imap_server",
|
"imap_server",
|
||||||
"imap_port",
|
"imap_port",
|
||||||
"imap_ssl",
|
"imap_ssl",
|
||||||
|
|
|
@ -2766,6 +2766,7 @@ RSpec.describe GroupsController do
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{
|
{
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
|
ssl_mode: ssl_mode,
|
||||||
ssl: ssl,
|
ssl: ssl,
|
||||||
port: port,
|
port: port,
|
||||||
host: host,
|
host: host,
|
||||||
|
@ -2784,7 +2785,8 @@ RSpec.describe GroupsController do
|
||||||
let(:username) { "test@gmail.com" }
|
let(:username) { "test@gmail.com" }
|
||||||
let(:password) { "password" }
|
let(:password) { "password" }
|
||||||
let(:domain) { nil }
|
let(:domain) { nil }
|
||||||
let(:ssl) { true }
|
let(:ssl_mode) { Group.smtp_ssl_modes[:starttls] }
|
||||||
|
let(:ssl) { nil }
|
||||||
let(:host) { "smtp.somemailsite.com" }
|
let(:host) { "smtp.somemailsite.com" }
|
||||||
let(:port) { 587 }
|
let(:port) { 587 }
|
||||||
|
|
||||||
|
@ -2811,11 +2813,12 @@ RSpec.describe GroupsController do
|
||||||
let(:password) { "password" }
|
let(:password) { "password" }
|
||||||
let(:domain) { nil }
|
let(:domain) { nil }
|
||||||
let(:ssl) { true }
|
let(:ssl) { true }
|
||||||
|
let(:ssl_mode) { nil }
|
||||||
let(:host) { "imap.somemailsite.com" }
|
let(:host) { "imap.somemailsite.com" }
|
||||||
let(:port) { 993 }
|
let(:port) { 993 }
|
||||||
|
|
||||||
it "validates with the correct TLS settings" do
|
it "validates with the correct TLS settings" do
|
||||||
EmailSettingsValidator.expects(:validate_imap).with(has_entry(ssl: true))
|
EmailSettingsValidator.expects(:validate_imap).with(has_entries(ssl: true))
|
||||||
post "/groups/#{group.id}/test_email_settings.json", params: params
|
post "/groups/#{group.id}/test_email_settings.json", params: params
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
end
|
end
|
||||||
|
@ -2844,6 +2847,7 @@ RSpec.describe GroupsController do
|
||||||
let(:username) { "test@gmail.com" }
|
let(:username) { "test@gmail.com" }
|
||||||
let(:password) { "password" }
|
let(:password) { "password" }
|
||||||
let(:ssl) { true }
|
let(:ssl) { true }
|
||||||
|
let(:ssl_mode) { nil }
|
||||||
|
|
||||||
context "when the protocol is not accepted" do
|
context "when the protocol is not accepted" do
|
||||||
let(:protocol) { "sigma" }
|
let(:protocol) { "sigma" }
|
||||||
|
|
|
@ -275,30 +275,6 @@ RSpec.describe EmailSettingsValidator do
|
||||||
}.to raise_error(ArgumentError)
|
}.to raise_error(ArgumentError)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "corrects tls settings for gmail based on port 587" do
|
|
||||||
net_smtp_stub.expects(:enable_starttls_auto).once
|
|
||||||
net_smtp_stub.expects(:enable_tls).never
|
|
||||||
described_class.validate_smtp(
|
|
||||||
host: host,
|
|
||||||
port: 587,
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
domain: domain,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "corrects tls settings for gmail based on port 465" do
|
|
||||||
net_smtp_stub.expects(:enable_starttls_auto).never
|
|
||||||
net_smtp_stub.expects(:enable_tls).once
|
|
||||||
described_class.validate_smtp(
|
|
||||||
host: host,
|
|
||||||
port: 465,
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
domain: domain,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "corrects authentication method to login for office365" do
|
it "corrects authentication method to login for office365" do
|
||||||
net_smtp_stub.expects(:start).with("office365.com", username, password, :login)
|
net_smtp_stub.expects(:start).with("office365.com", username, password, :login)
|
||||||
described_class.validate_smtp(
|
described_class.validate_smtp(
|
||||||
|
|
|
@ -2408,7 +2408,7 @@ RSpec.describe PostAlerter do
|
||||||
:group,
|
:group,
|
||||||
smtp_server: "smtp.gmail.com",
|
smtp_server: "smtp.gmail.com",
|
||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
smtp_ssl: true,
|
smtp_ssl_mode: Group.smtp_ssl_modes[:starttls],
|
||||||
imap_server: "imap.gmail.com",
|
imap_server: "imap.gmail.com",
|
||||||
imap_port: 993,
|
imap_port: 993,
|
||||||
imap_ssl: true,
|
imap_ssl: true,
|
||||||
|
|
Loading…
Reference in New Issue