예제 #1
0
        /// <summary>
        /// Converts the SRC attribute of IMG tags into embedded content ids (cid).
        /// Example: &lt;img src="filename.jpg" /&lt; becomes &lt;img src="cid:unique-cid-jpg" /&lt;
        /// </summary>
        private void ReplaceImgSrcByCid()
        {
            var fileList = new List <string>();

            _tagHelper.TagName = "img";

            foreach (var element in _tagHelper.StartTags)
            {
                var srcAttr = _tagHelper.GetAttributeValue(element, "src");
                if (string.IsNullOrEmpty(srcAttr))
                {
                    continue;
                }

                // this will succeed only with local files (at this time, they don't need to exist yet)
                var filename = MakeFullPath(MakeLocalPath(srcAttr));
                try
                {
                    if (!fileList.Contains(filename))
                    {
                        var fileInfo    = new FileInfo(filename);
                        var contentType = MimeTypes.GetMimeType(filename);
                        var cid         = MimeUtils.GenerateMessageId();
                        InlineAtt.Add(new FileAttachment(filename, MakeCid(string.Empty, cid, new FileInfo(filename).Extension), contentType));
                        _tagHelper.ReplaceTag(element, _tagHelper.SetAttributeValue(element, "src", MakeCid("cid:", cid, fileInfo.Extension)));
                        fileList.Add(filename);
                    }
                }
                catch
                {
                    BadInlineFiles.Add(filename);
                    continue;
                }
            }
        }
        /// <summary>
        /// Gets the ready made body part for a mail message either
        /// - as TextPart, if there are no inline attachments
        /// - as MultipartRelated with a TextPart and one or more MimeParts of type inline attachments
        /// </summary>
        public override MimeEntity GetBodyPart()
        {
            ReplaceImgSrcByCid();
            var htmlTextPart = new TextPart("html")
            {
                ContentTransferEncoding = Tools.IsSevenBit(DocHtml)
                                        ? ContentEncoding.SevenBit
                                        : TextTransferEncoding != ContentEncoding.SevenBit
                                                ? TextTransferEncoding
                                                : ContentEncoding.QuotedPrintable,
            };

            htmlTextPart.SetText(CharacterEncoding, DocHtml);              // MimeKit.ContentType.Charset is set using CharacterEncodig
            htmlTextPart.ContentId = MimeUtils.GenerateMessageId();

            if (!InlineAtt.Any())
            {
                return(htmlTextPart);
            }

            /*
             *      multipart/related
             *      text/html
             *      image/jpeg
             *      image/png
             *      image/gif...
             */
            var mpr = new MultipartRelated {
                htmlTextPart
            };


            // Produce attachments as part of the multipart/related MIME part,
            // as described in RFC2387
            // Some older clients may need Inline Attachments instead of LinkedResources:
            // RFC2183: 2.1 The Inline Disposition Type
            // A bodypart should be marked `inline' if it is intended to be displayed automatically upon display of the message. Inline
            // bodyparts should be presented in the order in which they occur, subject to the normal semantics of multipart messages.
            foreach (var ia in InlineAtt)
            {
                try
                {
                    // create an inline image attachment for the file located at path
                    var attachment = new AttachmentBuilder(new FileAttachment(ia.Filename, ia.DisplayName, ia.MimeType), CharacterEncoding,
                                                           TextTransferEncoding, BinaryTransferEncoding).GetAttachment();
                    attachment.ContentDisposition = new MimeKit.ContentDisposition(MimeKit.ContentDisposition.Inline);

                    mpr.Add(attachment);
                }
                catch (FileNotFoundException)
                {
                    BadInlineFiles.Add(ia.Filename);
                }
                catch (IOException)
                {
                    BadInlineFiles.Add(ia.Filename);
                }
            }
            return(mpr);
        }
