Add openssl verify mode and email encryption for smtp configuration (#3885)
* Add openssl verify mode and email encryption for smtp configuration * Add spec for code coverage
This commit is contained in:
parent
4ae9ed8f94
commit
4e416b4d51
11 changed files with 280 additions and 30 deletions
|
@ -26,8 +26,48 @@ module Api::V1::InboxesHelper
|
||||||
def validate_smtp(channel_data)
|
def validate_smtp(channel_data)
|
||||||
return unless channel_data.key?('smtp_enabled') && channel_data[:smtp_enabled]
|
return unless channel_data.key?('smtp_enabled') && channel_data[:smtp_enabled]
|
||||||
|
|
||||||
smtp = Net::SMTP.start(channel_data[:smtp_address], channel_data[:smtp_port], channel_data[:smtp_domain], channel_data[:smtp_email],
|
smtp = Net::SMTP.new(channel_data[:smtp_address], channel_data[:smtp_port])
|
||||||
channel_data[:smtp_password], :login)
|
|
||||||
|
set_smtp_encryption(channel_data, smtp)
|
||||||
|
|
||||||
|
smtp.start(channel_data[:smtp_domain], channel_data[:smtp_email], channel_data[:smtp_password], :login)
|
||||||
smtp.finish unless smtp&.nil?
|
smtp.finish unless smtp&.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_smtp_encryption(channel_data, smtp)
|
||||||
|
if channel_data[:smtp_enable_ssl_tls]
|
||||||
|
set_enable_tls(channel_data, smtp)
|
||||||
|
elsif channel_data[:smtp_enable_starttls_auto]
|
||||||
|
set_enable_starttls_auto(channel_data, smtp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_enable_starttls_auto(channel_data, smtp)
|
||||||
|
return unless smtp.respond_to?(:enable_starttls_auto)
|
||||||
|
|
||||||
|
if channel_data[:smtp_openssl_verify_mode]
|
||||||
|
context = enable_openssl_mode(channel_data[:smtp_openssl_verify_mode])
|
||||||
|
smtp.enable_starttls_auto(context)
|
||||||
|
else
|
||||||
|
smtp.enable_starttls_auto
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_enable_tls(channel_data, smtp)
|
||||||
|
return unless smtp.respond_to?(:enable_tls)
|
||||||
|
|
||||||
|
if channel_data[:smtp_openssl_verify_mode]
|
||||||
|
context = enable_openssl_mode(channel_data[:smtp_openssl_verify_mode])
|
||||||
|
smtp.enable_tls(context)
|
||||||
|
else
|
||||||
|
smtp.enable_tls
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_openssl_mode(smtp_openssl_verify_mode)
|
||||||
|
openssl_verify_mode = "OpenSSL::SSL::VERIFY_#{smtp_openssl_verify_mode.upcase}".constantize if smtp_openssl_verify_mode.is_a?(String)
|
||||||
|
context = Net::SMTP.default_ssl_context
|
||||||
|
context.verify_mode = openssl_verify_mode
|
||||||
|
context
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -522,7 +522,11 @@
|
||||||
"DOMAIN": {
|
"DOMAIN": {
|
||||||
"LABEL": "Domain",
|
"LABEL": "Domain",
|
||||||
"PLACE_HOLDER": "Domain"
|
"PLACE_HOLDER": "Domain"
|
||||||
}
|
},
|
||||||
|
"ENCRYPTION": "Encryption",
|
||||||
|
"SSL_TLS": "SSL/TLS",
|
||||||
|
"START_TLS": "STARTTLS",
|
||||||
|
"OPEN_SSL_VERIFY_MODE": "Open SSL Verify Mode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,18 @@
|
||||||
:placeholder="$t('INBOX_MGMT.SMTP.DOMAIN.PLACE_HOLDER')"
|
:placeholder="$t('INBOX_MGMT.SMTP.DOMAIN.PLACE_HOLDER')"
|
||||||
@blur="$v.domain.$touch"
|
@blur="$v.domain.$touch"
|
||||||
/>
|
/>
|
||||||
|
<input-radio-group
|
||||||
|
:label="$t('INBOX_MGMT.SMTP.ENCRYPTION')"
|
||||||
|
:items="encryptionProtocols"
|
||||||
|
:action="handleEncryptionChange"
|
||||||
|
/>
|
||||||
|
<single-select-dropdown
|
||||||
|
class="medium-9 columns"
|
||||||
|
:label="$t('INBOX_MGMT.SMTP.OPEN_SSL_VERIFY_MODE')"
|
||||||
|
:selected="openSSLVerifyMode"
|
||||||
|
:options="openSSLVerifyModes"
|
||||||
|
:action="handleSSLModeChange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:button-text="$t('INBOX_MGMT.SMTP.UPDATE')"
|
:button-text="$t('INBOX_MGMT.SMTP.UPDATE')"
|
||||||
|
@ -73,10 +85,14 @@ import { mapGetters } from 'vuex';
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
import SettingsSection from 'dashboard/components/SettingsSection';
|
import SettingsSection from 'dashboard/components/SettingsSection';
|
||||||
import { required, minLength, email } from 'vuelidate/lib/validators';
|
import { required, minLength, email } from 'vuelidate/lib/validators';
|
||||||
|
import InputRadioGroup from './components/InputRadioGroup';
|
||||||
|
import SingleSelectDropdown from './components/SingleSelectDropdown';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SettingsSection,
|
SettingsSection,
|
||||||
|
InputRadioGroup,
|
||||||
|
SingleSelectDropdown,
|
||||||
},
|
},
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
|
@ -93,6 +109,19 @@ export default {
|
||||||
email: '',
|
email: '',
|
||||||
password: '',
|
password: '',
|
||||||
domain: '',
|
domain: '',
|
||||||
|
ssl: false,
|
||||||
|
starttls: true,
|
||||||
|
openSSLVerifyMode: 'none',
|
||||||
|
encryptionProtocols: [
|
||||||
|
{ id: 'ssl', title: 'SSL/TLS', checked: false },
|
||||||
|
{ id: 'starttls', title: 'STARTTLS', checked: true },
|
||||||
|
],
|
||||||
|
openSSLVerifyModes: [
|
||||||
|
{ key: 1, value: 'none' },
|
||||||
|
{ key: 2, value: 'peer' },
|
||||||
|
{ key: 3, value: 'client_once' },
|
||||||
|
{ key: 4, value: 'fail_if_no_peer_cert' },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
validations: {
|
validations: {
|
||||||
|
@ -125,6 +154,9 @@ export default {
|
||||||
smtp_email,
|
smtp_email,
|
||||||
smtp_password,
|
smtp_password,
|
||||||
smtp_domain,
|
smtp_domain,
|
||||||
|
smtp_enable_starttls_auto,
|
||||||
|
smtp_enable_ssl_tls,
|
||||||
|
smtp_openssl_verify_mode,
|
||||||
} = this.inbox;
|
} = this.inbox;
|
||||||
this.isSMTPEnabled = smtp_enabled;
|
this.isSMTPEnabled = smtp_enabled;
|
||||||
this.address = smtp_address;
|
this.address = smtp_address;
|
||||||
|
@ -132,6 +164,30 @@ export default {
|
||||||
this.email = smtp_email;
|
this.email = smtp_email;
|
||||||
this.password = smtp_password;
|
this.password = smtp_password;
|
||||||
this.domain = smtp_domain;
|
this.domain = smtp_domain;
|
||||||
|
this.starttls = smtp_enable_starttls_auto;
|
||||||
|
this.ssl = smtp_enable_ssl_tls;
|
||||||
|
this.openSSLVerifyMode = smtp_openssl_verify_mode;
|
||||||
|
|
||||||
|
this.encryptionProtocols = [
|
||||||
|
{ id: 'ssl', title: 'SSL/TLS', checked: smtp_enable_ssl_tls },
|
||||||
|
{
|
||||||
|
id: 'starttls',
|
||||||
|
title: 'STARTTLS',
|
||||||
|
checked: smtp_enable_starttls_auto,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
handleEncryptionChange(encryption) {
|
||||||
|
if (encryption.id === 'ssl') {
|
||||||
|
this.ssl = true;
|
||||||
|
this.starttls = false;
|
||||||
|
} else {
|
||||||
|
this.ssl = false;
|
||||||
|
this.starttls = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSSLModeChange(mode) {
|
||||||
|
this.openSSLVerifyMode = mode;
|
||||||
},
|
},
|
||||||
async updateInbox() {
|
async updateInbox() {
|
||||||
try {
|
try {
|
||||||
|
@ -145,6 +201,9 @@ export default {
|
||||||
smtp_email: this.email,
|
smtp_email: this.email,
|
||||||
smtp_password: this.password,
|
smtp_password: this.password,
|
||||||
smtp_domain: this.domain,
|
smtp_domain: this.domain,
|
||||||
|
smtp_enable_ssl_tls: this.ssl,
|
||||||
|
smtp_enable_starttls_auto: this.starttls,
|
||||||
|
smtp_openssl_verify_mode: this.openSSLVerifyMode,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
await this.$store.dispatch('inboxes/updateInboxSMTP', payload);
|
await this.$store.dispatch('inboxes/updateInboxSMTP', payload);
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<label class="radio-group-label">{{ label }}</label>
|
||||||
|
<div class="radio-group">
|
||||||
|
<div v-for="item in items" :key="item.id">
|
||||||
|
<input
|
||||||
|
name="radio-input"
|
||||||
|
type="radio"
|
||||||
|
:checked="item.checked"
|
||||||
|
@change="action(item)"
|
||||||
|
/>
|
||||||
|
<label>{{ item.title }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.radio-group-label {
|
||||||
|
margin-bottom: var(--space-small);
|
||||||
|
}
|
||||||
|
.radio-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<label for="dropdown-select">
|
||||||
|
{{ label }}
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="dropdown-select"
|
||||||
|
v-model="value"
|
||||||
|
name="dropdown-select"
|
||||||
|
@change="action(value)"
|
||||||
|
>
|
||||||
|
<option v-for="option in options" :key="option.key">
|
||||||
|
{{ option.value }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: this.selected,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -29,7 +29,9 @@ module ConversationReplyMailerHelper
|
||||||
user_name: @channel.smtp_email,
|
user_name: @channel.smtp_email,
|
||||||
password: @channel.smtp_password,
|
password: @channel.smtp_password,
|
||||||
domain: @channel.smtp_domain,
|
domain: @channel.smtp_domain,
|
||||||
|
tls: @channel.smtp_enable_ssl_tls,
|
||||||
enable_starttls_auto: @channel.smtp_enable_starttls_auto,
|
enable_starttls_auto: @channel.smtp_enable_starttls_auto,
|
||||||
|
openssl_verify_mode: @channel.smtp_openssl_verify_mode,
|
||||||
authentication: @channel.smtp_authentication
|
authentication: @channel.smtp_authentication
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
# smtp_authentication :string default("login")
|
# smtp_authentication :string default("login")
|
||||||
# smtp_domain :string default("")
|
# smtp_domain :string default("")
|
||||||
# smtp_email :string default("")
|
# smtp_email :string default("")
|
||||||
|
# smtp_enable_ssl_tls :boolean default(FALSE)
|
||||||
# smtp_enable_starttls_auto :boolean default(TRUE)
|
# smtp_enable_starttls_auto :boolean default(TRUE)
|
||||||
# smtp_enabled :boolean default(FALSE)
|
# smtp_enabled :boolean default(FALSE)
|
||||||
|
# smtp_openssl_verify_mode :string default("none")
|
||||||
# smtp_password :string default("")
|
# smtp_password :string default("")
|
||||||
# smtp_port :integer default(0)
|
# smtp_port :integer default(0)
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
|
@ -35,7 +37,8 @@ class Channel::Email < ApplicationRecord
|
||||||
|
|
||||||
self.table_name = 'channel_email'
|
self.table_name = 'channel_email'
|
||||||
EDITABLE_ATTRS = [:email, :imap_enabled, :imap_email, :imap_password, :imap_address, :imap_port, :imap_enable_ssl, :imap_inbox_synced_at,
|
EDITABLE_ATTRS = [:email, :imap_enabled, :imap_email, :imap_password, :imap_address, :imap_port, :imap_enable_ssl, :imap_inbox_synced_at,
|
||||||
:smtp_enabled, :smtp_email, :smtp_password, :smtp_address, :smtp_port, :smtp_domain].freeze
|
:smtp_enabled, :smtp_email, :smtp_password, :smtp_address, :smtp_port, :smtp_domain, :smtp_enable_starttls_auto,
|
||||||
|
:smtp_enable_ssl_tls, :smtp_openssl_verify_mode].freeze
|
||||||
|
|
||||||
validates :email, uniqueness: true
|
validates :email, uniqueness: true
|
||||||
validates :forward_to_email, uniqueness: true
|
validates :forward_to_email, uniqueness: true
|
||||||
|
|
|
@ -67,6 +67,9 @@ if resource.email?
|
||||||
json.smtp_port resource.channel.try(:smtp_port)
|
json.smtp_port resource.channel.try(:smtp_port)
|
||||||
json.smtp_enabled resource.channel.try(:smtp_enabled)
|
json.smtp_enabled resource.channel.try(:smtp_enabled)
|
||||||
json.smtp_domain resource.channel.try(:smtp_domain)
|
json.smtp_domain resource.channel.try(:smtp_domain)
|
||||||
|
json.smtp_enable_ssl_tls resource.channel.try(:smtp_enable_ssl_tls)
|
||||||
|
json.smtp_enable_starttls_auto resource.channel.try(:smtp_enable_starttls_auto)
|
||||||
|
json.smtp_openssl_verify_mode resource.channel.try(:smtp_openssl_verify_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
## API Channel Attributes
|
## API Channel Attributes
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
class AddOpenSslVerifyModeToChannelEmail < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
change_table :channel_email, bulk: true do |t|
|
||||||
|
t.string :smtp_openssl_verify_mode, default: 'none'
|
||||||
|
t.boolean :smtp_enable_ssl_tls, default: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -202,6 +202,8 @@ ActiveRecord::Schema.define(version: 2022_01_31_081750) do
|
||||||
t.string "smtp_domain", default: ""
|
t.string "smtp_domain", default: ""
|
||||||
t.boolean "smtp_enable_starttls_auto", default: true
|
t.boolean "smtp_enable_starttls_auto", default: true
|
||||||
t.string "smtp_authentication", default: "login"
|
t.string "smtp_authentication", default: "login"
|
||||||
|
t.string "smtp_openssl_verify_mode", default: "none"
|
||||||
|
t.boolean "smtp_enable_ssl_tls", default: false
|
||||||
t.index ["email"], name: "index_channel_email_on_email", unique: true
|
t.index ["email"], name: "index_channel_email_on_email", unique: true
|
||||||
t.index ["forward_to_email"], name: "index_channel_email_on_forward_to_email", unique: true
|
t.index ["forward_to_email"], name: "index_channel_email_on_forward_to_email", unique: true
|
||||||
end
|
end
|
||||||
|
|
|
@ -437,32 +437,6 @@ RSpec.describe 'Inboxes API', type: :request do
|
||||||
expect(email_channel.reload.imap_port).to eq(993)
|
expect(email_channel.reload.imap_port).to eq(993)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates email inbox with smtp when administrator' do
|
|
||||||
email_channel = create(:channel_email, account: account)
|
|
||||||
email_inbox = create(:inbox, channel: email_channel, account: account)
|
|
||||||
|
|
||||||
smtp_connection = double
|
|
||||||
allow(smtp_connection).to receive(:finish).and_return(true)
|
|
||||||
allow(Net::SMTP).to receive(:start).and_return(smtp_connection)
|
|
||||||
|
|
||||||
patch "/api/v1/accounts/#{account.id}/inboxes/#{email_inbox.id}",
|
|
||||||
headers: admin.create_new_auth_token,
|
|
||||||
params: {
|
|
||||||
channel: {
|
|
||||||
smtp_enabled: true,
|
|
||||||
smtp_address: 'smtp.gmail.com',
|
|
||||||
smtp_port: 587,
|
|
||||||
smtp_email: 'smtptest@gmail.com'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
as: :json
|
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
|
||||||
expect(email_channel.reload.smtp_enabled).to be true
|
|
||||||
expect(email_channel.reload.smtp_address).to eq('smtp.gmail.com')
|
|
||||||
expect(email_channel.reload.smtp_port).to eq(587)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'updates avatar when administrator' do
|
it 'updates avatar when administrator' do
|
||||||
# no avatar before upload
|
# no avatar before upload
|
||||||
expect(inbox.avatar.attached?).to eq(false)
|
expect(inbox.avatar.attached?).to eq(false)
|
||||||
|
@ -501,6 +475,72 @@ RSpec.describe 'Inboxes API', type: :request do
|
||||||
expect(inbox.reload.allow_messages_after_resolved).to be_falsey
|
expect(inbox.reload.allow_messages_after_resolved).to be_falsey
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when an authenticated user updates email inbox' do
|
||||||
|
let(:admin) { create(:user, account: account, role: :administrator) }
|
||||||
|
let(:email_channel) { create(:channel_email, account: account) }
|
||||||
|
let(:email_inbox) { create(:inbox, channel: email_channel, account: account) }
|
||||||
|
|
||||||
|
it 'updates smtp configuration with starttls encryption' do
|
||||||
|
smtp_connection = double
|
||||||
|
allow(smtp_connection).to receive(:start).and_return(true)
|
||||||
|
allow(smtp_connection).to receive(:finish).and_return(true)
|
||||||
|
allow(smtp_connection).to receive(:respond_to?).and_return(true)
|
||||||
|
allow(smtp_connection).to receive(:enable_starttls_auto).and_return(true)
|
||||||
|
allow(Net::SMTP).to receive(:new).and_return(smtp_connection)
|
||||||
|
|
||||||
|
patch "/api/v1/accounts/#{account.id}/inboxes/#{email_inbox.id}",
|
||||||
|
headers: admin.create_new_auth_token,
|
||||||
|
params: {
|
||||||
|
channel: {
|
||||||
|
smtp_enabled: true,
|
||||||
|
smtp_address: 'smtp.gmail.com',
|
||||||
|
smtp_port: 587,
|
||||||
|
smtp_email: 'smtptest@gmail.com',
|
||||||
|
smtp_enable_starttls_auto: true,
|
||||||
|
smtp_openssl_verify_mode: 'peer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(email_channel.reload.smtp_enabled).to be true
|
||||||
|
expect(email_channel.reload.smtp_address).to eq('smtp.gmail.com')
|
||||||
|
expect(email_channel.reload.smtp_port).to eq(587)
|
||||||
|
expect(email_channel.reload.smtp_enable_starttls_auto).to be true
|
||||||
|
expect(email_channel.reload.smtp_openssl_verify_mode).to eq('peer')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates smtp configuration with ssl/tls encryption' do
|
||||||
|
smtp_connection = double
|
||||||
|
allow(smtp_connection).to receive(:start).and_return(true)
|
||||||
|
allow(smtp_connection).to receive(:finish).and_return(true)
|
||||||
|
allow(smtp_connection).to receive(:respond_to?).and_return(true)
|
||||||
|
allow(smtp_connection).to receive(:enable_tls).and_return(true)
|
||||||
|
allow(Net::SMTP).to receive(:new).and_return(smtp_connection)
|
||||||
|
|
||||||
|
patch "/api/v1/accounts/#{account.id}/inboxes/#{email_inbox.id}",
|
||||||
|
headers: admin.create_new_auth_token,
|
||||||
|
params: {
|
||||||
|
channel: {
|
||||||
|
smtp_enabled: true,
|
||||||
|
smtp_address: 'smtp.gmail.com',
|
||||||
|
smtp_email: 'smtptest@gmail.com',
|
||||||
|
smtp_port: 587,
|
||||||
|
smtp_enable_ssl_tls: true,
|
||||||
|
smtp_openssl_verify_mode: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(email_channel.reload.smtp_enabled).to be true
|
||||||
|
expect(email_channel.reload.smtp_address).to eq('smtp.gmail.com')
|
||||||
|
expect(email_channel.reload.smtp_port).to eq(587)
|
||||||
|
expect(email_channel.reload.smtp_enable_ssl_tls).to be true
|
||||||
|
expect(email_channel.reload.smtp_openssl_verify_mode).to eq('none')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/agent_bot' do
|
describe 'GET /api/v1/accounts/{account.id}/inboxes/{inbox.id}/agent_bot' do
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue