mirror of
https://github.com/strapi/strapi.git
synced 2025-09-01 04:42:58 +00:00
Merge branch 'develop'
This commit is contained in:
commit
1ab5afc33d
@ -168,20 +168,18 @@ module.exports = ({ env }) => ({
|
||||
|
||||
**Available options**
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ----------- |
|
||||
| `host` | Host name | string | `localhost` |
|
||||
| `port` | Port on which the server should be running. | integer | `1337` |
|
||||
| `emitErrors` | Enable errors to be emitted to `koa` when they happen in order to attach custom logic or use error reporting services. | boolean | |
|
||||
| `url` | Url of the server. Enable proxy support such as Apache or Nginx, example: `https://mywebsite.com/api`. Default value: `http://${host}:${port}`. | string | |
|
||||
| `cron` | Cron configuration (powered by [`node-schedule`](https://github.com/node-schedule/node-schedule)) | Object | |
|
||||
| `cron.enabled` | Enable or disable CRON tasks to schedule jobs at specific dates. | boolean | `false` |
|
||||
| `admin` | Admin panel configuration | Object | |
|
||||
| `admin.url` | Url of your admin panel. Default value: `/admin`. Note: If the url is relative, it will be concatenated with `url`. | string | `/admin` |
|
||||
| `admin.autoOpen` | Enable or disabled administration opening on start. | boolean | `true` |
|
||||
| `admin.watchIgnoreFiles` | Add custom files that should not be watched during development. See more [here](https://github.com/paulmillr/chokidar#path-filtering) (property `ignored`). | Array(string) | `[]`. |
|
||||
| `admin.build` | Admin panel build configuration | Object | |
|
||||
| `admin.build.backend` | URL that the admin panel and plugins will request | string | |
|
||||
| Property | Description | Type | Default |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | ----------- |
|
||||
| `host` | Host name | string | `localhost` |
|
||||
| `port` | Port on which the server should be running. | integer | `1337` |
|
||||
| `emitErrors` | Enable errors to be emitted to `koa` when they happen in order to attach custom logic or use error reporting services. | boolean | `false |
|
||||
| `url` | Url of the server. Enable proxy support such as Apache or Nginx, example: `https://mywebsite.com/api`. The url can be relative, if so, it is used with `http://${host}:${port}` as the base url. | string | `''` |
|
||||
| `cron` | Cron configuration (powered by [`node-schedule`](https://github.com/node-schedule/node-schedule)) | Object | |
|
||||
| `cron.enabled` | Enable or disable CRON tasks to schedule jobs at specific dates. | boolean | `false` |
|
||||
| `admin` | Admin panel configuration | Object | |
|
||||
| `admin.url` | Url of your admin panel. Default value: `/admin`. Note: If the url is relative, it will be concatenated with `url`. | string | `/admin` |
|
||||
| `admin.autoOpen` | Enable or disabled administration opening on start. | boolean | `true` |
|
||||
| `admin.watchIgnoreFiles` | Add custom files that should not be watched during development. See more [here](https://github.com/paulmillr/chokidar#path-filtering) (property `ignored`). | Array(string) | `[]`. |
|
||||
|
||||
## Functions
|
||||
|
||||
|
@ -12,7 +12,7 @@ Update your package.json accordingly:
|
||||
|
||||
```json
|
||||
{
|
||||
//...
|
||||
// ...
|
||||
"dependencies": {
|
||||
"strapi": "3.0.0-beta.20",
|
||||
"strapi-admin": "3.0.0-beta.20",
|
||||
|
@ -11,7 +11,9 @@ By using the following function, strapi will use the configured provider to send
|
||||
await strapi.plugins['email'].services.email.send({
|
||||
to: 'paulbocuse@strapi.io',
|
||||
from: 'joelrobuchon@strapi.io',
|
||||
replyTo: 'no-reply@strapi.io',
|
||||
cc: 'helenedarroze@strapi.io',
|
||||
bcc: 'ghislainearabian@strapi.io',
|
||||
replyTo: 'annesophiepic@strapi.io',
|
||||
subject: 'Use strapi email provider successfully',
|
||||
text: 'Hello world!',
|
||||
html: 'Hello world!',
|
||||
@ -20,15 +22,9 @@ await strapi.plugins['email'].services.email.send({
|
||||
|
||||
## Configure the plugin
|
||||
|
||||
The plugin provides you a settings page where you can define the email provider you want to use.
|
||||
You will also be able to add some configuration.
|
||||
### Install the provider you want
|
||||
|
||||
- Click on **Plugins** in the left menu
|
||||
- Click on the cog button on the **Email** plugin line
|
||||
|
||||
## Install new providers
|
||||
|
||||
By default Strapi provides a local email system. You might want to send email with a third party.
|
||||
By default Strapi provides a local email system ([sendmail](https://www.npmjs.com/package/sendmail)). If you want to use a third party to send emails, you need to install the correct provider module. Otherwise you can skip this part and continue to [Configure your provider](#configure-your-provider).
|
||||
|
||||
You can check all the available providers developed by the community on npmjs.org - [Providers list](https://www.npmjs.com/search?q=strapi-provider-email-)
|
||||
|
||||
@ -54,29 +50,44 @@ npm install strapi-provider-email-sendgrid@beta --save
|
||||
|
||||
::::
|
||||
|
||||
::: tip
|
||||
If the provider is not in the mono repo, you probably don't need `@beta` depending if the creator published it with this tag or not.
|
||||
:::
|
||||
### Configure your provider
|
||||
|
||||
Then, visit [http://localhost:1337/admin/plugins/email/configurations/development](http://localhost:1337/admin/plugins/email/configurations/development) on your web browser and configure the provider.
|
||||
After installing your provider you will need to add some settings in `config/plugins.js`. Check the README of each provider to know what configuration settings the provider needs.
|
||||
|
||||
Here is an example of a configuration made for the provider [strapi-provider-email-sendgrid](https://www.npmjs.com/package/strapi-provider-email-sendgrid).
|
||||
|
||||
**Path —** `./config/plugins.js`.
|
||||
|
||||
```js
|
||||
module.exports = ({ env }) => ({
|
||||
// ...
|
||||
email: {
|
||||
provider: 'sendgrid',
|
||||
providerOptions: {
|
||||
apiKey: env('SENDGRID_API_KEY'),
|
||||
},
|
||||
settings: {
|
||||
defaultFrom: 'juliasedefdjian@strapi.io',
|
||||
defaultReplyTo: 'juliasedefdjian@strapi.io',
|
||||
},
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
::: tip
|
||||
If you're using a different provider depending on your environment, you can specify the correct configuration in `config/env/${yourEnvironment}/plugins.js`. More info here: [Environments](../concepts/configurations#environments)
|
||||
:::
|
||||
|
||||
## Create new provider
|
||||
|
||||
If you want to create your own, make sure the name starts with `strapi-provider-email-` (duplicating an existing one will be easier), modify the `auth` config object and customize the `send` function.
|
||||
If you want to create your own, make sure the name starts with `strapi-provider-email-` (duplicating an existing one will be easier) and customize the `send` function.
|
||||
|
||||
Default template
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
provider: 'provider-id',
|
||||
name: 'display name',
|
||||
auth: {
|
||||
config_1: {
|
||||
label: 'My Config 1',
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
init: config => {
|
||||
init: (providerOptions = {}, settings = {}) => {
|
||||
return {
|
||||
send: async options => {},
|
||||
};
|
||||
@ -86,7 +97,8 @@ module.exports = {
|
||||
|
||||
In the `send` function you will have access to:
|
||||
|
||||
- `config` that contains configurations you setup in your admin panel
|
||||
- `providerOptions` that contains configurations written in `plugins.js`
|
||||
- `settings` that contains configurations written in `plugins.js`
|
||||
- `options` that contains options you send when you call the `send` function from the email plugin service
|
||||
|
||||
To use it you will have to publish it on **npm**.
|
||||
@ -147,6 +159,6 @@ Error: SMTP code:550 msg:550-5.7.1 [87.88.179.13] The IP you're using to send ma
|
||||
550 5.7.1 https://support.google.com/mail/?p=NotAuthorizedError 30si2132728pjz.75 - gsmtp
|
||||
```
|
||||
|
||||
To fix it, I suggest you to use another email provider that uses third party to send emails.
|
||||
To fix it, we suggest you to use another email provider that uses third party to send emails.
|
||||
|
||||
When using a third party provider, you avoid having to setup a mail server on your server and get extra features such as email analytics.
|
||||
|
1
examples/getstarted/.gitignore
vendored
1
examples/getstarted/.gitignore
vendored
@ -82,6 +82,7 @@ ssl
|
||||
nbproject
|
||||
public/uploads/*
|
||||
!public/uploads/.gitkeep
|
||||
.env
|
||||
|
||||
############################
|
||||
# Node.js
|
||||
|
@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
module.exports = ({ env }) => ({
|
||||
graphql: {
|
||||
amountLimit: 5,
|
||||
depthLimit: 10,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -11,8 +11,6 @@ import { Button, PopUpWarning } from 'strapi-helper-plugin';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
const PLUGINS_WITH_CONFIG = ['email'];
|
||||
|
||||
/* eslint-disable react/no-unused-state */
|
||||
class PluginCard extends React.Component {
|
||||
state = {
|
||||
@ -92,13 +90,7 @@ class PluginCard extends React.Component {
|
||||
? 'app.components.PluginCard.Button.label.install'
|
||||
: 'app.components.PluginCard.Button.label.download';
|
||||
|
||||
// Display settings link for a selection of plugins.
|
||||
const settingsComponent = PLUGINS_WITH_CONFIG.includes(this.props.plugin.id) && (
|
||||
<div className="settings" onClick={this.handleClickSettings}>
|
||||
<FontAwesomeIcon icon="cog" />
|
||||
<FormattedMessage id="app.components.PluginCard.settings" />
|
||||
</div>
|
||||
);
|
||||
const settingsComponent = null;
|
||||
|
||||
const descriptions = {
|
||||
short:
|
||||
|
@ -3,31 +3,17 @@ import PropTypes from 'prop-types';
|
||||
import { IconLinks } from '@buffetjs/core';
|
||||
import { useGlobalContext, PopUpWarning } from 'strapi-helper-plugin';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { faTrashAlt, faCog } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import Text from '../../components/Text';
|
||||
import CustomRow from './CustomRow';
|
||||
import LogoContainer from './Logo';
|
||||
|
||||
const PLUGINS_WITH_CONFIG = ['email'];
|
||||
|
||||
const Row = ({ logo, name, description, isRequired, id, icon, onConfirm }) => {
|
||||
const { currentEnvironment, formatMessage } = useGlobalContext();
|
||||
const { formatMessage } = useGlobalContext();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { push } = useHistory();
|
||||
const links = [];
|
||||
|
||||
if (PLUGINS_WITH_CONFIG.includes(id)) {
|
||||
links.push({
|
||||
icon: <FontAwesomeIcon icon={faCog} />,
|
||||
onClick: () => {
|
||||
const settingsPath = `/plugins/${id}/configurations/${currentEnvironment}`;
|
||||
|
||||
push(settingsPath);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const handleClickConfirm = () => {
|
||||
handleToggle();
|
||||
onConfirm(id);
|
||||
|
@ -316,11 +316,6 @@ module.exports = {
|
||||
const resetPasswordToken = crypto.randomBytes(64).toString('hex');
|
||||
|
||||
const settings = {
|
||||
from: {
|
||||
name: 'Administration Panel',
|
||||
email: 'no-reply@strapi.io',
|
||||
},
|
||||
response_email: '',
|
||||
object: 'Reset password',
|
||||
message: `<p>We heard that you lost your password. Sorry about that!</p>
|
||||
|
||||
@ -335,12 +330,7 @@ module.exports = {
|
||||
// Send an email to the admin.
|
||||
await strapi.plugins['email'].services.email.send({
|
||||
to: admin.email,
|
||||
from:
|
||||
settings.from.email || settings.from.name
|
||||
? `${settings.from.name} <${settings.from.email}>`
|
||||
: undefined,
|
||||
replyTo: settings.response_email,
|
||||
subject: settings.object,
|
||||
subject: 'Reset password',
|
||||
text: settings.message,
|
||||
html: settings.message,
|
||||
});
|
||||
|
@ -1,24 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
background: #ffffff;
|
||||
padding: 45px 30px 22px 30px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 4px #e3e9f3;
|
||||
|
||||
.inputStyle {
|
||||
max-width: 358px;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
margin-bottom: 1.1rem;
|
||||
}
|
||||
|
||||
.subFormWrapper {
|
||||
margin-bottom: 14px;
|
||||
padding: 23px 30px 0 30px;
|
||||
background-color: #fafafb;
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
@ -1,97 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* EditForm
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { findIndex, get, isEmpty, map } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import { InputsIndex as Input } from 'strapi-helper-plugin';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
class EditForm extends React.Component {
|
||||
getProviderForm = () =>
|
||||
get(
|
||||
this.props.settings,
|
||||
['providers', this.props.selectedProviderIndex, 'auth'],
|
||||
{}
|
||||
);
|
||||
|
||||
generateSelectOptions = () =>
|
||||
Object.keys(get(this.props.settings, 'providers', {})).reduce(
|
||||
(acc, current) => {
|
||||
const option = {
|
||||
id: get(this.props.settings, ['providers', current, 'name']),
|
||||
value: get(this.props.settings, ['providers', current, 'provider']),
|
||||
};
|
||||
acc.push(option);
|
||||
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Wrapper>
|
||||
<div className="row">
|
||||
<Input
|
||||
customBootstrapClass="col-md-6"
|
||||
inputDescription={{
|
||||
id: 'email.EditForm.Input.select.inputDescription',
|
||||
}}
|
||||
className="input-wrapper"
|
||||
inputClassName="inputStyle"
|
||||
label={{ id: 'email.EditForm.Input.select.label' }}
|
||||
name="provider"
|
||||
onChange={this.props.onChange}
|
||||
selectOptions={this.generateSelectOptions()}
|
||||
type="select"
|
||||
value={get(this.props.modifiedData, 'provider')}
|
||||
/>
|
||||
</div>
|
||||
{!isEmpty(this.getProviderForm()) && (
|
||||
<div className="subFormWrapper">
|
||||
<div className="row">
|
||||
{map(this.getProviderForm(), (value, key) => (
|
||||
<Input
|
||||
didCheckErrors={this.props.didCheckErrors}
|
||||
errors={get(this.props.formErrors, [
|
||||
findIndex(this.props.formErrors, ['name', key]),
|
||||
'errors',
|
||||
])}
|
||||
key={key}
|
||||
label={{ id: value.label }}
|
||||
name={key}
|
||||
onChange={this.props.onChange}
|
||||
selectOptions={value.values}
|
||||
type={value.type === 'enum' ? 'select' : value.type}
|
||||
validations={{ required: true }}
|
||||
value={get(this.props.modifiedData, key, '')}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EditForm.defaultProps = {
|
||||
settings: {
|
||||
providers: [],
|
||||
},
|
||||
};
|
||||
|
||||
EditForm.propTypes = {
|
||||
didCheckErrors: PropTypes.bool.isRequired,
|
||||
formErrors: PropTypes.array.isRequired,
|
||||
modifiedData: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
selectedProviderIndex: PropTypes.number.isRequired,
|
||||
settings: PropTypes.object,
|
||||
};
|
||||
|
||||
export default EditForm;
|
@ -1,36 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* This component is the skeleton around the actual pages, and should only
|
||||
* contain code that should be seen on all pages. (e.g. navigation bar)
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
// Containers
|
||||
import ConfigPage from '../ConfigPage';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className={pluginId}>
|
||||
<Switch>
|
||||
<Route
|
||||
path={`/plugins/${pluginId}/configurations/:env`}
|
||||
component={ConfigPage}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`/plugins/${pluginId}/configurations/`}
|
||||
component={ConfigPage}
|
||||
exact
|
||||
/>
|
||||
<Route path={`/plugins/${pluginId}`} component={ConfigPage} exact />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
@ -1,77 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ConfigPage actions
|
||||
*
|
||||
*/
|
||||
|
||||
import {
|
||||
GET_SETTINGS,
|
||||
GET_SETTINGS_SUCCEEDED,
|
||||
ON_CANCEL,
|
||||
ON_CHANGE,
|
||||
SET_ERRORS,
|
||||
SUBMIT,
|
||||
SUBMIT_ERROR,
|
||||
SUBMIT_SUCCEEDED,
|
||||
} from './constants';
|
||||
|
||||
export function getSettings(env) {
|
||||
return {
|
||||
type: GET_SETTINGS,
|
||||
env,
|
||||
};
|
||||
}
|
||||
|
||||
export function getSettingsSucceeded(settings, appEnvironments) {
|
||||
return {
|
||||
type: GET_SETTINGS_SUCCEEDED,
|
||||
appEnvironments,
|
||||
settings,
|
||||
initialData: settings.config,
|
||||
};
|
||||
}
|
||||
|
||||
export function onCancel() {
|
||||
return {
|
||||
type: ON_CANCEL,
|
||||
};
|
||||
}
|
||||
|
||||
export function onChange({ target }) {
|
||||
const keys = ['modifiedData'].concat(target.name.split('.'));
|
||||
const value = target.value;
|
||||
|
||||
return {
|
||||
type: ON_CHANGE,
|
||||
keys,
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
export function setErrors(errors) {
|
||||
return {
|
||||
type: SET_ERRORS,
|
||||
errors,
|
||||
};
|
||||
}
|
||||
|
||||
export function submit() {
|
||||
return {
|
||||
type: SUBMIT,
|
||||
};
|
||||
}
|
||||
|
||||
export function submitError(errors) {
|
||||
return {
|
||||
type: SUBMIT_ERROR,
|
||||
errors,
|
||||
};
|
||||
}
|
||||
|
||||
export function submitSucceeded(data) {
|
||||
return {
|
||||
type: SUBMIT_SUCCEEDED,
|
||||
data,
|
||||
};
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* ConfigPage constants
|
||||
*
|
||||
*/
|
||||
|
||||
export const GET_ENV = 'Email/ConfigPage/GET_ENV';
|
||||
export const GET_ENV_SUCCEEDED = 'Email/ConfigPage/GET_ENV_SUCCEEDED';
|
||||
export const GET_SETTINGS = 'Email/ConfigPage/GET_SETTINGS';
|
||||
export const GET_SETTINGS_SUCCEEDED = 'Email/ConfigPage/GET_SETTINGS_SUCCEEDED';
|
||||
export const ON_CANCEL = 'Email/ConfigPage/ON_CANCEL';
|
||||
export const ON_CHANGE = 'Email/ConfigPage/ON_CHANGE';
|
||||
export const SET_ERRORS = 'Email/ConfigPage/SET_ERRORS';
|
||||
export const SUBMIT = 'Email/ConfigPage/SUBMIT';
|
||||
export const SUBMIT_ERROR = 'Email/ConfigPage/SUBMIT_ERROR';
|
||||
export const SUBMIT_SUCCEEDED = 'Email/ConfigPage/SUBMIT_SUCCEEDED';
|
@ -1,190 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* ConfigPage
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import { findIndex, get, isEmpty } from 'lodash';
|
||||
import { Header } from '@buffetjs/custom';
|
||||
// You can find these components in either
|
||||
// ./node_modules/strapi-helper-plugin/lib/src
|
||||
// or strapi/packages/strapi-helper-plugin/lib/src
|
||||
import { ContainerFluid, HeaderNav, GlobalContext } from 'strapi-helper-plugin';
|
||||
import pluginId from '../../pluginId';
|
||||
// Plugin's components
|
||||
import EditForm from '../../components/EditForm';
|
||||
import { getSettings, onCancel, onChange, setErrors, submit } from './actions';
|
||||
import saga from './saga';
|
||||
import selectConfigPage from './selectors';
|
||||
|
||||
class ConfigPage extends React.Component {
|
||||
pluginHeaderActions = [
|
||||
{
|
||||
color: 'cancel',
|
||||
label: this.context.formatMessage({ id: 'app.components.Button.cancel' }),
|
||||
onClick: this.props.onCancel,
|
||||
type: 'button',
|
||||
key: 'button-cancel',
|
||||
},
|
||||
{
|
||||
color: 'success',
|
||||
label: this.context.formatMessage({ id: 'app.components.Button.save' }),
|
||||
onClick: this.handleSubmit,
|
||||
type: 'submit',
|
||||
key: 'button-submit',
|
||||
},
|
||||
];
|
||||
|
||||
componentDidMount() {
|
||||
this.getSettings(this.props);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
// Get new settings on navigation change
|
||||
if (prevProps.match.params.env !== this.props.match.params.env) {
|
||||
this.getSettings(this.props);
|
||||
}
|
||||
|
||||
// Redirect the user to the email list after modifying is provider
|
||||
if (prevProps.submitSuccess !== this.props.submitSuccess) {
|
||||
this.props.history.push(`/plugins/email/configurations/${this.props.match.params.env}`);
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedProviderIndex = () =>
|
||||
findIndex(this.props.settings.providers, [
|
||||
'provider',
|
||||
get(this.props.modifiedData, 'provider'),
|
||||
]);
|
||||
|
||||
/**
|
||||
* Get Settings depending on the props
|
||||
* @param {Object} props
|
||||
* @return {Func} calls the saga that gets the current settings
|
||||
*/
|
||||
getSettings = props => {
|
||||
const {
|
||||
match: {
|
||||
params: { env },
|
||||
},
|
||||
} = props;
|
||||
this.props.getSettings(env);
|
||||
};
|
||||
|
||||
generateLinks = () => {
|
||||
const headerNavLinks = this.props.appEnvironments
|
||||
.reduce((acc, current) => {
|
||||
const link = Object.assign(current, {
|
||||
to: `/plugins/email/configurations/${current.name}`,
|
||||
});
|
||||
acc.push(link);
|
||||
|
||||
return acc;
|
||||
}, [])
|
||||
.sort(link => link.name === 'production');
|
||||
|
||||
return headerNavLinks;
|
||||
};
|
||||
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
const formErrors = Object.keys(
|
||||
get(this.props.settings, ['providers', this.getSelectedProviderIndex(), 'auth'], {})
|
||||
).reduce((acc, current) => {
|
||||
if (isEmpty(get(this.props.modifiedData, current, ''))) {
|
||||
acc.push({
|
||||
name: current,
|
||||
errors: [{ id: 'components.Input.error.validation.required' }],
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (!isEmpty(formErrors)) {
|
||||
return this.props.setErrors(formErrors);
|
||||
}
|
||||
|
||||
return this.props.submit();
|
||||
};
|
||||
|
||||
static contextType = GlobalContext;
|
||||
|
||||
render() {
|
||||
const { formatMessage } = this.context;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<ContainerFluid>
|
||||
<Header
|
||||
actions={this.pluginHeaderActions}
|
||||
content={formatMessage({
|
||||
id: 'email.ConfigPage.description',
|
||||
})}
|
||||
title={{ label: formatMessage({ id: 'email.ConfigPage.title' }) }}
|
||||
/>
|
||||
<HeaderNav links={this.generateLinks()} style={{ marginTop: '4.6rem' }} />
|
||||
<EditForm
|
||||
didCheckErrors={this.props.didCheckErrors}
|
||||
formErrors={this.props.formErrors}
|
||||
modifiedData={this.props.modifiedData}
|
||||
onChange={this.props.onChange}
|
||||
selectedProviderIndex={this.getSelectedProviderIndex()}
|
||||
settings={this.props.settings}
|
||||
/>
|
||||
</ContainerFluid>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigPage.defaultProps = {
|
||||
appEnvironments: [],
|
||||
formErrors: [],
|
||||
settings: {
|
||||
providers: [],
|
||||
},
|
||||
};
|
||||
|
||||
ConfigPage.propTypes = {
|
||||
appEnvironments: PropTypes.array,
|
||||
didCheckErrors: PropTypes.bool.isRequired,
|
||||
formErrors: PropTypes.array,
|
||||
getSettings: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
modifiedData: PropTypes.object.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
setErrors: PropTypes.func.isRequired,
|
||||
settings: PropTypes.object,
|
||||
submit: PropTypes.func.isRequired,
|
||||
submitSuccess: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{
|
||||
getSettings,
|
||||
onCancel,
|
||||
onChange,
|
||||
setErrors,
|
||||
submit,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = selectConfigPage();
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withSaga = strapi.injectSaga({ key: 'configPage', saga, pluginId });
|
||||
|
||||
export default compose(withSaga, withConnect)(ConfigPage);
|
@ -1,67 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* ConfigPage reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS, List, Map } from 'immutable';
|
||||
|
||||
import {
|
||||
GET_SETTINGS,
|
||||
GET_SETTINGS_SUCCEEDED,
|
||||
ON_CANCEL,
|
||||
ON_CHANGE,
|
||||
SET_ERRORS,
|
||||
SUBMIT_ERROR,
|
||||
SUBMIT_SUCCEEDED,
|
||||
} from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
appEnvironments: List([]),
|
||||
didCheckErrors: false,
|
||||
env: '',
|
||||
formErrors: List([]),
|
||||
initialData: Map({}),
|
||||
modifiedData: Map({}),
|
||||
settings: {},
|
||||
submitSuccess: false,
|
||||
});
|
||||
|
||||
function configPageReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case GET_SETTINGS:
|
||||
return state.update('env', () => action.env);
|
||||
case GET_SETTINGS_SUCCEEDED:
|
||||
return state
|
||||
.update('appEnvironments', () => List(action.appEnvironments))
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List([]))
|
||||
.update('initialData', () => Map(action.initialData))
|
||||
.update('modifiedData', () => Map(action.initialData))
|
||||
.update('settings', () => action.settings);
|
||||
case ON_CANCEL:
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List([]))
|
||||
.update('modifiedData', () => state.get('initialData'));
|
||||
case ON_CHANGE:
|
||||
return state
|
||||
.updateIn(action.keys, () => action.value);
|
||||
case SET_ERRORS:
|
||||
case SUBMIT_ERROR:
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List(action.errors));
|
||||
case SUBMIT_SUCCEEDED:
|
||||
return state
|
||||
.update('didCheckErrors', (v) => v = !v)
|
||||
.update('formErrors', () => List([]))
|
||||
.update('initialData', () => Map(action.data))
|
||||
.update('modifiedData', () => Map(action.data))
|
||||
.update('submitSuccess', (v) => v = !v);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default configPageReducer;
|
@ -1,51 +0,0 @@
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { all, call, fork, put, select, takeLatest } from 'redux-saga/effects';
|
||||
import { request } from 'strapi-helper-plugin';
|
||||
import { getSettingsSucceeded, submitSucceeded } from './actions';
|
||||
import { GET_SETTINGS, SUBMIT } from './constants';
|
||||
import { makeSelectEnv, makeSelectModifiedData } from './selectors';
|
||||
|
||||
export function* settingsGet(action) {
|
||||
try {
|
||||
const requestURL = `/email/settings/${action.env}`;
|
||||
const response = yield all([
|
||||
call(request, requestURL, { method: 'GET' }),
|
||||
call(request, '/email/environments', { method: 'GET' }),
|
||||
]);
|
||||
|
||||
yield put(getSettingsSucceeded(response[0], response[1].environments));
|
||||
} catch (err) {
|
||||
strapi.notification.error('notification.error');
|
||||
}
|
||||
}
|
||||
|
||||
export function* submit() {
|
||||
try {
|
||||
const env = yield select(makeSelectEnv());
|
||||
let body = yield select(makeSelectModifiedData());
|
||||
|
||||
if (body.provider === 'local') {
|
||||
body = {
|
||||
enabled: body.enabled,
|
||||
provider: 'local',
|
||||
sizeLimit: body.sizeLimit,
|
||||
};
|
||||
}
|
||||
const requestURL = `/email/settings/${env}`;
|
||||
yield call(request, requestURL, { method: 'PUT', body });
|
||||
|
||||
// Update reducer with optimisticResponse
|
||||
strapi.notification.success('email.notification.config.success');
|
||||
yield put(submitSucceeded(body));
|
||||
} catch (err) {
|
||||
strapi.notification.error('notification.error');
|
||||
// TODO handle error PUT
|
||||
}
|
||||
}
|
||||
|
||||
function* defaultSaga() {
|
||||
yield fork(takeLatest, GET_SETTINGS, settingsGet);
|
||||
yield fork(takeLatest, SUBMIT, submit);
|
||||
}
|
||||
|
||||
export default defaultSaga;
|
@ -1,32 +0,0 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the configPage state domain
|
||||
*/
|
||||
const selectConfigPageDomain = () => state => state.get(`${pluginId}_configPage`);
|
||||
|
||||
/**
|
||||
* Default selector used by ConfigPage
|
||||
*/
|
||||
|
||||
const selectConfigPage = () => createSelector(
|
||||
selectConfigPageDomain(),
|
||||
(substate) => substate.toJS(),
|
||||
);
|
||||
|
||||
const makeSelectEnv = () => createSelector(
|
||||
selectConfigPageDomain(),
|
||||
(substate) => substate.get('env'),
|
||||
);
|
||||
|
||||
const makeSelectModifiedData = () => createSelector(
|
||||
selectConfigPageDomain(),
|
||||
(substate) => substate.get('modifiedData').toJS(),
|
||||
);
|
||||
|
||||
export default selectConfigPage;
|
||||
export {
|
||||
makeSelectEnv,
|
||||
makeSelectModifiedData,
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Initializer
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
class Initializer extends React.PureComponent {
|
||||
// eslint-disable-line react/prefer-stateless-function
|
||||
componentDidMount() {
|
||||
// Emit the event 'pluginReady'
|
||||
this.props.updatePlugin(pluginId, 'isReady', true);
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Initializer.propTypes = {
|
||||
updatePlugin: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Initializer;
|
@ -1,19 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mount, shallow } from 'enzyme';
|
||||
|
||||
import Initializer from '../index';
|
||||
|
||||
describe('<Initializer />', () => {
|
||||
it('Should not crash', () => {
|
||||
const updatePlugin = jest.fn();
|
||||
shallow(<Initializer updatePlugin={updatePlugin} />);
|
||||
});
|
||||
|
||||
it('should call the updatePlugin props when mounted', () => {
|
||||
const updatePlugin = jest.fn();
|
||||
|
||||
const wrapper = mount(<Initializer updatePlugin={updatePlugin} />);
|
||||
|
||||
expect(wrapper.prop('updatePlugin')).toHaveBeenCalledWith('email', 'isReady', true);
|
||||
});
|
||||
});
|
@ -8,10 +8,6 @@
|
||||
import pluginPkg from '../../package.json';
|
||||
import pluginId from './pluginId';
|
||||
import pluginLogo from './assets/images/logo.svg';
|
||||
import App from './containers/App';
|
||||
import Initializer from './containers/Initializer';
|
||||
import lifecycles from './lifecycles';
|
||||
import reducers from './reducers';
|
||||
import trads from './translations';
|
||||
|
||||
export default strapi => {
|
||||
@ -23,18 +19,18 @@ export default strapi => {
|
||||
description: pluginDescription,
|
||||
icon: pluginPkg.strapi.icon,
|
||||
id: pluginId,
|
||||
initializer: Initializer,
|
||||
isReady: true,
|
||||
initializer: () => null,
|
||||
injectedComponents: [],
|
||||
isRequired: pluginPkg.strapi.required || false,
|
||||
layout: null,
|
||||
lifecycles,
|
||||
lifecycles: () => {},
|
||||
leftMenuLinks: [],
|
||||
leftMenuSections: [],
|
||||
mainComponent: App,
|
||||
mainComponent: null,
|
||||
name: pluginPkg.strapi.name,
|
||||
pluginLogo,
|
||||
preventComponentRendering: false,
|
||||
reducers,
|
||||
trads,
|
||||
};
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* SET THE HOOKS TO ENABLE THE MAGIC OF STRAPI.
|
||||
* -------------------------------------------
|
||||
*
|
||||
* Secure, customise and enhance your project by setting
|
||||
* the hooks via this file.
|
||||
*
|
||||
*/
|
||||
|
||||
function lifecycles() {}
|
||||
|
||||
export default lifecycles;
|
@ -1,8 +0,0 @@
|
||||
import configPageReducer from './containers/ConfigPage/reducer';
|
||||
import pluginId from './pluginId';
|
||||
|
||||
const reducers = {
|
||||
[`${pluginId}_configPage`]: configPageReducer,
|
||||
};
|
||||
|
||||
export default reducers;
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Nastavení zásuvný modul odesílání e-mailů",
|
||||
"ConfigPage.title": "E-mail - Nastavení",
|
||||
"EditForm.Input.number.label": "Maximální povolená velikost (v MB)",
|
||||
"EditForm.Input.select.inputDescription": "E-maily mohou být odeslány výchozím (Sendmail) nebo externím poskytovatelem.",
|
||||
"EditForm.Input.select.label": "Poskytovatelé",
|
||||
"EditForm.Input.toggle.label": "Povolit odesílání e-mailů",
|
||||
"notification.config.success": "Nastavení bylo uloženo",
|
||||
"plugin.description.long": "Odeslat e-maily.",
|
||||
"plugin.description.short": "Odeslat e-maily."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "E-Mail-Plugin konfigurieren",
|
||||
"ConfigPage.title": "E-Mail - Einstellungen",
|
||||
"EditForm.Input.number.label": "Maximal zulässige Größe (in MB)",
|
||||
"EditForm.Input.select.inputDescription": "E-Mails können mit dem Standardanbieter (Sendmail) oder einem externen Anbieter versendet werden",
|
||||
"EditForm.Input.select.label": "Anbieter",
|
||||
"EditForm.Input.toggle.label": "E-Mail-Versand aktivieren",
|
||||
"notification.config.success": "Die Einstellungen wurden aktualisiert",
|
||||
"plugin.description.long": "Zum Versand von E-Mails.",
|
||||
"plugin.description.short": "Zum Versand von E-Mails."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configure the email plugin",
|
||||
"ConfigPage.title": "Email - Settings",
|
||||
"EditForm.Input.number.label": "Maximum size allowed (in MB)",
|
||||
"EditForm.Input.select.inputDescription": "Emails can be sent with the default provider (Sendmail) or an external provider",
|
||||
"EditForm.Input.select.label": "Providers",
|
||||
"EditForm.Input.toggle.label": "Enable email send",
|
||||
"notification.config.success": "The settings has been updated",
|
||||
"plugin.description.long": "Send emails.",
|
||||
"plugin.description.short": "Send emails."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configurar el plugin de correo electrónico",
|
||||
"ConfigPage.title": "Correo electrónico - Configuración",
|
||||
"EditForm.Input.number.label": "Tamaño máximo permitido (en MB)",
|
||||
"EditForm.Input.select.inputDescription": "Los correos electrónicos se pueden enviar con el proveedor predeterminado (Sendmail) o con un proveedor externo.",
|
||||
"EditForm.Input.select.label": "Proveedores",
|
||||
"EditForm.Input.toggle.label": "Habilitar envío de correo electrónico",
|
||||
"notification.config.success": "Se ha actualizado la configuración",
|
||||
"plugin.description.long": "Enviar correos electrónicos.",
|
||||
"plugin.description.short": "Enviar correos electrónicos."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configurer le plugin email",
|
||||
"ConfigPage.title": "E-mail - Paramètres",
|
||||
"EditForm.Input.number.label": "Taille maximale autorisée (en MB)",
|
||||
"EditForm.Input.select.inputDescription": "Les e-mails peuvent être envoyés avec le fournisseur par défaut (Sendmail) ou un fournisseur externe.",
|
||||
"EditForm.Input.select.label": "Fournisseurs",
|
||||
"EditForm.Input.toggle.label": "Activer l'envoi d'e-mails",
|
||||
"notification.config.success": "Les paramètres ont été mis à jour.",
|
||||
"plugin.description.long": "Envoyez des emails",
|
||||
"plugin.description.short": "Envoyez des emails"
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configura il plugin Email",
|
||||
"ConfigPage.title": "Email - Impostazioni",
|
||||
"EditForm.Input.number.label": "Dimensione massima consentita (in MB)",
|
||||
"EditForm.Input.select.inputDescription": "Le e-mail possono essere inviate con il provider predefinito (Sendmail) o un provider esterno",
|
||||
"EditForm.Input.select.label": "Providers",
|
||||
"EditForm.Input.toggle.label": "Abilita invio email",
|
||||
"notification.config.success": "Le impostazioni sono state aggiornate",
|
||||
"plugin.description.long": "Invia le email.",
|
||||
"plugin.description.short": "Invia le email."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Eメールプラグインを設定する",
|
||||
"ConfigPage.title": "Eメール - 設定",
|
||||
"EditForm.Input.number.label": "許可される最大サイズ(MB単位)",
|
||||
"EditForm.Input.select.inputDescription": "電子メールは、デフォルトのプロバイダ(Sendmail)または外部プロバイダ",
|
||||
"EditForm.Input.select.label": "プロバイダー",
|
||||
"EditForm.Input.toggle.label": "メール送信を有効にする",
|
||||
"notification.config.success": "設定が更新されました",
|
||||
"plugin.description.long": "メールを送る",
|
||||
"plugin.description.short": "メールを送る"
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "이메일 플러그인을 설정합니다.",
|
||||
"ConfigPage.title": "이메일 설정",
|
||||
"EditForm.Input.number.label": "최대 허용 크기(MB)",
|
||||
"EditForm.Input.select.inputDescription": "이메일을 기본 프로바이더(Sendmail) 또는 외부 프로바이더를 통해 전동합니다.",
|
||||
"EditForm.Input.select.label": "프로바이더(Providers)",
|
||||
"EditForm.Input.toggle.label": "이메일 전송 허용",
|
||||
"notification.config.success": "설정을 업데이트 했습니다.",
|
||||
"plugin.description.long": "이메일을 전송합니다.",
|
||||
"plugin.description.short": "이메일을 전송합니다."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configureer de e-mail extensie",
|
||||
"ConfigPage.title": "E-mail - Instellingen",
|
||||
"EditForm.Input.number.label": "Maximum grootte toegestaan (in MB)",
|
||||
"EditForm.Input.select.inputDescription": "E-mails kunnen worden verstuurd via de standaard leverancier (Sendmail) of via een externe leverancier",
|
||||
"EditForm.Input.select.label": "Leveranciers",
|
||||
"EditForm.Input.toggle.label": "E-mail versturen inschakelen",
|
||||
"notification.config.success": "De instellingen zijn opgeslagen.",
|
||||
"plugin.description.long": "Verstuur e-mails.",
|
||||
"plugin.description.short": "Verstuur e-mails."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Skonfiguruj plugin email",
|
||||
"ConfigPage.title": "Email - Ustawienia",
|
||||
"EditForm.Input.number.label": "Maksymalny dozwolony rozmiar (w MB)",
|
||||
"EditForm.Input.select.inputDescription": "E-maile mogą być wysyłane z wykorzystaniem domyślnego (Sendmail) albo zewnętrznego dostawcy",
|
||||
"EditForm.Input.select.label": "Dostawcy",
|
||||
"EditForm.Input.toggle.label": "Włącz wysyłkę e-maili",
|
||||
"notification.config.success": "Ustawienia zostały zaktualizowane",
|
||||
"plugin.description.long": "Wysyłaj E-maile",
|
||||
"plugin.description.short": "Wysyłaj E-maile"
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configure a extensão do email",
|
||||
"ConfigPage.title": "E-mail - Definições",
|
||||
"EditForm.Input.number.label": "Tamanho máximo permitido (em MB)",
|
||||
"EditForm.Input.select.inputDescription": "Os emails podem ser enviados com o provedor predefinido (Sendmail) ou por um provedor externo",
|
||||
"EditForm.Input.select.label": "Provedores",
|
||||
"EditForm.Input.toggle.label": "Ativar envio de email",
|
||||
"notification.config.success": "As configurações foram atualizadas",
|
||||
"plugin.description.long": "Enviar emails.",
|
||||
"plugin.description.short": "Enviar emails."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Configure a extensão do email",
|
||||
"ConfigPage.title": "Email - Definições",
|
||||
"EditForm.Input.number.label": "Tamanho máximo permitido (em MB)",
|
||||
"EditForm.Input.select.inputDescription": "Os emails podem ser enviados com o provedor predefinido (Sendmail) ou por um provedor externo",
|
||||
"EditForm.Input.select.label": "Provedores",
|
||||
"EditForm.Input.toggle.label": "Activar envio de email",
|
||||
"notification.config.success": "As configurações foram actualizadas",
|
||||
"plugin.description.long": "Enviar emails.",
|
||||
"plugin.description.short": "Enviar emails."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Настройка плагина email",
|
||||
"ConfigPage.title": "Email - Настройки",
|
||||
"EditForm.Input.number.label": "Максимально допустимый размер (в МБ)",
|
||||
"EditForm.Input.select.inputDescription": "Письма могут быть отправлены стандартным способом (Sendmail) или с помощью внешних провайдеров",
|
||||
"EditForm.Input.select.label": "Провайдеры",
|
||||
"EditForm.Input.toggle.label": "Активировать отправку писем",
|
||||
"notification.config.success": "Настройки успешно обновлены",
|
||||
"plugin.description.long": "Отправка почты.",
|
||||
"plugin.description.short": "Отправка почты."
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Nastavenia odosielania e-mailov",
|
||||
"ConfigPage.title": "Email - Nastavenia",
|
||||
"EditForm.Input.number.label": "Maximálna povolená veľkosť (v MB)",
|
||||
"EditForm.Input.select.inputDescription": "E-maily môžu byť posielané cez Sendmail alebo externého poskytovateľa",
|
||||
"EditForm.Input.select.label": "Poskytovatelia",
|
||||
"EditForm.Input.toggle.label": "Povoliť odosielanie emailov",
|
||||
"notification.config.success": "Nastavenia boli upravené",
|
||||
"plugin.description.long": "Posielanie e-mailov.",
|
||||
"plugin.description.short": "Posielanie e-mailov."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "E-posta eklentisini yapılandırma",
|
||||
"ConfigPage.title": "E-posta - Ayarlar",
|
||||
"EditForm.Input.number.label": "İzin verilen maksimum boyut (MB cinsinden)",
|
||||
"EditForm.Input.select.inputDescription": "E-postalar varsayılan sağlayıcı (Sendmail) veya harici bir sağlayıcıyla gönderilebilir",
|
||||
"EditForm.Input.select.label": "Sağlayıcıları",
|
||||
"EditForm.Input.toggle.label": "E-posta gönderimini etkinleştir",
|
||||
"notification.config.success": "Ayarlar güncellendi",
|
||||
"plugin.description.long": "E-posta gönder.",
|
||||
"plugin.description.short": "E-posta gönder."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "Cấu hình email plugin",
|
||||
"ConfigPage.title": "Email - Các cài đặt",
|
||||
"EditForm.Input.number.label": "Kích thước tối đa được phép (MB)",
|
||||
"EditForm.Input.select.inputDescription": "Các Email có thể được gửi với nhà cung cấp mặc định (Sendmail) hoặc là nhà cung cấp bên ngoài",
|
||||
"EditForm.Input.select.label": "Các nhà cung cấp",
|
||||
"EditForm.Input.toggle.label": "Kích hoạt gửi email",
|
||||
"notification.config.success": "Các cài đặt đã được cập nhật",
|
||||
"plugin.description.long": "Gửi các email.",
|
||||
"plugin.description.short": "Gửi các email."
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "配置电子邮件插件",
|
||||
"ConfigPage.title": "电子邮件 - 设置",
|
||||
"EditForm.Input.number.label": "最大文件限制 (单位:MB)",
|
||||
"EditForm.Input.select.inputDescription": "可以使用默认提供商(Sendmail)或外部提供商发送电子邮件",
|
||||
"EditForm.Input.select.label": "提供商",
|
||||
"EditForm.Input.toggle.label": "启用电子邮件发送",
|
||||
"notification.config.success": "设置已更新",
|
||||
"plugin.description.long": "发送电子邮件。",
|
||||
"plugin.description.short": "发送电子邮件。"
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
{
|
||||
"ConfigPage.description": "設定郵件擴充功能",
|
||||
"ConfigPage.title": "郵件 - 設定",
|
||||
"EditForm.Input.number.label": "最大大小 (MB)",
|
||||
"EditForm.Input.select.inputDescription": "可以使用預設 (Sendmail) 或其他套件寄送郵件",
|
||||
"EditForm.Input.select.label": "套件",
|
||||
"EditForm.Input.toggle.label": "啟動寄信功能",
|
||||
"notification.config.success": "設定已經更新",
|
||||
"plugin.description.long": "寄送電子郵件",
|
||||
"plugin.description.short": "寄送電子郵件"
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* An asynchronous bootstrap function that runs before
|
||||
* your application gets started.
|
||||
*
|
||||
* This gives you an opportunity to set up your data model,
|
||||
* run jobs, or perform some special logic.
|
||||
*/
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = async () => {
|
||||
// set plugin store
|
||||
const pluginStore = strapi.store({
|
||||
environment: strapi.config.environment,
|
||||
type: 'plugin',
|
||||
name: 'email',
|
||||
});
|
||||
|
||||
strapi.plugins.email.config.providers = [];
|
||||
|
||||
const installedProviders = Object.keys(strapi.config.info.dependencies)
|
||||
.filter(d => d.includes('strapi-provider-email-'))
|
||||
.concat('strapi-provider-email-sendmail');
|
||||
|
||||
for (let installedProvider of _.uniq(installedProviders)) {
|
||||
strapi.plugins.email.config.providers.push(require(installedProvider));
|
||||
}
|
||||
|
||||
// if provider config does not exist set one by default
|
||||
const config = await pluginStore.get({ key: 'provider' });
|
||||
|
||||
if (!config) {
|
||||
const provider = _.find(strapi.plugins.email.config.providers, {
|
||||
provider: 'sendmail',
|
||||
});
|
||||
|
||||
const value = _.assign({}, provider, {
|
||||
// TODO: set other default settings here
|
||||
});
|
||||
|
||||
await pluginStore.set({ key: 'provider', value });
|
||||
const createProvider = emailConfig => {
|
||||
const providerName = _.toLower(emailConfig.provider);
|
||||
let provider;
|
||||
try {
|
||||
provider = require(`strapi-provider-email-${providerName}`);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`The provider package isn't installed. Please run \`npm install strapi-provider-email-${providerName}\` --save`
|
||||
);
|
||||
}
|
||||
return provider.init(emailConfig.providerOptions, emailConfig.settings);
|
||||
};
|
||||
|
||||
module.exports = async () => {
|
||||
const emailConfig = _.get(strapi.plugins, 'email.config', {});
|
||||
strapi.plugins.email.provider = createProvider(emailConfig);
|
||||
};
|
||||
|
@ -12,30 +12,6 @@
|
||||
"name": "Email"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/environments",
|
||||
"handler": "Email.getEnvironments",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/settings/:environment",
|
||||
"handler": "Email.getSettings",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "PUT",
|
||||
"path": "/settings/:environment",
|
||||
"handler": "Email.updateSettings",
|
||||
"config": {
|
||||
"policies": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
7
packages/strapi-plugin-email/config/settings.js
Normal file
7
packages/strapi-plugin-email/config/settings.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
provider: 'sendmail',
|
||||
providerOptions: {},
|
||||
settings: {
|
||||
defaultFrom: 'Strapi <no-reply@strapi.io>',
|
||||
},
|
||||
};
|
@ -7,69 +7,10 @@
|
||||
*/
|
||||
module.exports = {
|
||||
send: async ctx => {
|
||||
// Retrieve provider configuration.
|
||||
const config = await strapi
|
||||
.store({
|
||||
environment: strapi.config.environment,
|
||||
type: 'plugin',
|
||||
name: 'email',
|
||||
})
|
||||
.get({ key: 'provider' });
|
||||
|
||||
// Verify if the file email is enable.
|
||||
if (config.enabled === false) {
|
||||
strapi.log.error('Email is disabled');
|
||||
return ctx.badRequest(null, [
|
||||
{
|
||||
messages: [{ id: 'Email.status.disabled', message: 'Emails disabled' }],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
// Something is wrong
|
||||
if (ctx.status === 400) {
|
||||
return;
|
||||
}
|
||||
|
||||
let options = ctx.request.body;
|
||||
|
||||
await strapi.plugins.email.services.email.send(options, config);
|
||||
await strapi.plugins.email.services.email.send(options);
|
||||
|
||||
// Send 200 `ok`
|
||||
ctx.send({});
|
||||
},
|
||||
|
||||
getEnvironments: async ctx => {
|
||||
const envs = ['development', 'staging', 'production'];
|
||||
|
||||
ctx.send({
|
||||
environments: envs.map(env => ({
|
||||
name: env,
|
||||
active: env === strapi.config.environment,
|
||||
})),
|
||||
});
|
||||
},
|
||||
|
||||
getSettings: async ctx => {
|
||||
let config = await strapi.plugins.email.services.email.getProviderConfig(
|
||||
ctx.params.environment
|
||||
);
|
||||
|
||||
ctx.send({
|
||||
providers: strapi.plugins.email.config.providers,
|
||||
config,
|
||||
});
|
||||
},
|
||||
|
||||
updateSettings: async ctx => {
|
||||
await strapi
|
||||
.store({
|
||||
environment: ctx.params.environment,
|
||||
type: 'plugin',
|
||||
name: 'email',
|
||||
})
|
||||
.set({ key: 'provider', value: ctx.request.body });
|
||||
|
||||
ctx.send({ ok: true });
|
||||
},
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
"/email/": {
|
||||
"post": {
|
||||
"deprecated": false,
|
||||
"description": "Send an email using the provider defined through the dashboard",
|
||||
"description": "Send an email",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
@ -17,11 +17,22 @@
|
||||
"to": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"example": "user@example.com"
|
||||
"example": "user1@example.com"
|
||||
},
|
||||
"reply_to": {
|
||||
"cc": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"example": "user2@example.com"
|
||||
},
|
||||
"bcc": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"example": "user3@example.com"
|
||||
},
|
||||
"replyTo": {
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
"example": "user4@example.com"
|
||||
},
|
||||
"subject": {
|
||||
"type": "string",
|
||||
@ -53,4 +64,4 @@
|
||||
"name": "Email"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,72 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Email.js service
|
||||
*
|
||||
* @description: A set of functions similar to controller's actions to avoid code duplication.
|
||||
*/
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const createDefaultEnvConfig = async env => {
|
||||
const pluginStore = strapi.store({
|
||||
environment: env,
|
||||
type: 'plugin',
|
||||
name: 'email',
|
||||
});
|
||||
|
||||
const provider = _.find(strapi.plugins.email.config.providers, {
|
||||
provider: 'sendmail',
|
||||
});
|
||||
const value = _.assign({}, provider, {});
|
||||
|
||||
await pluginStore.set({ key: 'provider', value });
|
||||
return await strapi
|
||||
.store({
|
||||
environment: env,
|
||||
type: 'plugin',
|
||||
name: 'email',
|
||||
})
|
||||
.get({ key: 'provider' });
|
||||
};
|
||||
|
||||
const getProviderConfig = async env => {
|
||||
let config = await strapi
|
||||
.store({
|
||||
environment: env,
|
||||
type: 'plugin',
|
||||
name: 'email',
|
||||
})
|
||||
.get({ key: 'provider' });
|
||||
|
||||
if (!config) {
|
||||
config = await createDefaultEnvConfig(env);
|
||||
}
|
||||
|
||||
return config;
|
||||
const getProviderConfig = () => {
|
||||
return strapi.plugins.email.config;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getProviderConfig,
|
||||
async send(options, config) {
|
||||
// Get email provider settings to configure the provider to use.
|
||||
if (!config) {
|
||||
config = await getProviderConfig(strapi.config.environment);
|
||||
}
|
||||
|
||||
const provider = _.find(strapi.plugins.email.config.providers, {
|
||||
provider: config.provider,
|
||||
});
|
||||
|
||||
if (!provider) {
|
||||
throw new Error(
|
||||
`The provider package isn't installed. Please run \`npm install strapi-provider-email-${config.provider}\``
|
||||
);
|
||||
}
|
||||
|
||||
const actions = await provider.init(config);
|
||||
|
||||
// Execute email function of the provider for all files.
|
||||
return actions.send(options);
|
||||
async send(options) {
|
||||
return strapi.plugins.email.provider.send(options);
|
||||
},
|
||||
};
|
||||
|
@ -9,3 +9,50 @@
|
||||
- [Strapi website](http://strapi.io/)
|
||||
- [Strapi community on Slack](http://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need to have the plugin `strapi-plugin-email` installed in you Strapi project.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# using yarn
|
||||
yarn add strapi-provider-email-amazon-ses
|
||||
|
||||
# using npm
|
||||
npm install strapi-provider-email-amazon-ses --save
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Type | Description | Required | Default |
|
||||
| ----------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------- | --------- |
|
||||
| provider | string | The name of the provider you use | yes | |
|
||||
| providerOptions | object | Will be directly given to `createClient` function. Please refer to [node-ses](https://www.npmjs.com/package/node-ses) doc. | yes | |
|
||||
| settings | object | Settings | no | {} |
|
||||
| settings.defaultFrom | string | Default sender mail address | no | undefined |
|
||||
| settings.defaultReplyTo | string \| array<string> | Default address or addresses the receiver is asked to reply to | no | undefined |
|
||||
|
||||
### Example
|
||||
|
||||
**Path -** `config/plugins.js`
|
||||
|
||||
```js
|
||||
module.exports = ({ env }) => ({
|
||||
// ...
|
||||
email: {
|
||||
provider: 'amazon-ses',
|
||||
providerOptions: {
|
||||
key: env('AWS_SES_KEY'),
|
||||
secret: env('AWS_SES_SECRET'),
|
||||
amazon: 'https://email.us-east-1.amazonaws.com',
|
||||
},
|
||||
settings: {
|
||||
defaultFrom: 'myemail@protonmail.com',
|
||||
defaultReplyTo: 'myemail@protonmail.com',
|
||||
},
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
@ -1,68 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const nodeSES = require('node-ses');
|
||||
const { removeUndefined } = require('strapi-utils');
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
module.exports = {
|
||||
provider: 'amazon-ses',
|
||||
name: 'Amazon SES',
|
||||
auth: {
|
||||
amazon_ses_default_from: {
|
||||
label: 'Default From',
|
||||
type: 'text',
|
||||
},
|
||||
amazon_ses_default_replyto: {
|
||||
label: 'Default Reply-To',
|
||||
type: 'text',
|
||||
},
|
||||
amazon_ses_api_key: {
|
||||
label: 'Amazon Access key ID',
|
||||
type: 'text',
|
||||
},
|
||||
amazon_ses_secret: {
|
||||
label: 'Amazon Secret access key',
|
||||
type: 'text',
|
||||
},
|
||||
amazon_ses_endpoint: {
|
||||
label: 'Amazon end-point uri',
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
|
||||
init: config => {
|
||||
var client = nodeSES.createClient({
|
||||
key: config.amazon_ses_api_key,
|
||||
secret: config.amazon_ses_secret,
|
||||
amazon: config.amazon_ses_endpoint,
|
||||
});
|
||||
init: (providerOptions = {}, settings = {}) => {
|
||||
var client = nodeSES.createClient({ ...providerOptions });
|
||||
|
||||
return {
|
||||
send: options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Default values.
|
||||
options = _.isObject(options) ? options : {};
|
||||
options.from = config.amazon_ses_default_from || options.from;
|
||||
options.replyTo = config.amazon_ses_default_replyto || options.replyTo;
|
||||
options.text = options.text || options.html;
|
||||
options.html = options.html || options.text;
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
let msg = {
|
||||
from: options.from,
|
||||
to: options.to,
|
||||
replyTo: options.replyTo,
|
||||
subject: options.subject,
|
||||
altText: options.text,
|
||||
message: options.html,
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
replyTo: replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
|
||||
client.sendEmail(msg, function(err) {
|
||||
client.sendEmail(removeUndefined(msg), function(err) {
|
||||
if (err) {
|
||||
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
|
||||
} else {
|
||||
|
@ -14,8 +14,8 @@
|
||||
},
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.11",
|
||||
"node-ses": "^3.0.0"
|
||||
"node-ses": "^3.0.0",
|
||||
"strapi-utils": "3.0.0-beta.20.3"
|
||||
},
|
||||
"author": {
|
||||
"email": "nikolay@tsenkov.net",
|
||||
|
@ -9,3 +9,48 @@
|
||||
- [Strapi website](http://strapi.io/)
|
||||
- [Strapi community on Slack](http://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need to have the plugin `strapi-plugin-email` installed in you Strapi project.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# using yarn
|
||||
yarn add strapi-provider-email-mailgun
|
||||
|
||||
# using npm
|
||||
npm install strapi-provider-email-mailgun --save
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Type | Description | Required | Default |
|
||||
| ----------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- |
|
||||
| provider | string | The name of the provider you use | yes | |
|
||||
| providerOptions | object | Will be directly given to the `require('mailgun-js')`. Please refer to [mailgun-js](https://www.npmjs.com/package/mailgun-js) doc. | yes | |
|
||||
| settings | object | Settings | no | {} |
|
||||
| settings.defaultFrom | string | Default sender mail address | no | undefined |
|
||||
| settings.defaultReplyTo | string \| array<string> | Default address or addresses the receiver is asked to reply to | no | undefined |
|
||||
|
||||
### Example
|
||||
|
||||
**Path -** `config/plugins.js`
|
||||
|
||||
```js
|
||||
module.exports = ({ env }) => ({
|
||||
// ...
|
||||
email: {
|
||||
provider: 'mailgun',
|
||||
providerOptions: {
|
||||
apiKey: env('MAILGUN_API_KEY'),
|
||||
},
|
||||
settings: {
|
||||
defaultFrom: 'myemail@protonmail.com',
|
||||
defaultReplyTo: 'myemail@protonmail.com',
|
||||
},
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
@ -1,69 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
// Public node modules.
|
||||
const isObject = require('lodash/isObject');
|
||||
const mailgunFactory = require('mailgun-js');
|
||||
const { removeUndefined } = require('strapi-utils');
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
module.exports = {
|
||||
provider: 'mailgun',
|
||||
name: 'Mailgun',
|
||||
auth: {
|
||||
mailgun_default_from: {
|
||||
label: 'Mailgun Default From',
|
||||
type: 'text',
|
||||
},
|
||||
mailgun_default_replyto: {
|
||||
label: 'Mailgun Default Reply-To',
|
||||
type: 'text',
|
||||
},
|
||||
mailgun_api_key: {
|
||||
label: 'Mailgun API Key',
|
||||
type: 'text',
|
||||
},
|
||||
mailgun_api_host: {
|
||||
label: 'Mailgun API Host',
|
||||
type: 'text',
|
||||
},
|
||||
mailgun_domain: {
|
||||
label: 'Mailgun Domain',
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
init: config => {
|
||||
init: (providerOptions = {}, settings = {}) => {
|
||||
const mailgun = mailgunFactory({
|
||||
apiKey: config.mailgun_api_key,
|
||||
host: config.mailgun_api_host,
|
||||
domain: config.mailgun_domain,
|
||||
mute: false,
|
||||
...providerOptions,
|
||||
});
|
||||
|
||||
return {
|
||||
send: options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Default values.
|
||||
options = isObject(options) ? options : {};
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
let msg = {
|
||||
from: options.from || config.mailgun_default_from,
|
||||
to: options.to,
|
||||
subject: options.subject,
|
||||
...(options.text && { text: options.text }),
|
||||
...(options.html && { html: options.html }),
|
||||
...(options.template && { template: options.template }),
|
||||
...(options['h:X-Mailgun-Variables'] && {
|
||||
'h:X-Mailgun-Variables': options['h:X-Mailgun-Variables'],
|
||||
}),
|
||||
...(options.attachment && { attachment: options.attachment }),
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
'h:Reply-To': replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
msg['h:Reply-To'] = options.replyTo || config.mailgun_default_replyto;
|
||||
|
||||
mailgun.messages().send(msg, function(err) {
|
||||
mailgun.messages().send(removeUndefined(msg), function(err) {
|
||||
if (err) {
|
||||
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
|
||||
} else {
|
||||
|
@ -13,8 +13,8 @@
|
||||
},
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.11",
|
||||
"mailgun-js": "0.22.0"
|
||||
"mailgun-js": "0.22.0",
|
||||
"strapi-utils": "3.0.0-beta.20.3"
|
||||
},
|
||||
"strapi": {
|
||||
"isProvider": true
|
||||
|
@ -1,4 +1,4 @@
|
||||
# strapi-provider-email-sendmail
|
||||
# strapi-provider-email-sendgrid
|
||||
|
||||
## Resources
|
||||
|
||||
@ -9,3 +9,49 @@
|
||||
- [Strapi website](http://strapi.io/)
|
||||
- [Strapi community on Slack](http://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need to have the plugin `strapi-plugin-email` installed in you Strapi project.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# using yarn
|
||||
yarn add strapi-provider-email-sendgrid
|
||||
|
||||
# using npm
|
||||
npm install strapi-provider-email-sendgrid --save
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Type | Description | Required | Default |
|
||||
| ----------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------- | --------- |
|
||||
| provider | string | The name of the provider you use | yes | |
|
||||
| providerOptions | object | Provider options | yes | |
|
||||
| providerOptions.apiKey | object | Api key given to the function setApiKey. Please refer to [@sendgrid/mail](https://www.npmjs.com/package/@sendgrid/mail) | yes | |
|
||||
| settings | object | Settings | no | {} |
|
||||
| settings.defaultFrom | string | Default sender mail address | no | undefined |
|
||||
| settings.defaultReplyTo | string \| array<string> | Default address or addresses the receiver is asked to reply to | no | undefined |
|
||||
|
||||
### Example
|
||||
|
||||
**Path -** `config/plugins.js`
|
||||
|
||||
```js
|
||||
module.exports = ({ env }) => ({
|
||||
// ...
|
||||
email: {
|
||||
provider: 'sendgrid',
|
||||
providerOptions: {
|
||||
apiKey: env('SENDGRID_API_KEY'),
|
||||
},
|
||||
settings: {
|
||||
defaultFrom: 'myemail@protonmail.com',
|
||||
defaultReplyTo: 'myemail@protonmail.com',
|
||||
},
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
@ -1,59 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
/* eslint-disable prefer-template */
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const sendgrid = require('@sendgrid/mail');
|
||||
const { removeUndefined } = require('strapi-utils');
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
module.exports = {
|
||||
provider: 'sendgrid',
|
||||
name: 'Sendgrid',
|
||||
auth: {
|
||||
sendgrid_default_from: {
|
||||
label: 'Sendgrid Default From',
|
||||
type: 'text',
|
||||
},
|
||||
sendgrid_default_replyto: {
|
||||
label: 'Sendgrid Default Reply-To',
|
||||
type: 'text',
|
||||
},
|
||||
sendgrid_api_key: {
|
||||
label: 'Sendgrid API Key',
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
init: config => {
|
||||
sendgrid.setApiKey(config.sendgrid_api_key);
|
||||
init: (providerOptions = {}, settings = {}) => {
|
||||
sendgrid.setApiKey(providerOptions.apiKey);
|
||||
|
||||
return {
|
||||
send: options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Default values.
|
||||
options = _.isObject(options) ? options : {};
|
||||
options.from = options.from || config.sendgrid_default_from;
|
||||
options.replyTo = options.replyTo || config.sendgrid_default_replyto;
|
||||
options.text = options.text || options.html;
|
||||
options.html = options.html || options.text;
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
let msg = {
|
||||
from: options.from,
|
||||
to: options.to,
|
||||
replyTo: options.replyTo,
|
||||
subject: options.subject,
|
||||
text: options.text,
|
||||
html: options.html,
|
||||
templateId: options.templateId,
|
||||
dynamic_template_data: options.dynamic_template_data,
|
||||
sendAt: options.sendAt,
|
||||
batchId: options.batchId,
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
replyTo: replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
|
||||
sendgrid.send(msg, function(err) {
|
||||
sendgrid.send(removeUndefined(msg), function(err) {
|
||||
if (err) {
|
||||
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
|
||||
} else {
|
||||
|
@ -14,7 +14,7 @@
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"@sendgrid/mail": "6.4.0",
|
||||
"lodash": "^4.17.11"
|
||||
"strapi-utils": "3.0.0-beta.20.3"
|
||||
},
|
||||
"strapi": {
|
||||
"isProvider": true
|
||||
|
@ -9,3 +9,45 @@
|
||||
- [Strapi website](http://strapi.io/)
|
||||
- [Strapi community on Slack](http://slack.strapi.io)
|
||||
- [Strapi news on Twitter](https://twitter.com/strapijs)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need to have the plugin `strapi-plugin-email` installed in you Strapi project.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# using yarn
|
||||
yarn add strapi-provider-email-sendmail
|
||||
|
||||
# using npm
|
||||
npm install strapi-provider-email-sendmail --save
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Variable | Type | Description | Required | Default |
|
||||
| ----------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------- | --------- |
|
||||
| provider | string | The name of the provider you use | yes | |
|
||||
| providerOptions | object | Will be directly given to `require('sendmail')`. Please refer to [sendmail](https://www.npmjs.com/package/sendmail) doc. | no | {} |
|
||||
| settings | object | Settings | no | {} |
|
||||
| settings.defaultFrom | string | Default sender mail address | no | undefined |
|
||||
| settings.defaultReplyTo | string \| array<string> | Default address or addresses the receiver is asked to reply to | no | undefined |
|
||||
|
||||
### Example
|
||||
|
||||
**Path -** `config/plugins.js`
|
||||
|
||||
```js
|
||||
module.exports = ({ env }) => ({
|
||||
// ...
|
||||
email: {
|
||||
provider: 'sendmail',
|
||||
settings: {
|
||||
defaultFrom: 'myemail@protonmail.com',
|
||||
defaultReplyTo: 'myemail@protonmail.com',
|
||||
},
|
||||
},
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
@ -1,58 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
const sendmailFactory = require('sendmail');
|
||||
const { removeUndefined } = require('strapi-utils');
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
const sendmail = require('sendmail')({
|
||||
silent: true,
|
||||
});
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
module.exports = {
|
||||
provider: 'sendmail',
|
||||
name: 'Sendmail',
|
||||
auth: {
|
||||
sendmail_default_from: {
|
||||
label: 'Sendmail Default From',
|
||||
type: 'text',
|
||||
},
|
||||
sendmail_default_replyto: {
|
||||
label: 'Sendmail Default Reply-To',
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
init: config => {
|
||||
init: (providerOptions = {}, settings = {}) => {
|
||||
const sendmail = sendmailFactory({
|
||||
silent: true,
|
||||
...providerOptions,
|
||||
});
|
||||
return {
|
||||
send: options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Default values.
|
||||
options = _.isObject(options) ? options : {};
|
||||
options.from = options.from || config.sendmail_default_from;
|
||||
options.replyTo = options.replyTo || config.sendmail_default_replyto;
|
||||
options.text = options.text || options.html;
|
||||
options.html = options.html || options.text;
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
sendmail(
|
||||
{
|
||||
from: options.from,
|
||||
to: options.to,
|
||||
replyTo: options.replyTo,
|
||||
subject: options.subject,
|
||||
text: options.text,
|
||||
html: options.html,
|
||||
attachments: options.attachments,
|
||||
},
|
||||
function(err) {
|
||||
if (err) {
|
||||
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
let msg = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
replyTo: replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
|
||||
sendmail(removeUndefined(msg), err => {
|
||||
if (err) {
|
||||
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -12,8 +12,8 @@
|
||||
},
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.11",
|
||||
"sendmail": "^1.2.0"
|
||||
"sendmail": "^1.6.1",
|
||||
"strapi-utils": "3.0.0-beta.20.3"
|
||||
},
|
||||
"strapi": {
|
||||
"isProvider": true
|
||||
|
@ -21,6 +21,7 @@ const {
|
||||
getCommonBeginning,
|
||||
escapeQuery,
|
||||
} = require('./stringFormatting');
|
||||
const { removeUndefined } = require('./objectFormatting');
|
||||
const { getConfigUrls } = require('./config');
|
||||
|
||||
module.exports = {
|
||||
@ -41,4 +42,5 @@ module.exports = {
|
||||
getCommonBeginning,
|
||||
getConfigUrls,
|
||||
escapeQuery,
|
||||
removeUndefined,
|
||||
};
|
||||
|
9
packages/strapi-utils/lib/objectFormatting.js
Normal file
9
packages/strapi-utils/lib/objectFormatting.js
Normal file
@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const removeUndefined = obj => _.pickBy(obj, value => typeof value !== 'undefined');
|
||||
|
||||
module.exports = {
|
||||
removeUndefined,
|
||||
};
|
@ -16421,7 +16421,7 @@ send@0.17.1:
|
||||
range-parser "~1.2.1"
|
||||
statuses "~1.5.0"
|
||||
|
||||
sendmail@^1.2.0:
|
||||
sendmail@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/sendmail/-/sendmail-1.6.1.tgz#6be92fb4be70d1d9ad102030aeb1e737bd512159"
|
||||
integrity sha512-lIhvnjSi5e5jL8wA1GPP6j2QVlx6JOEfmdn0QIfmuJdmXYGmJ375kcOU0NSm/34J+nypm4sa1AXrYE5w3uNIIA==
|
||||
|
Loading…
x
Reference in New Issue
Block a user