Browse Source

Add new rule for sending email

pull/340/head
seamys 7 years ago
parent
commit
dbdf6331de
  1. 39
      extensions/Squidex.Extensions/Actions/Email/EmailAction.cs
  2. 74
      extensions/Squidex.Extensions/Actions/Email/EmailActionHandler.cs
  3. 22
      extensions/Squidex.Extensions/Actions/Email/EmailOptions.cs
  4. 3
      src/Squidex/AppServices.cs
  5. 1
      src/Squidex/app/features/rules/declarations.ts
  6. 4
      src/Squidex/app/features/rules/module.ts
  7. 58
      src/Squidex/app/features/rules/pages/rules/actions/email-action.component.html
  8. 5
      src/Squidex/app/features/rules/pages/rules/actions/email-action.component.scss
  9. 48
      src/Squidex/app/features/rules/pages/rules/actions/email-action.component.ts
  10. 7
      src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html

39
extensions/Squidex.Extensions/Actions/Email/EmailAction.cs

@ -0,0 +1,39 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.ComponentModel.DataAnnotations;
using Squidex.Domain.Apps.Core.Rules;
namespace Squidex.Extensions.Actions.Email
{
[RuleActionHandler(typeof(EmailActionHandler))]
[RuleAction(
IconImage = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><path d='M28 5h-24c-2.209 0-4 1.792-4 4v13c0 2.209 1.791 4 4 4h24c2.209 0 4-1.791 4-4v-13c0-2.208-1.791-4-4-4zM2 10.25l6.999 5.25-6.999 5.25v-10.5zM30 22c0 1.104-0.898 2-2 2h-24c-1.103 0-2-0.896-2-2l7.832-5.875 4.368 3.277c0.533 0.398 1.166 0.6 1.8 0.6 0.633 0 1.266-0.201 1.799-0.6l4.369-3.277 7.832 5.875zM30 20.75l-7-5.25 7-5.25v10.5zM17.199 18.602c-0.349 0.262-0.763 0.4-1.199 0.4s-0.851-0.139-1.2-0.4l-12.8-9.602c0-1.103 0.897-2 2-2h24c1.102 0 2 0.897 2 2l-12.801 9.602z'/></svg>",
IconColor = "#333300",
Display = "Send an email",
Description = "Send an email, when some contents has changed",
ReadMore = "https://en.wikipedia.org/wiki/Email")]
public class EmailAction : RuleAction
{
[Required]
[EmailAddress]
[Display(Name = "From", Description = "The mail is sent from?")]
public string From { get; set; }
[Required]
[Display(Name = "To", Description = "The email will be sent to?")]
public string To { get; set; }
[Required]
[Display(Name = "Subject", Description = "The email Subject")]
public string Subject { get; set; }
[Required]
[Display(Name = "Body", Description = "The email body")]
public string Body { get; set; }
}
}

74
extensions/Squidex.Extensions/Actions/Email/EmailActionHandler.cs

