Try your search with a different keyword or use * as a wildcard.
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;
/// <summary>
/// Email sender
/// </summary>
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
/// <summary>
/// Create an file attachment for the specific download object from DB
/// </summary>
/// <param name="download">Attachment download (another attachment)</param>
/// <returns>A leaf-node MIME part that contains an attachment.</returns>
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);
}
/// <summary>
/// Create an file attachment for the specific file path
/// </summary>
/// <param name="filePath">Attachment file path</param>
/// <param name="attachmentFileName">Attachment file name</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains a leaf-node MIME part that contains an attachment.
/// </returns>
protected virtual async Task<MimePart> 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));
}
/// <summary>
/// Create an file attachment for the binary data
/// </summary>
/// <param name="attachmentFileName">Attachment file name</param>
/// <param name="binaryContent">The array of unsigned bytes from which to create the attachment stream.</param>
/// <param name="cDate">Creation date and time for the specified file or directory</param>
/// <param name="mDate">Date and time that the specified file or directory was last written to</param>
/// <param name="rDate">Date and time that the specified file or directory was last access to.</param>
/// <returns>A leaf-node MIME part that contains an attachment.</returns>
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
/// <summary>
/// Sends an email
/// </summary>
/// <param name="emailAccount">Email account to use</param>
/// <param name="subject">Subject</param>
/// <param name="body">Body</param>
/// <param name="fromAddress">From address</param>
/// <param name="fromName">From display name</param>
/// <param name="toAddress">To address</param>
/// <param name="toName">To display name</param>
/// <param name="replyTo">ReplyTo address</param>
/// <param name="replyToName">ReplyTo display name</param>
/// <param name="bcc">BCC addresses list</param>
/// <param name="cc">CC addresses list</param>
/// <param name="attachmentFilePath">Attachment file path</param>
/// <param name="attachmentFileName">Attachment file name. If specified, then this file name will be sent to a recipient. Otherwise, "AttachmentFilePath" name will be used.</param>
/// <param name="attachedDownloadId">Attachment download ID (another attachment)</param>
/// <param name="headers">Headers</param>
/// <returns>A task that represents the asynchronous operation</returns>
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<string> bcc = null, IEnumerable<string> cc = null,
string attachmentFilePath = null, string attachmentFileName = null,
int attachedDownloadId = 0, IDictionary<string, string> 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 email 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
}