Webiant Logo Webiant Logo
  1. No results found.

    Try your search with a different keyword or use * as a wildcard.

EmailSender.cs

using MimeKit;
using MimeKit.Text;
using Nop.Core.Domain.Media;
using Nop.Core.Domain.Messages;
using Nop.Core.Infrastructure;
using Nop.Services.Media;

namespace Nop.Services.Messages;

/// 
/// Email sender
/// 
public partial class EmailSender : IEmailSender
{
    #region Fields

    protected readonly IDownloadService _downloadService;
    protected readonly INopFileProvider _fileProvider;
    protected readonly ISmtpBuilder _smtpBuilder;

    #endregion

    #region Ctor

    public EmailSender(IDownloadService downloadService, INopFileProvider fileProvider, ISmtpBuilder smtpBuilder)
    {
        _downloadService = downloadService;
        _fileProvider = fileProvider;
        _smtpBuilder = smtpBuilder;
    }

    #endregion

    #region Utilities

    /// 
    /// Create an file attachment for the specific download object from DB
    /// 
    /// Attachment download (another attachment)
    /// A leaf-node MIME part that contains an attachment.
    protected MimePart CreateMimeAttachment(Download download)
    {
        ArgumentNullException.ThrowIfNull(download);

        var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : download.Id.ToString();

        return CreateMimeAttachment($"{fileName}{download.Extension}", download.DownloadBinary, DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow);
    }

    /// 
    /// Create an file attachment for the specific file path
    /// 
    /// Attachment file path
    /// Attachment file name
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains a leaf-node MIME part that contains an attachment.
    /// 
    protected virtual async Task CreateMimeAttachmentAsync(string filePath, string attachmentFileName = null)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(filePath);

        if (string.IsNullOrWhiteSpace(attachmentFileName))
            attachmentFileName = Path.GetFileName(filePath);

        return CreateMimeAttachment(
            attachmentFileName,
            await _fileProvider.ReadAllBytesAsync(filePath),
            _fileProvider.GetCreationTime(filePath),
            _fileProvider.GetLastWriteTime(filePath),
            _fileProvider.GetLastAccessTime(filePath));
    }

    /// 
    /// Create an file attachment for the binary data
    /// 
    /// Attachment file name
    /// The array of unsigned bytes from which to create the attachment stream.
    /// Creation date and time for the specified file or directory
    /// Date and time that the specified file or directory was last written to
    /// Date and time that the specified file or directory was last access to.
    /// A leaf-node MIME part that contains an attachment.
    protected MimePart CreateMimeAttachment(string attachmentFileName, byte[] binaryContent, DateTime cDate, DateTime mDate, DateTime rDate)
    {
        if (!ContentType.TryParse(MimeTypes.GetMimeType(attachmentFileName), out var mimeContentType))
            mimeContentType = new ContentType("application", "octet-stream");

        return new MimePart(mimeContentType)
        {
            FileName = attachmentFileName,
            Content = new MimeContent(new MemoryStream(binaryContent)),
            ContentDisposition = new ContentDisposition
            {
                CreationDate = cDate,
                ModificationDate = mDate,
                ReadDate = rDate
            },
            ContentTransferEncoding = ContentEncoding.Base64
        };
    }

    #endregion

    #region Methods

    /// 
    /// Sends an email
    /// 
    /// Email account to use
    /// Subject
    /// Body
    /// From address
    /// From display name
    /// To address
    /// To display name
    /// ReplyTo address
    /// ReplyTo display name
    /// BCC addresses list
    /// CC addresses list
    /// Attachment file path
    /// Attachment file name. If specified, then this file name will be sent to a recipient. Otherwise, "AttachmentFilePath" name will be used.
    /// Attachment download ID (another attachment)
    /// Headers
    /// A task that represents the asynchronous operation
    public virtual async Task SendEmailAsync(EmailAccount emailAccount, string subject, string body,
        string fromAddress, string fromName, string toAddress, string toName,
        string replyTo = null, string replyToName = null,
        IEnumerable bcc = null, IEnumerable cc = null,
        string attachmentFilePath = null, string attachmentFileName = null,
        int attachedDownloadId = 0, IDictionary headers = null)
    {
        var message = new MimeMessage();

        message.From.Add(new MailboxAddress(fromName, fromAddress));
        message.To.Add(new MailboxAddress(toName, toAddress));

        if (!string.IsNullOrEmpty(replyTo))
        {
            message.ReplyTo.Add(new MailboxAddress(replyToName, replyTo));
        }

        //BCC
        if (bcc != null)
        {
            foreach (var address in bcc.Where(bccValue => !string.IsNullOrWhiteSpace(bccValue)))
            {
                message.Bcc.Add(new MailboxAddress("", address.Trim()));
            }
        }

        //CC
        if (cc != null)
        {
            foreach (var address in cc.Where(ccValue => !string.IsNullOrWhiteSpace(ccValue)))
            {
                message.Cc.Add(new MailboxAddress("", address.Trim()));
            }
        }

        //content
        message.Subject = subject;

        //headers
        if (headers != null)
            foreach (var header in headers)
            {
                message.Headers.Add(header.Key, header.Value);
            }

        var multipart = new Multipart("mixed")
        {
            new TextPart(TextFormat.Html) { Text = body }
        };

        //create the file attachment for this e-mail message
        if (!string.IsNullOrEmpty(attachmentFilePath) && _fileProvider.FileExists(attachmentFilePath))
        {
            multipart.Add(await CreateMimeAttachmentAsync(attachmentFilePath, attachmentFileName));
        }

        //another attachment?
        if (attachedDownloadId > 0)
        {
            var download = await _downloadService.GetDownloadByIdAsync(attachedDownloadId);
            //we do not support URLs as attachments
            if (!download?.UseDownloadUrl ?? false)
            {
                multipart.Add(CreateMimeAttachment(download));
            }
        }

        message.Body = multipart;

        //send email
        using var smtpClient = await _smtpBuilder.BuildAsync(emailAccount);
        await smtpClient.SendAsync(message);
        await smtpClient.DisconnectAsync(true);
    }

    #endregion
}