Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions framework/core/js/src/admin/components/MailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,24 +138,64 @@ export default class MailPage<CustomAttrs extends IPageAttrs = IPageAttrs> exten
);

if (!!fieldKeys.length) {
const driver = this.setting('mail_driver')();
const descriptionKey = `core.admin.email.${driver}_description`;
const descriptionText = app.translator.trans(descriptionKey);

items.add(
'mail_driver_settings',
<FieldSet
label={app.translator.trans(`core.admin.email.${this.setting('mail_driver')()}_heading`)}
label={app.translator.trans(`core.admin.email.${driver}_heading`)}
className="MailPage-MailSettings FieldSet--form"
description={descriptionText}
>
{fieldKeys.map((field) => {
const fieldInfo = fields[field];

// For encryption field, show all help text options above the dropdown
let helpText;
if (field === 'mail_encryption') {
const tlsHelp = app.translator.trans('core.admin.email.mail_encryption_tls_help');
const sslHelp = app.translator.trans('core.admin.email.mail_encryption_ssl_help');
const noneHelp = app.translator.trans('core.admin.email.mail_encryption_none_help');

helpText = (
<>
<div>
<strong>TLS:</strong> {tlsHelp}
</div>
<div>
<strong>SSL:</strong> {sslHelp}
</div>
<div>
<strong>None:</strong> {noneHelp}
</div>
</>
);
} else {
const helpKey = `core.admin.email.${field}_help`;
const translatedHelp = app.translator.trans(helpKey);
helpText = translatedHelp !== helpKey ? translatedHelp : undefined;
}

return (
<>
{this.buildSettingComponent({
type: typeof fieldInfo === 'string' ? 'text' : 'select',
label: app.translator.trans(`core.admin.email.${field}_label`),
setting: field,
options: fieldInfo,
help: helpText,
})}
{this.status!.errors[field] && <p className="ValidationError">{this.status!.errors[field]}</p>}
{this.status!.errors[field] && (
<div className="ValidationError">
{Array.isArray(this.status!.errors[field]) ? (
this.status!.errors[field].map((error: string) => <p key={error}>{error}</p>)
) : (
<p>{this.status!.errors[field]}</p>
)}
</div>
)}
</>
);
})}
Expand Down
2 changes: 1 addition & 1 deletion framework/core/js/src/common/components/FormGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export default class FormGroup<CustomAttrs extends IFormGroupAttrs = IFormGroupA
const Tag = multiple ? MultiSelect : Select;

settingElement = (
<Tag id={inputId} aria-describedby={helpTextId} value={value || defaultValue} options={options} onchange={stream} {...otherAttrs} />
<Tag id={inputId} aria-describedby={helpTextId} value={value ?? defaultValue} options={options} onchange={stream} {...otherAttrs} />
);
} else if ((RadioSettingTypes as readonly string[]).includes(type)) {
const { default: defaultValue, options, multiple, ...otherAttrs } = attrs;
Expand Down
4 changes: 4 additions & 0 deletions framework/core/locale/core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ core:
format_help: "Choose the format that outgoing emails will be sent in. The recommended option is <code>multipart</code>, as this will allow your user's email client to display the most appropriate format."
from_label: Sender
mail_encryption_label: Encryption
mail_encryption_tls_help: "Connection starts unencrypted and upgrades to TLS (STARTTLS). Typically used with port 587 or 25."
mail_encryption_ssl_help: "Connection is encrypted from the start (Implicit TLS). Typically used with port 465."
mail_encryption_none_help: "No encryption. Not recommended for production use."
mail_host_label: Host
mail_mailgun_domain_label: Domain
mail_mailgun_region_label: Region
Expand All @@ -243,6 +246,7 @@ core:
send_test_mail_success: "Test mail sent successfully!"
send_test_mail_text: "This will send an email using the above configuration to your email, {email}."
smtp_heading: SMTP Settings
smtp_description: "Configure SMTP connection settings. Common configurations: Port 587 with TLS, or Port 465 with SSL."
title: => core.ref.email

# These translations are used on default extension pages.
Expand Down
14 changes: 12 additions & 2 deletions framework/core/src/Mail/SmtpDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public function availableSettings(): array
return [
'mail_host' => '', // a hostname, IPv4 address or IPv6 wrapped in []
'mail_port' => '', // a number, defaults to 25
'mail_encryption' => '', // "tls" or "ssl"
'mail_encryption' => [ // Dropdown options for encryption
'' => 'None',
'tls' => 'TLS',
'ssl' => 'SSL',
],
'mail_username' => '',
'mail_password' => '',
];
Expand All @@ -54,8 +58,14 @@ public function canSend(): bool

public function buildTransport(SettingsRepositoryInterface $settings): TransportInterface
{
$encryption = strtolower((string) $settings->get('mail_encryption'));

// 'ssl' means implicit TLS/SSL (smtps://), typically used with port 465
// 'tls' or empty means STARTTLS (smtp://), typically used with port 587 or 25
$scheme = ($encryption === 'ssl') ? 'smtps' : 'smtp';

return $this->factory->create(new Dsn(
$settings->get('mail_encryption') === 'tls' ? 'smtps' : 'smtp',
$scheme,
$settings->get('mail_host'),
$settings->get('mail_username'),
$settings->get('mail_password'),
Expand Down
6 changes: 5 additions & 1 deletion framework/core/tests/integration/extenders/MailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ public function drivers_are_unchanged_by_default()
$this->assertEquals([
'mail_host' => '',
'mail_port' => '',
'mail_encryption' => '',
'mail_encryption' => [
'' => 'None',
'tls' => 'TLS',
'ssl' => 'SSL',
],
'mail_username' => '',
'mail_password' => '',
], $fields['smtp']);
Expand Down
Loading