Files
Common-VS2019/SacsStandardBase/Base/Email/SaEmailConsole.cs
T
2024-08-20 17:51:51 +01:00

193 lines
7.1 KiB
C#

using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace Sarand.Net.Standard.Base.Email
{
//=======================================================================
public abstract class SaEmailConsole
{
//-------------------------------------------------------------------
// Protected construction.
protected SaEmailConsole()
{
}
//-------------------------------------------------------------------
// Send email.
//-------------------------------------------------------------------
public bool SendEmail(SaEmailData emailData)
{
// Validate email data.
if (emailData.AddressesTo.IsEmpty())
{
SaLogger.Error($"{SysUtil.Fn} Unable to send email - To address not specified.");
return false;
}
try
{
// Mail message.
MimeMessage mailMessage = CreateMailMessage(emailData);
// Send the email.
using (var smtpClient = new SmtpClient())
{
smtpClient.ServerCertificateValidationCallback = (s, c, h, e) => true;
smtpClient.Connect(emailData.Config.SMTP.Server, emailData.Config.SMTP.ServerPort, emailData.Config.SMTP.UseSSL ? SecureSocketOptions.StartTlsWhenAvailable : SecureSocketOptions.Auto);
if (!StringUtil.IsEmpty(emailData.Config.Send.UserName))
smtpClient.Authenticate(emailData.Config.Send.UserName, emailData.Config.Send.Password);
smtpClient.Send(mailMessage);
smtpClient.Disconnect(true);
}
}
catch (Exception exc)
{
SaLogger.Error($"{SysUtil.Fn} {ExceptionUtil.GetLogMessage(exc)}");
return false;
}
SaLogger.Info($"{SysUtil.Fn} Email sent to {emailData.AddressesTo[0]}. Subject: {emailData.Subject}");
return true;
}
//-------------------------------------------------------------------
private MimeMessage CreateMailMessage(SaEmailData emailData)
{
// Mail message.
MimeMessage mailMessage = new MimeMessage();
// Addresses.
mailMessage.From.Add(new MailboxAddress("", emailData.Config.Message.AddressFrom));
foreach (String addressTo in emailData.AddressesTo)
mailMessage.To.Add(new MailboxAddress("", addressTo));
foreach (String addressCc in emailData.AddressesCc)
mailMessage.Cc.Add(new MailboxAddress("", addressCc));
foreach (String addressBcc in emailData.AddressesBcc)
mailMessage.Bcc.Add(new MailboxAddress("", addressBcc));
foreach (String addressBcc in emailData.Config.Message.AddressesBcc)
mailMessage.Bcc.Add(new MailboxAddress("", addressBcc));
// Body builder.
var builder = new BodyBuilder();
// First add the message itself.
mailMessage.Subject = emailData.Subject;
if (emailData.HtmlBody)
builder.HtmlBody = emailData.MessageBody;
else
builder.TextBody = emailData.MessageBody;
// Attachments.
int attachmentCount = 0;
foreach (SaEmailAttachmentData attachmentData in emailData.Attachments)
{
attachmentCount++;
// Construct attachment.
MimePart attachment = new MimePart(attachmentData.ContentType.MediaType, attachmentData.ContentType.MediaSubtype)
{
Content = new MimeContent(new MemoryStream(attachmentData.Data)),
ContentDisposition = new ContentDisposition(attachmentData.Inline ? ContentDisposition.Inline : ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64
};
// All attachments should have a Filename.
attachment.FileName = attachmentData.Filename;
if (StringUtil.IsEmpty(attachment.FileName))
attachment.FileName = "Attachment_" + StringUtil.PadLeft(attachmentCount.ToString(), 3, '0') + ".dat";
// Inline attachments also have a ContentId.
if (attachmentData.Inline)
{
attachment.ContentId = attachmentData.ContentId;
if (StringUtil.IsEmpty(attachmentData.ContentId))
attachmentData.ContentId = "Attachment_" + StringUtil.PadLeft(attachmentCount.ToString(), 3, '0') + "@saxonite.com";
// Add the inline attachment as a linked resource.
builder.LinkedResources.Add(attachment);
}
else
{
// Add the attachment.
builder.Attachments.Add(attachment);
}
}
// Populate the message body.
mailMessage.Body = builder.ToMessageBody();
return mailMessage;
}
//-------------------------------------------------------------------
// Replace dynamic Email Body tags.
//-------------------------------------------------------------------
// Tags.
/// <summary>Check whether the body includes a specific tag.</summary>
public static bool EmailContainsTag(SaEmailData emailData, String tag)
{
return (Regex.Matches(emailData.MessageBody, Regex.Escape(tag), RegexOptions.IgnoreCase).Count > 0);
}
/// <summary>Replace a dynamic tag in the email message.</summary>
public static void ReplaceDynamicEmailTag(SaEmailData emailData, String tag, String content)
{
if (EmailContainsTag(emailData, tag))
emailData.MessageBody = Regex.Replace(emailData.MessageBody, Regex.Escape(tag), content ?? "", RegexOptions.IgnoreCase);
}
/// <summary>
/// Replace dynamic tags in email message that are known to the base project eg.:
/// <para>- stylesheet (including style tags).</para>
/// </summary>
public static void ReplaceDynamicEmailTags(SaEmailData emailData)
{
// Nothing to do.
}
//-------------------------------------------------------------------
protected void AddInlineImageToEmail(SaEmailData emailData, String imageResourceName, byte[] imageData, String imageType = "png")
{
string tag = "[#image." + imageResourceName + "]";
String imageFilename = Regex.Replace(imageResourceName, "_" + imageType, "." + imageType);
if (Regex.Matches(emailData.MessageBody, Regex.Escape(tag), RegexOptions.IgnoreCase).Count > 0)
{
String imageContentId = FormatAttachmentContentId(Regex.Replace(imageFilename, "\\.", "_"));
if (!emailData.Attachments.Exists(item => StringUtil.EmptyOnNull(item.ContentId).EqualsCI(imageContentId)))
{
// Image not yet in attachments.
SaEmailAttachmentData attachment = new SaEmailAttachmentData("image", imageResourceName)
{
Filename = imageFilename,
ContentId = imageContentId,
Data = imageData,
Inline = true
};
emailData.Attachments.Add(attachment);
}
String content = "cid:" + imageContentId;
emailData.MessageBody = Regex.Replace(emailData.MessageBody, Regex.Escape(tag), content, RegexOptions.IgnoreCase);
}
}
//-------------------------------------------------------------------
public static String FormatAttachmentContentId(String attachmentName)
{
// Inline content Ids should be formatted similar to an email address (user@domain).
// Replace '@' and whitespace with underscores and add domain.
String contentId = Regex.Replace(Regex.Replace(Regex.Replace(attachmentName, "@", "_"), "\\s+", "_"), "_+", "_") + "@saxonite.com";
return contentId;
}
//-------------------------------------------------------------------
}
//=======================================================================
}