예제 #3
0
        /// <summary>
        /// Converts the SRC attribute of IMG tags into embedded content ids (cid).
        /// Example: &lt;img src="filename.jpg" /&lt; becomes &lt;img src="cid:unique-cid-jpg" /&lt;
        /// </summary>
        private void ReplaceImgSrcByCid()
        {
            var fileList = new Dictionary <string, string>();

            foreach (var element in _htmlDocument.All.Where(m => m is IHtmlImageElement))
            {
                var img     = (IHtmlImageElement)element;
                var currSrc = img.Attributes["src"]?.Value?.Trim();
                if (currSrc == null)
                {
                    continue;
                }

                // replace any placeholders with variables
                currSrc = _mailMergeMessage.SearchAndReplaceVars(currSrc, _dataItem);
                // Note: if currSrc is a rooted path, _docBaseUrl will be ignored
                var currSrcUri = new Uri(_docBaseUri, currSrc);

                // img src is not a local file (e.g. starting with "http" or is embedded base64 image), or manually included cid reference
                // so we just save the value with placeholders replaced
                if (string.IsNullOrEmpty(currSrc) || (currSrcUri.Scheme != UriScheme.File) ||
                    currSrc.StartsWith("data:image", StringComparison.OrdinalIgnoreCase) || currSrc.StartsWith("cid:", StringComparison.OrdinalIgnoreCase))
                {
                    // leave img.Attributes["src"].Value as it is
                    continue;
                }

                // this will succeed only with local files (at this time, they don't need to exist yet)
                var filename = _mailMergeMessage.SearchAndReplaceVarsInFilename(currSrcUri.LocalPath, _dataItem);
                try
                {
                    if (!fileList.ContainsKey(filename))
                    {
                        var fileInfo    = new FileInfo(filename);
                        var contentType = MimeTypes.GetMimeType(filename);
                        var cid         = MimeUtils.GenerateMessageId();
                        InlineAtt.Add(new FileAttachment(fileInfo.FullName, MakeCid(string.Empty, cid, fileInfo.Extension), contentType));
                        img.Attributes["src"].Value = MakeCid("cid:", cid, fileInfo.Extension);
                        fileList.Add(fileInfo.FullName, cid);
                    }
                    else
                    {
                        var cidForExistingFile = fileList[filename];
                        var fileInfo           = new FileInfo(filename);
                        img.Attributes["src"].Value = MakeCid("cid:", cidForExistingFile, fileInfo.Extension);
                    }
                }
                catch
                {
                    BadInlineFiles.Add(filename);
                    continue;
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Converts the SRC attribute of IMG tags into embedded content ids (cid).
        /// Example: &lt;img src="filename.jpg" /&lt; becomes &lt;img src="cid:unique-cid-jpg" /&lt;
        /// </summary>
        private void ReplaceImgSrcByCid()
        {
            var fileList = new HashSet <string>();

            foreach (var element in _htmlDocument.All.Where(m => m is IHtmlImageElement))
            {
                var img     = (IHtmlImageElement)element;
                var currSrc = img.Attributes["src"]?.Value;
                if (currSrc == null)
                {
                    continue;
                }

                // replace any placeholders with variables
                currSrc = _mailMergeMessage.SearchAndReplaceVars(currSrc, _dataItem);

                // img scr is not a local file (e.g. starting with "http"), so we just save the value with placeholders replaced
                if (!string.IsNullOrEmpty(currSrc) && !new Uri(MakeUri(currSrc)).IsFile)
                {
                    img.Attributes["src"].Value = currSrc;
                    continue;
                }

                // this will succeed only with local files (at this time, they don't need to exist yet)
                var filename = MakeFullPath(MakeLocalPath(currSrc));
                try
                {
                    if (!fileList.Contains(filename))
                    {
                        var fileInfo    = new FileInfo(filename);
                        var contentType = MimeTypes.GetMimeType(filename);
                        var cid         = MimeUtils.GenerateMessageId();
                        InlineAtt.Add(new FileAttachment(fileInfo.FullName, MakeCid(string.Empty, cid, fileInfo.Extension), contentType));

                        img.Attributes["src"].Value = MakeCid("cid:", cid, fileInfo.Extension);
                        fileList.Add(fileInfo.FullName);
                    }
                }
                catch
                {
                    BadInlineFiles.Add(filename);
                    continue;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Gets the ready made body part for a mail message either
        /// - as TextPart, if there are no inline attachments
        /// - as MultipartRelated with a TextPart and one or more MimeParts of type inline attachments
        /// </summary>
        public override MimeEntity GetBodyPart()
        {
            // remove all Script elements, because they cannot be used in mail messages
            foreach (var element in _htmlDocument.All.Where(e => e is IHtmlScriptElement).ToList())
            {
                element.Remove();
            }

            // set the HTML title tag from email subject
            var titleEle = _htmlDocument.All.FirstOrDefault(m => m is IHtmlTitleElement) as IHtmlTitleElement;

            if (titleEle != null)
            {
                titleEle.Text = _mailMergeMessage.SearchAndReplaceVars(_mailMergeMessage.Subject, _dataItem);
            }

            // read the <base href="..."> tag in order to find the embedded image files later on
            var baseEle = _htmlDocument.All.FirstOrDefault(m => m is IHtmlBaseElement) as IHtmlBaseElement;
            var baseDir = baseEle?.Href == null ? null : new Uri(baseEle.Href);

            // only replace the base url if it was not set programmatically
            if (_docBaseUri == null)
            {
                _docBaseUri = baseDir;
            }

            // remove if base tag is local file reference, because it's not usable in the resulting HTML
            if (baseEle != null && baseDir != null && baseDir.Scheme == UriScheme.File)
            {
                baseEle.Remove();
            }

            ReplaceImgSrcByCid();

            // replace placeholders only in the HTML Body, because e.g.
            // in the header there may be CSS definitions with curly brace which collide with SmartFormat {placeholders}
            _htmlDocument.Body.InnerHtml = _mailMergeMessage.SearchAndReplaceVars(_htmlDocument.Body.InnerHtml, _dataItem);

            var htmlTextPart = new TextPart("html")
            {
                ContentTransferEncoding = Tools.IsSevenBit(DocHtml)
                    ? ContentEncoding.SevenBit
                    : TextTransferEncoding != ContentEncoding.SevenBit
                        ? TextTransferEncoding
                        : ContentEncoding.QuotedPrintable,
            };

            htmlTextPart.SetText(CharacterEncoding, DocHtml);  // MimeKit.ContentType.Charset is set using CharacterEncoding
            htmlTextPart.ContentId = MimeUtils.GenerateMessageId();

            if (!InlineAtt.Any())
            {
                return(htmlTextPart);
            }

            /*
             *  multipart/related
             *  text/html
             *  image/jpeg
             *  image/png
             *  image/gif...
             */
            var mpr = new MultipartRelated {
                htmlTextPart
            };

            // Produce attachments as part of the multipart/related MIME part,
            // as described in RFC2387
            // Some older clients may need Inline Attachments instead of LinkedResources:
            // RFC2183: 2.1 The Inline Disposition Type
            // A bodypart should be marked `inline' if it is intended to be displayed automatically upon display of the message. Inline
            // bodyparts should be presented in the order in which they occur, subject to the normal semantics of multipart messages.
            foreach (var ia in InlineAtt)
            {
                try
                {
                    var readyInlineAtt = new FileAttachment(_mailMergeMessage.SearchAndReplaceVarsInFilename(ia.Filename, _dataItem), _mailMergeMessage.SearchAndReplaceVars(ia.DisplayName, _dataItem));
                    // create an inline image attachment for the file located at path
                    var attachment = new AttachmentBuilder(readyInlineAtt, CharacterEncoding,
                                                           TextTransferEncoding, BinaryTransferEncoding).GetAttachment();
                    attachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline);
                    attachment.ContentId          = ia.DisplayName;
                    attachment.FileName           = null; // not needed for inline attachments, save some space

                    mpr.Add(attachment);
                }
                catch (FileNotFoundException)
                {
                    BadInlineFiles.Add(ia.Filename);
                }
                catch (IOException)
                {
                    BadInlineFiles.Add(ia.Filename);
                }
            }
            return(mpr);
        }