/// <summary> /// Copy the plugin file to shadow copy directory /// </summary> /// <param name="pluginFilePath">Plugin file path</param> /// <param name="shadowCopyPlugFolder">Path to shadow copy folder</param> /// <returns>File path to shadow copy of plugin file</returns> private static string ShadowCopyFile(string pluginFilePath, string shadowCopyPlugFolder) { var shouldCopy = true; var shadowCopiedPlug = _fileProvider.Combine(shadowCopyPlugFolder, _fileProvider.GetFileName(pluginFilePath)); //check if a shadow copied file already exists and if it does, check if it's updated, if not don't copy if (_fileProvider.FileExists(shadowCopiedPlug)) { //it's better to use LastWriteTimeUTC, but not all file systems have this property //maybe it is better to compare file hash? var areFilesIdentical = _fileProvider.GetCreationTime(shadowCopiedPlug).ToUniversalTime().Ticks >= _fileProvider.GetCreationTime(pluginFilePath).ToUniversalTime().Ticks; if (areFilesIdentical) { Debug.WriteLine("Not copying; files appear identical: '{0}'", _fileProvider.GetFileName(shadowCopiedPlug)); shouldCopy = false; } else { //delete an existing file //More info: https://www.nopcommerce.com/boards/t/11511/access-error-nopplugindiscountrulesbillingcountrydll.aspx?p=4#60838 Debug.WriteLine("New plugin found; Deleting the old file: '{0}'", _fileProvider.GetFileName(shadowCopiedPlug)); _fileProvider.DeleteFile(shadowCopiedPlug); } } if (!shouldCopy) { return(shadowCopiedPlug); } try { _fileProvider.FileCopy(pluginFilePath, shadowCopiedPlug, true); } catch (IOException) { Debug.WriteLine(shadowCopiedPlug + " is locked, attempting to rename"); //this occurs when the files are locked, //for some reason devenv locks plugin files some times and for another crazy reason you are allowed to rename them //which releases the lock, so that it what we are doing here, once it's renamed, we can re-shadow copy try { var oldFile = shadowCopiedPlug + Guid.NewGuid().ToString("N") + ".old"; _fileProvider.FileMove(shadowCopiedPlug, oldFile); } catch (IOException exc) { throw new IOException(shadowCopiedPlug + " rename failed, cannot initialize plugin", exc); } //OK, we've made it this far, now retry the shadow copy _fileProvider.FileCopy(pluginFilePath, shadowCopiedPlug, true); } return(shadowCopiedPlug); }
/// <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> public virtual void SendEmail(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 MailMessage { //from, to, reply to From = new MailAddress(fromAddress, fromName) }; message.To.Add(new MailAddress(toAddress, toName)); if (!string.IsNullOrEmpty(replyTo)) { message.ReplyToList.Add(new MailAddress(replyTo, replyToName)); } //BCC if (bcc != null) { foreach (var address in bcc.Where(bccValue => !string.IsNullOrWhiteSpace(bccValue))) { message.Bcc.Add(address.Trim()); } } //CC if (cc != null) { foreach (var address in cc.Where(ccValue => !string.IsNullOrWhiteSpace(ccValue))) { message.CC.Add(address.Trim()); } } //content message.Subject = subject; message.Body = body; message.IsBodyHtml = true; //headers if (headers != null) { foreach (var header in headers) { message.Headers.Add(header.Key, header.Value); } } //create the file attachment for this e-mail message if (!string.IsNullOrEmpty(attachmentFilePath) && _fileProvider.FileExists(attachmentFilePath)) { var attachment = new Attachment(attachmentFilePath); attachment.ContentDisposition.CreationDate = _fileProvider.GetCreationTime(attachmentFilePath); attachment.ContentDisposition.ModificationDate = _fileProvider.GetLastWriteTime(attachmentFilePath); attachment.ContentDisposition.ReadDate = _fileProvider.GetLastAccessTime(attachmentFilePath); if (!string.IsNullOrEmpty(attachmentFileName)) { attachment.Name = attachmentFileName; } message.Attachments.Add(attachment); } //another attachment? if (attachedDownloadId > 0) { var download = _downloadService.GetDownloadById(attachedDownloadId); if (download != null) { //we do not support URLs as attachments if (!download.UseDownloadUrl) { var fileName = !string.IsNullOrWhiteSpace(download.Filename) ? download.Filename : download.Id.ToString(); fileName += download.Extension; var ms = new MemoryStream(download.DownloadBinary); var attachment = new Attachment(ms, fileName); //string contentType = !string.IsNullOrWhiteSpace(download.ContentType) ? download.ContentType : "application/octet-stream"; //var attachment = new Attachment(ms, fileName, contentType); attachment.ContentDisposition.CreationDate = DateTime.UtcNow; attachment.ContentDisposition.ModificationDate = DateTime.UtcNow; attachment.ContentDisposition.ReadDate = DateTime.UtcNow; message.Attachments.Add(attachment); } } } //send email using (var smtpClient = new SmtpClient()) { smtpClient.UseDefaultCredentials = emailAccount.UseDefaultCredentials; smtpClient.Host = emailAccount.Host; smtpClient.Port = emailAccount.Port; smtpClient.EnableSsl = emailAccount.EnableSsl; smtpClient.Credentials = emailAccount.UseDefaultCredentials ? CredentialCache.DefaultNetworkCredentials : new NetworkCredential(emailAccount.Username, emailAccount.Password); smtpClient.Send(message); } }