@ -0,0 +1,74 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Squidex.Domain.Apps.Core.HandleRules;
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents;
using Squidex.Infrastructure;
namespace Squidex.Extensions.Actions.Email
{
public sealed class EmailActionHandler : RuleActionHandler<EmailAction, EmailJob>
{
private const string Description = "Send an Email";
private readonly EmailOptions emailOptions;
public EmailActionHandler(RuleEventFormatter formatter, IOptions<EmailOptions> emailOptions)
: base(formatter)
{
Guard.NotNull(emailOptions, nameof(emailOptions));
this.emailOptions = emailOptions.Value;
}
protected override (string Description, EmailJob Data) CreateJob(EnrichedEvent @event, EmailAction action)
{
var ruleJob = new EmailJob
{
From = action.From,
To = action.To,
Subject = Format(action.Subject, @event),
Body = Format(action.Body, @event)
};
return (Description, ruleJob);
}
protected override async Task<(string Dump, Exception Exception)> ExecuteJobAsync(EmailJob job)
{
using (SmtpClient client = new SmtpClient(emailOptions.Host, emailOptions.Port))
{
client.EnableSsl = emailOptions.EnableSsl;
client.Credentials = new NetworkCredential(emailOptions.Username, emailOptions.Password);
using (var message = new MailMessage(job.From, job.To))
{
message.Subject = job.Subject;
message.Body = job.Body;
await client.SendMailAsync(message);
}
}
return ("Completed", null);
}
}
public class EmailJob
{
public string From { get; set; }
public string To { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
}

22
extensions/Squidex.Extensions/Actions/Email/EmailOptions.cs

@ -0,0 +1,22 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Extensions.Actions.Email
{
public sealed class EmailOptions
{
public string Host { get; set; }
public int Port { get; set; }
public bool EnableSsl { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
}

3
src/Squidex/AppServices.cs

@ -16,6 +16,7 @@ using Squidex.Config.Domain;
using Squidex.Config.Web;
using Squidex.Domain.Apps.Entities.Assets;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Extensions.Actions.Email;
using Squidex.Extensions.Actions.Twitter;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Diagnostics;
@ -56,6 +57,8 @@ namespace Squidex
config.GetSection("mode"));
services.Configure<TwitterOptions>(
config.GetSection("twitter"));
services.Configure<EmailOptions>(
config.GetSection("smtpServer"));
services.Configure<RobotsTxtOptions>(
config.GetSection("robots"));
services.Configure<GCHealthCheckOptions>(

1
src/Squidex/app/features/rules/declarations.ts

@ -9,6 +9,7 @@ export * from './pages/rules/actions/algolia-action.component';
export * from './pages/rules/actions/azure-queue-action.component';
export * from './pages/rules/actions/discourse-action.component';
export * from './pages/rules/actions/elastic-search-action.component';
export * from './pages/rules/actions/email-action.component';
export * from './pages/rules/actions/fastly-action.component';
export * from './pages/rules/actions/medium-action.component';
export * from './pages/rules/actions/prerender-action.component';

4
src/Squidex/app/features/rules/module.ts

@ -21,6 +21,7 @@ import {
ContentChangedTriggerComponent,
DiscourseActionComponent,
ElasticSearchActionComponent,
EmailActionComponent,
FastlyActionComponent,
MediumActionComponent,
PrerenderActionComponent,
@ -31,7 +32,7 @@ import {
RuleWizardComponent,
SlackActionComponent,
TweetActionComponent,
WebhookActionComponent
WebhookActionComponent,
} from './declarations';
const routes: Routes = [
@ -66,6 +67,7 @@ const routes: Routes = [
AzureQueueActionComponent,
ContentChangedTriggerComponent,
DiscourseActionComponent,
EmailActionComponent,
ElasticSearchActionComponent,
FastlyActionComponent,
MediumActionComponent,

58
src/Squidex/app/features/rules/pages/rules/actions/email-action.component.html

@ -0,0 +1,58 @@
<div [formGroup]="actionForm" class="form-horizontal">
<div class="form-group row">
<label class="col-3 col-form-label" for="from">From</label>
<div class="col-9">
<sqx-control-errors for="from" [submitted]="actionFormSubmitted"></sqx-control-errors>
<input type="text" class="form-control" id="from" formControlName="from" />
<small class="form-text text-muted">
The mail is sent from?
</small>
</div>
</div>
<div class="form-group row">
<label class="col-3 col-form-label" for="to">To</label>
<div class="col-9">
<sqx-control-errors for="to" [submitted]="actionFormSubmitted"></sqx-control-errors>
<input type="text" class="form-control" id="to" formControlName="to" />
<small class="form-text text-muted">
The email will be sent to?
</small>
</div>
</div>
<div class="form-group row">
<label class="col-3 col-form-label" for="subject">Subject</label>
<div class="col-9">
<sqx-control-errors for="subject" [submitted]="actionFormSubmitted"></sqx-control-errors>
<input type="text" class="form-control" id="subject" formControlName="subject" />
<small class="form-text text-muted">
The Email Subject.
</small>
</div>
</div>
<div class="form-group row">
<label class="col-3 col-form-label" for="body">Body</label>
<div class="col-9">
<sqx-control-errors for="body" [submitted]="actionFormSubmitted"></sqx-control-errors>
<textarea class="form-control" id="body" formControlName="body"></textarea>
<small class="form-text text-muted">
The Email body
</small>
</div>
</div>
</div>

5
src/Squidex/app/features/rules/pages/rules/actions/email-action.component.scss

@ -0,0 +1,5 @@
@import '_vars';
@import '_mixins';
textarea {
height: 250px;
}

48
src/Squidex/app/features/rules/pages/rules/actions/email-action.component.ts

@ -0,0 +1,48 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'sqx-email-action',
styleUrls: ['./email-action.component.scss'],
templateUrl: './email-action.component.html'
})
export class EmailActionComponent implements OnInit {
@Input()
public action: any;
@Input()
public actionForm: FormGroup;
@Input()
public actionFormSubmitted = false;
public ngOnInit() {
this.actionForm.setControl('from',
new FormControl(this.action.from || '', [
Validators.required,
Validators.email
]));
this.actionForm.setControl('to',
new FormControl(this.action.to || '', [
Validators.required
]));
this.actionForm.setControl('subject',
new FormControl(this.action.subject || '', [
Validators.required
]));
this.actionForm.setControl('body',
new FormControl(this.action.body || '', [
Validators.required
]));
}
}

7
src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html

@ -94,6 +94,13 @@
[actionFormSubmitted]="actionForm.submitted | async">
</sqx-elastic-search-action>
</ng-container>
<ng-container *ngSwitchCase="'Email'">
<sqx-email-action
[action]="action"
[actionForm]="actionForm.form"
[actionFormSubmitted]="actionForm.submitted | async">
</sqx-email-action>
</ng-container>
<ng-container *ngSwitchCase="'Fastly'">
<sqx-fastly-action
[action]="action"

Loading…
Cancel
Save