// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.ComponentModel.DataAnnotations;
using MailKit.Net.Smtp;
using MimeKit;
using MimeKit.Text;
using Squidex.Domain.Apps.Core.Rules.Deprecated;
using Squidex.Flows;
using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.Validation;
namespace Squidex.Extensions.Actions.Email;
[FlowStep(
Title = "Email",
IconImage = "",
IconColor = "#333300",
Display = "Send an email",
Description = "Send an email with a custom SMTP server.",
ReadMore = "https://en.wikipedia.org/wiki/Email")]
#pragma warning disable CS0618 // Type or member is obsolete
internal sealed record EmailFlowStep : FlowStep, IConvertibleToAction
#pragma warning restore CS0618 // Type or member is obsolete
{
[LocalizedRequired]
[Display(Name = "Server Host", Description = "The IP address or host to the SMTP server.")]
[Editor(FlowStepEditor.Text)]
public string ServerHost { get; set; }
[LocalizedRequired]
[Display(Name = "Server Port", Description = "The port to the SMTP server.")]
[Editor(FlowStepEditor.Text)]
public int ServerPort { get; set; }
[Display(Name = "Username", Description = "The username for the SMTP server.")]
[Editor(FlowStepEditor.Text)]
[Expression]
public string ServerUsername { get; set; }
[Display(Name = "Password", Description = "The password for the SMTP server.")]
[Editor(FlowStepEditor.Password)]
public string ServerPassword { get; set; }
[LocalizedRequired]
[Display(Name = "From Address", Description = "The email sending address.")]
[Editor(FlowStepEditor.Text)]
[Expression]
public string MessageFrom { get; set; }
[LocalizedRequired]
[Display(Name = "To Address", Description = "The email message will be sent to.")]
[Editor(FlowStepEditor.Text)]
[Expression]
public string MessageTo { get; set; }
[LocalizedRequired]
[Display(Name = "Subject", Description = "The subject line for this email message.")]
[Editor(FlowStepEditor.Text)]
[Expression]
public string MessageSubject { get; set; }
[LocalizedRequired]
[Display(Name = "Body", Description = "The message body.")]
[Editor(FlowStepEditor.TextArea)]
[Expression]
public string MessageBody { get; set; }
public override async ValueTask ExecuteAsync(FlowExecutionContext executionContext,
CancellationToken ct)
{
if (executionContext.IsSimulation)
{
executionContext.LogSkipSimulation();
return Next();
}
using var smtpClient = new SmtpClient();
await smtpClient.ConnectAsync(ServerHost, ServerPort, cancellationToken: ct);
if (!string.IsNullOrWhiteSpace(ServerUsername) && !string.IsNullOrWhiteSpace(ServerPassword))
{
await smtpClient.AuthenticateAsync(ServerUsername, ServerPassword, ct);
}
var smtpMessage = new MimeMessage
{
Body = new TextPart(TextFormat.Html)
{
Text = MessageBody,
},
Subject = MessageSubject,
};
smtpMessage.From.Add(MailboxAddress.Parse(
MessageFrom));
smtpMessage.To.Add(MailboxAddress.Parse(
MessageTo));
await smtpClient.SendAsync(smtpMessage, ct);
executionContext.Log($"Email sent to {MessageTo}");
return Next();
}
#pragma warning disable CS0618 // Type or member is obsolete
public RuleAction ToAction()
{
return SimpleMapper.Map(this, new EmailAction());
}
#pragma warning restore CS0618 // Type or member is obsolete
}