Stores all MIME decoded information of a received email. One email might consist of several MIME entities, which have a very similar structure to an email. A RxMailMessage can be a top most level email or a MIME entity the emails contains. According to various RFCs, MIME entities can contain other MIME entities recursively. However, they usually need to be mapped to alternative views and attachments, which are non recursive. MailMessageParser inherits from System.Net.MailMessage, but provides additional receiving related information.
Inheritance: System.Net.Mail.MailMessage
Exemple #1
0
        /// <summary>
        /// Add all attachments and alternative views from child to the parent
        /// </summary>
        /// <param name="child">child Object</param>
        /// <param name="parent">parent Object</param>
        private static void AddChildPartsToParent(MailMessageParser child, MailMessageParser parent)
        {
            ////add the child itself to the parent
            parent.Entities.Add(child);

            ////add the alternative views of the child to the parent
            if (null != child.AlternateViews)
            {
                foreach (AlternateView childView in child.AlternateViews)
                {
                    parent.AlternateViews.Add(childView);
                }
            }

            ////add the body of the child as alternative view to parent
            ////this should be the last view attached here, because the POP 3 MIME client
            ////is supposed to display the last alternative view
            if (child.MediaMainType == ServiceConstants.TEXT_MEDIA_MAIN_TYPE && null != child.ContentStream && null != child.Parent.ContentType && child.Parent.ContentType.MediaType.ToUpperInvariant() == ServiceConstants.MULTI_PART_MEDIA_TYPE)
            {
                AlternateView thisAlternateView = new AlternateView(child.ContentStream);
                thisAlternateView.ContentId        = RemoveBrackets(child.ContentId);
                thisAlternateView.ContentType      = child.ContentType;
                thisAlternateView.TransferEncoding = child.ContentTransferEncoding;
                parent.AlternateViews.Add(thisAlternateView);
            }

            ////add the attachments of the child to the parent
            if (null != child.Attachments)
            {
                foreach (Attachment childAttachment in child.Attachments)
                {
                    parent.Attachments.Add(childAttachment);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Copies the content found for the MIME entity to the MailMessageParser body and creates
        /// a stream which can be used to create attachments and alternative views.
        /// </summary>
        /// <param name="message">Parsed mail message</param>
        /// <param name="contentString">mail content string</param>
        private static void SaveMessageBody(MailMessageParser message, string contentString)
        {
            message.Body = contentString;
            System.Text.Encoding ascii      = System.Text.Encoding.ASCII;
            MemoryStream         bodyStream = new MemoryStream(ascii.GetBytes(contentString), 0, contentString.Length);

            message.ContentStream = bodyStream;
        }
        /// <summary>
        /// Creates an empty child MIME entity from the parent MIME entity.
        /// An email can consist of several MIME entities. A entity has the same structure of email.
        /// </summary>
        /// <returns>Mail message child object</returns>
        public MailMessageParser CreateChildEntity()
        {
            MailMessageParser child = new MailMessageParser();

            child.Parent    = this;
            child.TopParent = this.TopParent;
            child.ContentTransferEncoding = this.ContentTransferEncoding;
            return(child);
        }
Exemple #4
0
        /// <summary>
        /// Gets an email from the supplied Email Stream and processes it.
        /// </summary>
        /// <param name="mailPath">string that designates the path to a .EML file</param>
        /// <returns>MailMessageParser or null if email not properly formatted</returns>
        public MailMessageParser GetEmail(string mailPath)
        {
            MailMessageParser messageParser = null;

            using (Stream emailStream = File.Open(mailPath, FileMode.Open))
            {
                messageParser = this.GetEmail(emailStream);
            }

            return(messageParser);
        }
        /// <summary>
        /// Creates Mail message object from file.
        /// </summary>
        /// <param name="mimeDecoder">read MIME object</param>
        /// <param name="mailPath">EML file path.</param>
        /// <returns>Mime decoded email object</returns>
        public static MailMessageParser CreateFromFile(MailMimeReader mimeDecoder, string mailPath)
        {
            MailMessageParser result = null;

            if (null != mimeDecoder)
            {
                result = mimeDecoder.GetEmail(mailPath);
            }
            else
            {
                result = null;
            }
            return(result);
        }
        /// <summary>
        /// Creates Mail message object from stream.
        /// </summary>
        /// <param name="mimeDecoder">read MIME object</param>
        /// <param name="emailStream">The email stream.</param>
        /// <returns>Mime decoded email object</returns>
        public static MailMessageParser CreateFromStream(MailMimeReader mimeDecoder, Stream emailStream)
        {
            MailMessageParser result = null;

            if (mimeDecoder != null)
            {
                result = mimeDecoder.GetEmail(emailStream);
            }
            else
            {
                result = null;
            }
            return(result);
        }
Exemple #7
0
        /// <summary>
        /// Processes the delimited body of Mail Mime Entity.
        /// </summary>
        /// <param name="message">Parsed Mail Message.</param>
        /// <param name="boundaryStart">boundary start identifier</param>
        /// <param name="parentBoundaryStart">parent boundary start identifier</param>
        /// <param name="parentBoundaryEnd">parent boundary end identifier</param>
        /// <returns>MimeEntity process result code</returns>
        private MimeEntityReturnCode ProcessDelimitedBody(MailMessageParser message, string boundaryStart, string parentBoundaryStart, string parentBoundaryEnd)
        {
            string response;

            if (boundaryStart.Trim() == parentBoundaryStart.Trim())
            {
                while (this.ReadMultipleLine(out response))
                {
                    continue;
                }

                return(MimeEntityReturnCode.problem);
            }

            MimeEntityReturnCode returnCode;

            do
            {
                this.mimeEntitySB.Length = 0;
                MailMessageParser childPart = message.CreateChildEntity();

                ////recursively call MIME part processing
                returnCode = this.ProcessMimeEntity(childPart, boundaryStart);

                if (returnCode == MimeEntityReturnCode.problem)
                {
                    return(MimeEntityReturnCode.problem);
                }

                ////add the newly found child MIME part to the parent
                AddChildPartsToParent(childPart, message);
            }while (returnCode != MimeEntityReturnCode.parentBoundaryEndFound);

            MimeEntityReturnCode boundaryMimeReturnCode;
            bool hasParentBoundary = parentBoundaryStart.Length > 0;

            while (this.ReadMultipleLine(out response))
            {
                if (hasParentBoundary && ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
                {
                    return(boundaryMimeReturnCode);
                }
            }

            return(MimeEntityReturnCode.bodyComplete);
        }
Exemple #8
0
        /// <summary>
        /// each attachment is stored in its own MIME entity and read into this entity's
        /// ContentStream. SaveAttachment creates an attachment out of the ContentStream
        /// and attaches it to the parent MIME entity.
        /// </summary>
        /// <param name="message">Parsed mail message</param>
        private static void SaveAttachment(MailMessageParser message)
        {
            if (null != message.Parent)
            {
                Attachment thisAttachment = new Attachment(message.ContentStream, message.ContentType);

                if (null != message.ContentDisposition)
                {
                    ContentDisposition messageContentDisposition    = message.ContentDisposition;
                    ContentDisposition attachmentContentDisposition = thisAttachment.ContentDisposition;
                    if (messageContentDisposition.CreationDate > DateTime.MinValue)
                    {
                        attachmentContentDisposition.CreationDate = messageContentDisposition.CreationDate;
                    }

                    attachmentContentDisposition.DispositionType = messageContentDisposition.DispositionType;
                    attachmentContentDisposition.FileName        = messageContentDisposition.FileName;
                    attachmentContentDisposition.Inline          = messageContentDisposition.Inline;
                    if (messageContentDisposition.ModificationDate > DateTime.MinValue)
                    {
                        attachmentContentDisposition.ModificationDate = messageContentDisposition.ModificationDate;
                    }

                    if (messageContentDisposition.ReadDate > DateTime.MinValue)
                    {
                        attachmentContentDisposition.ReadDate = messageContentDisposition.ReadDate;
                    }

                    if (0 < messageContentDisposition.Size)
                    {
                        attachmentContentDisposition.Size = messageContentDisposition.Size;
                    }
                }

                string contentIdString = message.ContentId;
                if (null != contentIdString)
                {
                    thisAttachment.ContentId = RemoveBrackets(contentIdString);
                }

                thisAttachment.TransferEncoding = message.ContentTransferEncoding;
                message.Parent.Attachments.Add(thisAttachment);
            }
        }
Exemple #9
0
        /// <summary>
        /// Gets an email from the supplied Email Stream and processes it.
        /// </summary>
        /// <param name="emailStream">The email stream object</param>
        /// <returns>
        /// MailMessageParser or null if email not properly formatted
        /// </returns>
        public MailMessageParser GetEmail(Stream emailStream)
        {
            this.EmailStreamReader = new StreamReader(emailStream, Encoding.ASCII);

            ////prepare message, set defaults as specified in RFC 2046
            MailMessageParser message = new MailMessageParser();

            message.ContentTransferEncoding = TransferEncoding.SevenBit;
            MailMessageParser    result = null;
            MimeEntityReturnCode messageMimeReturnCode = this.ProcessMimeEntity(message, string.Empty);

            if (messageMimeReturnCode == MimeEntityReturnCode.bodyComplete || messageMimeReturnCode == MimeEntityReturnCode.parentBoundaryEndFound)
            {
                if (0 == message.To.Count)
                {
                    string toField = message.Headers[ServiceConstants.Mail_Message_Receiver_Header];
                    if (!string.IsNullOrEmpty(toField))
                    {
                        message.To.Add(toField);
                    }
                }

                if (null == message.From)
                {
                    string mailFrom = message.Headers[ServiceConstants.Mail_Message_Sender_Header];
                    if (!string.IsNullOrEmpty(mailFrom))
                    {
                        message.From = new MailAddress(mailFrom);
                    }
                }

                result = message;
            }

            return(result);
        }
Exemple #10
0
        /// <summary>
        /// Processes the delimited body of Mail Mime Entity.
        /// </summary>
        /// <param name="message">Parsed Mail Message.</param>
        /// <param name="boundaryStart">boundary start identifier</param>
        /// <param name="parentBoundaryStart">parent boundary start identifier</param>
        /// <param name="parentBoundaryEnd">parent boundary end identifier</param>
        /// <returns>MimeEntity process result code</returns>
        private MimeEntityReturnCode ProcessDelimitedBody(MailMessageParser message, string boundaryStart, string parentBoundaryStart, string parentBoundaryEnd)
        {
            string response;

            if (boundaryStart.Trim() == parentBoundaryStart.Trim())
            {
                while (this.ReadMultipleLine(out response))
                {
                    continue;
                }

                return MimeEntityReturnCode.problem;
            }

            MimeEntityReturnCode returnCode;
            do
            {
                this.mimeEntitySB.Length = 0;
                MailMessageParser childPart = message.CreateChildEntity();

                ////recursively call MIME part processing
                returnCode = this.ProcessMimeEntity(childPart, boundaryStart);

                if (returnCode == MimeEntityReturnCode.problem)
                {
                    return MimeEntityReturnCode.problem;
                }

                ////add the newly found child MIME part to the parent
                AddChildPartsToParent(childPart, message);
            }
            while (returnCode != MimeEntityReturnCode.parentBoundaryEndFound);

            MimeEntityReturnCode boundaryMimeReturnCode;
            bool hasParentBoundary = parentBoundaryStart.Length > 0;
            while (this.ReadMultipleLine(out response))
            {
                if (hasParentBoundary && ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
                {
                    return boundaryMimeReturnCode;
                }
            }

            return MimeEntityReturnCode.bodyComplete;
        }
Exemple #11
0
        /// <summary>
        /// Add all attachments and alternative views from child to the parent
        /// </summary>
        /// <param name="child">child Object</param>
        /// <param name="parent">parent Object</param>
        private static void AddChildPartsToParent(MailMessageParser child, MailMessageParser parent)
        {
            ////add the child itself to the parent
            parent.Entities.Add(child);

            ////add the alternative views of the child to the parent
            if (null != child.AlternateViews)
            {
                foreach (AlternateView childView in child.AlternateViews)
                {
                    parent.AlternateViews.Add(childView);
                }
            }

            ////add the body of the child as alternative view to parent
            ////this should be the last view attached here, because the POP 3 MIME client
            ////is supposed to display the last alternative view
            if (child.MediaMainType == ServiceConstants.TEXT_MEDIA_MAIN_TYPE && null != child.ContentStream && null != child.Parent.ContentType && child.Parent.ContentType.MediaType.ToUpperInvariant() == ServiceConstants.MULTI_PART_MEDIA_TYPE)
            {
                AlternateView thisAlternateView = new AlternateView(child.ContentStream);
                thisAlternateView.ContentId = RemoveBrackets(child.ContentId);
                thisAlternateView.ContentType = child.ContentType;
                thisAlternateView.TransferEncoding = child.ContentTransferEncoding;
                parent.AlternateViews.Add(thisAlternateView);
            }

            ////add the attachments of the child to the parent
            if (null != child.Attachments)
            {
                foreach (Attachment childAttachment in child.Attachments)
                {
                    parent.Attachments.Add(childAttachment);
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// each attachment is stored in its own MIME entity and read into this entity's
        /// ContentStream. SaveAttachment creates an attachment out of the ContentStream
        /// and attaches it to the parent MIME entity.
        /// </summary>
        /// <param name="message">Parsed mail message</param>
        private static void SaveAttachment(MailMessageParser message)
        {
            if (null != message.Parent)
            {
                Attachment thisAttachment = new Attachment(message.ContentStream, message.ContentType);

                if (null != message.ContentDisposition)
                {
                    ContentDisposition messageContentDisposition = message.ContentDisposition;
                    ContentDisposition attachmentContentDisposition = thisAttachment.ContentDisposition;
                    if (messageContentDisposition.CreationDate > DateTime.MinValue)
                    {
                        attachmentContentDisposition.CreationDate = messageContentDisposition.CreationDate;
                    }

                    attachmentContentDisposition.DispositionType = messageContentDisposition.DispositionType;
                    attachmentContentDisposition.FileName = messageContentDisposition.FileName;
                    attachmentContentDisposition.Inline = messageContentDisposition.Inline;
                    if (messageContentDisposition.ModificationDate > DateTime.MinValue)
                    {
                        attachmentContentDisposition.ModificationDate = messageContentDisposition.ModificationDate;
                    }

                    if (messageContentDisposition.ReadDate > DateTime.MinValue)
                    {
                        attachmentContentDisposition.ReadDate = messageContentDisposition.ReadDate;
                    }

                    if (0 < messageContentDisposition.Size)
                    {
                        attachmentContentDisposition.Size = messageContentDisposition.Size;
                    }
                }

                string contentIdString = message.ContentId;
                if (null != contentIdString)
                {
                    thisAttachment.ContentId = RemoveBrackets(contentIdString);
                }

                thisAttachment.TransferEncoding = message.ContentTransferEncoding;
                message.Parent.Attachments.Add(thisAttachment);
            }
        }
Exemple #13
0
 /// <summary>
 /// Copies the content found for the MIME entity to the MailMessageParser body and creates
 /// a stream which can be used to create attachments and alternative views.
 /// </summary>
 /// <param name="message">Parsed mail message</param>
 /// <param name="contentString">mail content string</param>
 private static void SaveMessageBody(MailMessageParser message, string contentString)
 {
     message.Body = contentString;
     System.Text.Encoding ascii = System.Text.Encoding.ASCII;
     MemoryStream bodyStream = new MemoryStream(ascii.GetBytes(contentString), 0, contentString.Length);
     message.ContentStream = bodyStream;
 }
Exemple #14
0
        /// <summary>
        /// Gets an email from the supplied Email Stream and processes it.
        /// </summary>
        /// <param name="emailStream">The email stream object</param>
        /// <returns>
        /// MailMessageParser or null if email not properly formatted
        /// </returns>
        public MailMessageParser GetEmail(Stream emailStream)
        {
            this.EmailStreamReader = new StreamReader(emailStream, Encoding.ASCII);

            ////prepare message, set defaults as specified in RFC 2046
            MailMessageParser message = new MailMessageParser();
            message.ContentTransferEncoding = TransferEncoding.SevenBit;
            MailMessageParser result = null;
            MimeEntityReturnCode messageMimeReturnCode = this.ProcessMimeEntity(message, string.Empty);

            if (messageMimeReturnCode == MimeEntityReturnCode.bodyComplete || messageMimeReturnCode == MimeEntityReturnCode.parentBoundaryEndFound)
            {
                if (0 == message.To.Count)
                {
                    string toField = message.Headers[ServiceConstants.Mail_Message_Receiver_Header];
                    if (!string.IsNullOrEmpty(toField))
                    {
                        message.To.Add(toField);
                    }
                }

                if (null == message.From)
                {
                    string mailFrom = message.Headers[ServiceConstants.Mail_Message_Sender_Header];
                    if (!string.IsNullOrEmpty(mailFrom))
                    {
                        message.From = new MailAddress(mailFrom);
                    }
                }

                result = message;
            }

            return result;
        }
 /// <summary>
 /// Creates an empty child MIME entity from the parent MIME entity.        
 /// An email can consist of several MIME entities. A entity has the same structure of email.    
 /// </summary>
 /// <returns>Mail message child object</returns>
 public MailMessageParser CreateChildEntity()
 {
     MailMessageParser child = new MailMessageParser();
     child.Parent = this;
     child.TopParent = this.TopParent;
     child.ContentTransferEncoding = this.ContentTransferEncoding;
     return child;
 }
        /// <summary>
        /// Gets the uploaded email file properties....
        /// </summary>
        /// <param name="fileStream">The file stream.</param>
        /// <param name="mailProperties">The mail properties.</param>
        /// <returns>Dictionary string key value pair for mail properties</returns>
        public static Dictionary <string, string> GetMailFileProperties(System.IO.Stream fileStream, Dictionary <string, string> mailProperties)
        {
            if (null != mailProperties && mailProperties.ContainsKey(ServiceConstants.MAIL_FILE_EXTENSION_KEY))
            {
                if (string.Equals(mailProperties[ServiceConstants.MAIL_FILE_EXTENSION_KEY], ServiceConstants.EMAIL_FILE_EXTENSION, StringComparison.OrdinalIgnoreCase))
                {
                    MailMimeReader    mime            = new MailMimeReader();
                    MailMessageParser messageParser   = mime.GetEmail(fileStream);
                    string            fromDisplayName = Convert.ToString(messageParser.From.DisplayName, CultureInfo.InvariantCulture);
                    mailProperties[ServiceConstants.MAIL_SENDER_KEY]           = String.Concat(Convert.ToString(messageParser.From.Address, CultureInfo.InvariantCulture), ServiceConstants.SEMICOLON, fromDisplayName.Replace(Convert.ToString(messageParser.From.Address, CultureInfo.InvariantCulture), string.Empty).Replace(ServiceConstants.OPENING_BRACKET + ServiceConstants.CLOSING_BRACKET, string.Empty));
                    mailProperties[ServiceConstants.MAIL_SEARCH_EMAIL_SUBJECT] = messageParser.Subject;
                    mailProperties[ServiceConstants.MAIL_SENT_DATE_KEY]        = Convert.ToString(messageParser.DeliveryDate, CultureInfo.InvariantCulture);
                    mailProperties[ServiceConstants.MAIL_RECEIVED_DATEKEY]     = Convert.ToString(messageParser.ReceivedDate, CultureInfo.InvariantCulture);
                    mailProperties[ServiceConstants.MAIL_ORIGINAL_NAME]        = messageParser.Subject;
                    StringBuilder mailReceiver   = new StringBuilder();
                    StringBuilder mailCCAddress  = new StringBuilder();
                    StringBuilder attachmentName = new StringBuilder();

                    foreach (MailAddress toItem in messageParser.To)
                    {
                        string toMailAlias = Convert.ToString(toItem.Address, CultureInfo.InvariantCulture);
                        string toMailName  = Convert.ToString(toItem.DisplayName, CultureInfo.InvariantCulture);
                        if (toMailName.Contains(toMailAlias))
                        {
                            toMailName = toMailName.Replace(toMailAlias, string.Empty).Replace(ServiceConstants.OPENING_BRACKET + ServiceConstants.CLOSING_BRACKET, string.Empty);
                        }

                        mailReceiver.Append(toMailAlias + ServiceConstants.SEMICOLON + toMailName + ServiceConstants.SEMICOLON);
                    }

                    mailProperties[ServiceConstants.MAIL_RECEIVER_KEY] = Convert.ToString(mailReceiver, CultureInfo.InvariantCulture);

                    foreach (MailAddress itemCC in messageParser.CC)
                    {
                        string mailCCAlias = Convert.ToString(itemCC.Address, CultureInfo.InvariantCulture);
                        string mailCCName  = Convert.ToString(itemCC.DisplayName, CultureInfo.InvariantCulture);
                        if (mailCCName.Contains(mailCCAlias))
                        {
                            mailCCName = mailCCName.Replace(mailCCAlias, string.Empty).Replace(ServiceConstants.OPENING_BRACKET + ServiceConstants.CLOSING_BRACKET, string.Empty);
                        }

                        mailCCAddress.Append(mailCCAlias + ServiceConstants.SEMICOLON + mailCCName + ServiceConstants.SEMICOLON);
                    }

                    mailProperties[ServiceConstants.MAIL_CC_ADDRESS_KEY] = Convert.ToString(mailCCAddress, CultureInfo.InvariantCulture);

                    foreach (System.Net.Mail.Attachment itemAttachment in messageParser.Attachments)
                    {
                        if (!string.IsNullOrWhiteSpace(itemAttachment.Name))
                        {
                            attachmentName.Append(itemAttachment.Name + ServiceConstants.SEMICOLON);
                        }
                    }

                    for (int mailEntitiesCount = 0; mailEntitiesCount < messageParser.Entities.Count; mailEntitiesCount++)
                    {
                        if (string.Equals(messageParser.Entities[mailEntitiesCount].MediaMainType, ServiceConstants.MAIL_ATTACHMENT_MEDIA_MAINT_YPE, StringComparison.CurrentCultureIgnoreCase))
                        {
                            attachmentName.Append(messageParser.Entities[mailEntitiesCount].ContentDescription + ServiceConstants.SEMICOLON);
                        }
                    }

                    mailProperties[ServiceConstants.MAIL_ATTACHMENT_KEY] = Convert.ToString(attachmentName, CultureInfo.InvariantCulture);

                    // Setting email importance
                    mailProperties[ServiceConstants.MAIL_IMPORTANCE_KEY] = (!string.IsNullOrWhiteSpace(messageParser.MailImportance) ? messageParser.MailImportance : ServiceConstants.MAIL_DEFAULT_IMPORTANCE);

                    // Setting email categories
                    mailProperties[ServiceConstants.MAIL_CATEGORIES_KEY] = (!string.IsNullOrWhiteSpace(messageParser.MailCategories) ? messageParser.MailCategories.Replace(ServiceConstants.COMMA, ServiceConstants.SEMICOLON) : string.Empty);
                }
            }

            return(mailProperties);
        }
Exemple #17
0
        /// <summary>
        /// Process a MIME entity
        /// A MIME entity consists of header and body.
        /// Separator lines in the body might mark children MIME entities
        /// </summary>
        /// <param name="message">Mail Message.</param>
        /// <param name="parentBoundaryStart">The parent boundary start value</param>
        /// <returns>Mime entity return code for parsed mail message</returns>
        private MimeEntityReturnCode ProcessMimeEntity(MailMessageParser message, string parentBoundaryStart)
        {
            bool hasParentBoundary = parentBoundaryStart.Length > 0;
            string parentBoundaryEnd = parentBoundaryStart + ServiceConstants.HYPHEN + ServiceConstants.HYPHEN;
            MimeEntityReturnCode boundaryMimeReturnCode;

            ////some format fields are inherited from parent, only the default for
            ////ContentType needs to be set here, otherwise the boundary parameter would be
            ////inherited as well
            message.SetContentTypeFields(ServiceConstants.MAIL_CONTENT_TYPE);
            string completeHeaderField = null;     ////consists of one start line and possibly several continuation lines
            string response;

            //// read header lines until empty line is found (end of header)
            while (true)
            {
                if (!this.ReadMultipleLine(out response))
                {
                    while (this.ReadMultipleLine(out response))
                    {
                        continue;
                    }

                    return MimeEntityReturnCode.problem;
                }

                if (1 > response.Length)
                {
                    ////empty line found => end of header
                    if (completeHeaderField != null)
                    {
                        this.ProcessHeaderField(message, completeHeaderField);
                    }

                    break;
                }

                if (hasParentBoundary && ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
                {
                    while (this.ReadMultipleLine(out response))
                    {
                        continue;
                    }

                    return boundaryMimeReturnCode;
                }
                ////read header field
                ////one header field can extend over one start line and multiple continuation lines
                ////a continuation line starts with at least 1 blank (' ') or tab
                if (ServiceConstants.SPACE == Convert.ToString(response[0], CultureInfo.InvariantCulture) || ServiceConstants.HORIZONTAL_TAB == Convert.ToString(response[0], CultureInfo.InvariantCulture))
                {
                    if (completeHeaderField == null)
                    {
                        while (this.ReadMultipleLine(out response))
                        {
                            continue;
                        }

                        return MimeEntityReturnCode.problem;
                    }
                    else
                    {
                        if (ServiceConstants.SPACE != Convert.ToString(completeHeaderField[completeHeaderField.Length - 1], CultureInfo.InvariantCulture))
                        {
                            completeHeaderField += ServiceConstants.SPACE + response.TrimStart(whiteSpaceChars);
                        }
                        else
                        {
                            completeHeaderField += response.TrimStart(whiteSpaceChars);
                        }
                    }
                }
                else
                {
                    if (null == completeHeaderField)
                    {
                        completeHeaderField = response;
                    }
                    else
                    {
                        this.ProcessHeaderField(message, completeHeaderField);
                        completeHeaderField = response;
                    }
                }
            }

            this.mimeEntitySB.Length = 0;
            string boundaryDelimiterLineStart = null;
            bool isBoundaryDefined = false;
            if (null != message.ContentType.Boundary)
            {
                isBoundaryDefined = true;
                boundaryDelimiterLineStart = "--" + message.ContentType.Boundary;
            }
            ////prepare return code for the case there is no boundary in the body
            boundaryMimeReturnCode = MimeEntityReturnCode.bodyComplete;

            ////read body lines
            while (this.ReadMultipleLine(out response))
            {
                ////check if there is a boundary line from this entity itself in the body
                if (isBoundaryDefined && response.TrimEnd() == boundaryDelimiterLineStart)
                {
                    ////boundary line found.
                    ////stop the processing here and start a delimited body processing
                    return this.ProcessDelimitedBody(message, boundaryDelimiterLineStart, parentBoundaryStart, parentBoundaryEnd);
                }

                ////check if there is a parent boundary in the body
                if (hasParentBoundary &&
                  ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
                {
                    ////a parent boundary is found. Decode the content of the body received so far, then end this MIME entity
                    ////note that boundaryMimeReturnCode is set here, but used in the return statement
                    break;
                }

                ////process next line
                this.mimeEntitySB.Append(response + this.CRLF);
            }

            ////a complete MIME body read
            ////convert received US ASCII characters to .NET string (Unicode)
            string transferEncodedMessage = Convert.ToString(this.mimeEntitySB, CultureInfo.InvariantCulture);
            bool isAttachmentSaved = false;
            switch (message.ContentTransferEncoding)
            {
                case TransferEncoding.SevenBit:
                    SaveMessageBody(message, transferEncodedMessage);
                    break;

                case TransferEncoding.Base64:
                    byte[] bodyBytes = System.Convert.FromBase64String(transferEncodedMessage);
                    message.ContentStream = new MemoryStream(bodyBytes, false);

                    if (message.MediaMainType == ServiceConstants.TEXT_MEDIA_MAIN_TYPE)
                    {
                        message.Body = DecodeByteArrayToString(bodyBytes, message.BodyEncoding);
                    }
                    else if (message.MediaMainType == ServiceConstants.IMAGE_MEDIA_MAIN_TYPE || message.MediaMainType == ServiceConstants.APPLICATION_MEDIA_MAIN_TYPE || message.MediaMainType == ServiceConstants.MESSAGE_MEDIA_MAIN_TYPE)
                    {
                        SaveAttachment(message);
                        isAttachmentSaved = true;
                    }

                    break;

                case TransferEncoding.QuotedPrintable:
                    SaveMessageBody(message, QuotedPrintable.Decode(transferEncodedMessage));
                    break;

                default:
                    SaveMessageBody(message, transferEncodedMessage);
                    break;
            }

            if (null != message.ContentDisposition && message.ContentDisposition.DispositionType.ToUpperInvariant() == ServiceConstants.MailAttributes.ATTACHMENT && !isAttachmentSaved)
            {
                SaveAttachment(message);
                isAttachmentSaved = true;
            }

            return boundaryMimeReturnCode;
        }
Exemple #18
0
        /// <summary>
        /// Convert one MIME header field and update message accordingly
        /// </summary>
        /// <param name="message">Parsed message object</param>
        /// <param name="headerField">header field</param>
        private void ProcessHeaderField(MailMessageParser message, string headerField)
        {
            string headerLineType;
            string headerLineContent;
            int    separatorPosition = headerField.IndexOf(ServiceConstants.COLON, StringComparison.CurrentCulture);

            if (0 < separatorPosition)
            {
                ////process header field type
                headerLineType    = headerField.Substring(0, separatorPosition).ToUpperInvariant();
                headerLineContent = headerField.Substring(separatorPosition + 1).Trim(whiteSpaceChars);
                if (string.IsNullOrEmpty(headerLineType) || string.IsNullOrEmpty(headerLineContent))
                {
                    ////mail header parts missing, exist function
                    return;
                }
                //// add header line to headers
                message.Headers.Add(headerLineType, headerLineContent);

                switch (headerLineType)
                {
                case ServiceConstants.MailAttributes.BCC:
                    AddMailAddresses(headerLineContent, message.Bcc);
                    break;

                case ServiceConstants.MailAttributes.CC:
                    AddMailAddresses(headerLineContent, message.CC);
                    break;

                case ServiceConstants.MailAttributes.CONTENT_DESCRIPTION:
                    message.ContentDescription = headerLineContent;
                    break;

                case ServiceConstants.MailAttributes.CONTENT_DISPOSITION:
                    message.SetContentDisposition(headerLineContent);
                    break;

                case ServiceConstants.MailAttributes.CONTENT_ID:
                    message.ContentId = headerLineContent;
                    break;

                case ServiceConstants.MailAttributes.CONTENT_TRANSFER_ENCODING:
                    message.ContentTransferEncoding = ConvertToTransferEncoding(headerLineContent);
                    break;

                case ServiceConstants.MailAttributes.CONTENT_TYPE:
                    message.SetContentTypeFields(headerLineContent);
                    break;

                case ServiceConstants.MailAttributes.DATE:
                    message.DeliveryDate = this.ConvertToDateTime(headerLineContent);
                    break;

                case ServiceConstants.MailAttributes.FROM:
                    MailAddress address = ConvertToMailAddress(headerLineContent);
                    if (null != address)
                    {
                        message.From = address;
                    }
                    break;

                case ServiceConstants.MailAttributes.SENDER:
                    message.Sender = ConvertToMailAddress(headerLineContent);
                    break;

                case ServiceConstants.MailAttributes.SUBJECT:
                    message.Subject = headerLineContent;
                    break;

                case ServiceConstants.MailAttributes.TO:
                    AddMailAddresses(headerLineContent, message.To);
                    break;

                case ServiceConstants.MailAttributes.IMPORTANCE:
                    message.MailImportance = headerLineContent;
                    break;

                case ServiceConstants.MailAttributes.CATEGORIES:
                    message.MailCategories = headerLineContent;
                    break;

                case ServiceConstants.MailAttributes.RECEIVED:
                    if (message.ReceivedDate.Year.Equals(1))
                    {
                        message.ReceivedDate = this.ProcessReceivedDate(headerLineContent);
                    }
                    break;

                default:
                    message.UnknowHeaderlines.Add(headerField);
                    if (IsCollectHiddenHeaderLines)
                    {
                        AllHiddenHeaderLines.Add(headerField);
                    }

                    break;
                }
            }
        }
Exemple #19
0
        /// <summary>
        /// Process a MIME entity
        /// A MIME entity consists of header and body.
        /// Separator lines in the body might mark children MIME entities
        /// </summary>
        /// <param name="message">Mail Message.</param>
        /// <param name="parentBoundaryStart">The parent boundary start value</param>
        /// <returns>Mime entity return code for parsed mail message</returns>
        private MimeEntityReturnCode ProcessMimeEntity(MailMessageParser message, string parentBoundaryStart)
        {
            bool   hasParentBoundary = parentBoundaryStart.Length > 0;
            string parentBoundaryEnd = parentBoundaryStart + ServiceConstants.HYPHEN + ServiceConstants.HYPHEN;
            MimeEntityReturnCode boundaryMimeReturnCode;

            ////some format fields are inherited from parent, only the default for
            ////ContentType needs to be set here, otherwise the boundary parameter would be
            ////inherited as well
            message.SetContentTypeFields(ServiceConstants.MAIL_CONTENT_TYPE);
            string completeHeaderField = null;     ////consists of one start line and possibly several continuation lines
            string response;

            //// read header lines until empty line is found (end of header)
            while (true)
            {
                if (!this.ReadMultipleLine(out response))
                {
                    while (this.ReadMultipleLine(out response))
                    {
                        continue;
                    }

                    return(MimeEntityReturnCode.problem);
                }

                if (1 > response.Length)
                {
                    ////empty line found => end of header
                    if (completeHeaderField != null)
                    {
                        this.ProcessHeaderField(message, completeHeaderField);
                    }

                    break;
                }

                if (hasParentBoundary && ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
                {
                    while (this.ReadMultipleLine(out response))
                    {
                        continue;
                    }

                    return(boundaryMimeReturnCode);
                }
                ////read header field
                ////one header field can extend over one start line and multiple continuation lines
                ////a continuation line starts with at least 1 blank (' ') or tab
                if (ServiceConstants.SPACE == Convert.ToString(response[0], CultureInfo.InvariantCulture) || ServiceConstants.HORIZONTAL_TAB == Convert.ToString(response[0], CultureInfo.InvariantCulture))
                {
                    if (completeHeaderField == null)
                    {
                        while (this.ReadMultipleLine(out response))
                        {
                            continue;
                        }

                        return(MimeEntityReturnCode.problem);
                    }
                    else
                    {
                        if (ServiceConstants.SPACE != Convert.ToString(completeHeaderField[completeHeaderField.Length - 1], CultureInfo.InvariantCulture))
                        {
                            completeHeaderField += ServiceConstants.SPACE + response.TrimStart(whiteSpaceChars);
                        }
                        else
                        {
                            completeHeaderField += response.TrimStart(whiteSpaceChars);
                        }
                    }
                }
                else
                {
                    if (null == completeHeaderField)
                    {
                        completeHeaderField = response;
                    }
                    else
                    {
                        this.ProcessHeaderField(message, completeHeaderField);
                        completeHeaderField = response;
                    }
                }
            }

            this.mimeEntitySB.Length = 0;
            string boundaryDelimiterLineStart = null;
            bool   isBoundaryDefined          = false;

            if (null != message.ContentType.Boundary)
            {
                isBoundaryDefined          = true;
                boundaryDelimiterLineStart = "--" + message.ContentType.Boundary;
            }
            ////prepare return code for the case there is no boundary in the body
            boundaryMimeReturnCode = MimeEntityReturnCode.bodyComplete;

            ////read body lines
            while (this.ReadMultipleLine(out response))
            {
                ////check if there is a boundary line from this entity itself in the body
                if (isBoundaryDefined && response.TrimEnd() == boundaryDelimiterLineStart)
                {
                    ////boundary line found.
                    ////stop the processing here and start a delimited body processing
                    return(this.ProcessDelimitedBody(message, boundaryDelimiterLineStart, parentBoundaryStart, parentBoundaryEnd));
                }

                ////check if there is a parent boundary in the body
                if (hasParentBoundary &&
                    ParentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode))
                {
                    ////a parent boundary is found. Decode the content of the body received so far, then end this MIME entity
                    ////note that boundaryMimeReturnCode is set here, but used in the return statement
                    break;
                }

                ////process next line
                this.mimeEntitySB.Append(response + this.CRLF);
            }

            ////a complete MIME body read
            ////convert received US ASCII characters to .NET string (Unicode)
            string transferEncodedMessage = Convert.ToString(this.mimeEntitySB, CultureInfo.InvariantCulture);
            bool   isAttachmentSaved      = false;

            switch (message.ContentTransferEncoding)
            {
            case TransferEncoding.SevenBit:
                SaveMessageBody(message, transferEncodedMessage);
                break;

            case TransferEncoding.Base64:
                byte[] bodyBytes = System.Convert.FromBase64String(transferEncodedMessage);
                message.ContentStream = new MemoryStream(bodyBytes, false);

                if (message.MediaMainType == ServiceConstants.TEXT_MEDIA_MAIN_TYPE)
                {
                    message.Body = DecodeByteArrayToString(bodyBytes, message.BodyEncoding);
                }
                else if (message.MediaMainType == ServiceConstants.IMAGE_MEDIA_MAIN_TYPE || message.MediaMainType == ServiceConstants.APPLICATION_MEDIA_MAIN_TYPE || message.MediaMainType == ServiceConstants.MESSAGE_MEDIA_MAIN_TYPE)
                {
                    SaveAttachment(message);
                    isAttachmentSaved = true;
                }

                break;

            case TransferEncoding.QuotedPrintable:
                SaveMessageBody(message, QuotedPrintable.Decode(transferEncodedMessage));
                break;

            default:
                SaveMessageBody(message, transferEncodedMessage);
                break;
            }

            if (null != message.ContentDisposition && message.ContentDisposition.DispositionType.ToUpperInvariant() == ServiceConstants.MailAttributes.ATTACHMENT && !isAttachmentSaved)
            {
                SaveAttachment(message);
                isAttachmentSaved = true;
            }

            return(boundaryMimeReturnCode);
        }
Exemple #20
0
        /// <summary>
        /// Convert one MIME header field and update message accordingly
        /// </summary>
        /// <param name="message">Parsed message object</param>
        /// <param name="headerField">header field</param>
        private void ProcessHeaderField(MailMessageParser message, string headerField)
        {
            string headerLineType;
            string headerLineContent;
            int separatorPosition = headerField.IndexOf(ServiceConstants.COLON, StringComparison.CurrentCulture);
            if (0 < separatorPosition)
            {
                ////process header field type
                headerLineType = headerField.Substring(0, separatorPosition).ToUpperInvariant();
                headerLineContent = headerField.Substring(separatorPosition + 1).Trim(whiteSpaceChars);
                if (string.IsNullOrEmpty(headerLineType) || string.IsNullOrEmpty(headerLineContent))
                {
                    ////mail header parts missing, exist function
                    return;
                }
                //// add header line to headers
                message.Headers.Add(headerLineType, headerLineContent);

                switch (headerLineType)
                {
                    case ServiceConstants.MailAttributes.BCC:
                        AddMailAddresses(headerLineContent, message.Bcc);
                        break;
                    case ServiceConstants.MailAttributes.CC:
                        AddMailAddresses(headerLineContent, message.CC);
                        break;
                    case ServiceConstants.MailAttributes.CONTENT_DESCRIPTION:
                        message.ContentDescription = headerLineContent;
                        break;
                    case ServiceConstants.MailAttributes.CONTENT_DISPOSITION:
                        message.SetContentDisposition(headerLineContent);
                        break;
                    case ServiceConstants.MailAttributes.CONTENT_ID:
                        message.ContentId = headerLineContent;
                        break;
                    case ServiceConstants.MailAttributes.CONTENT_TRANSFER_ENCODING:
                        message.ContentTransferEncoding = ConvertToTransferEncoding(headerLineContent);
                        break;
                    case ServiceConstants.MailAttributes.CONTENT_TYPE:
                        message.SetContentTypeFields(headerLineContent);
                        break;
                    case ServiceConstants.MailAttributes.DATE:
                        message.DeliveryDate = this.ConvertToDateTime(headerLineContent);
                        break;
                    case ServiceConstants.MailAttributes.FROM:
                        MailAddress address = ConvertToMailAddress(headerLineContent);
                        if (null != address)
                        {
                            message.From = address;
                        }
                        break;
                    case ServiceConstants.MailAttributes.SENDER:
                        message.Sender = ConvertToMailAddress(headerLineContent);
                        break;
                    case ServiceConstants.MailAttributes.SUBJECT:
                        message.Subject = headerLineContent;
                        break;
                    case ServiceConstants.MailAttributes.TO:
                        AddMailAddresses(headerLineContent, message.To);
                        break;
                    case ServiceConstants.MailAttributes.IMPORTANCE:
                        message.MailImportance = headerLineContent;
                        break;
                    case ServiceConstants.MailAttributes.CATEGORIES:
                        message.MailCategories = headerLineContent;
                        break;
                    case ServiceConstants.MailAttributes.RECEIVED:
                        if (message.ReceivedDate.Year.Equals(1))
                        {
                            message.ReceivedDate = this.ProcessReceivedDate(headerLineContent);
                        }
                        break;
                    default:
                        message.UnknowHeaderlines.Add(headerField);
                        if (IsCollectHiddenHeaderLines)
                        {
                            AllHiddenHeaderLines.Add(headerField);
                        }

                        break;
                }
            }
        }
        /// <summary>
        /// Gets the uploaded email file properties.
        /// </summary>
        /// <param name="fileStream">The file stream.</param>
        /// <param name="mailProperties">The mail properties.</param>
        /// <returns>Dictionary string key value pair for mail properties</returns>
        public static Dictionary <string, string> GetMailFileProperties(System.IO.Stream fileStream, Dictionary <string, string> mailProperties)
        {
            if (null != mailProperties && mailProperties.ContainsKey(ConstantStrings.MailFileExtensionKey))
            {
                if (string.Equals(mailProperties[ConstantStrings.MailFileExtensionKey], ConstantStrings.EmailFileExtension, StringComparison.OrdinalIgnoreCase))
                {
                    MailMimeReader    mime            = new MailMimeReader();
                    MailMessageParser messageParser   = mime.GetEmail(fileStream);
                    string            fromDisplayName = Convert.ToString(messageParser.From.DisplayName, CultureInfo.InvariantCulture);
                    mailProperties[ConstantStrings.MailSenderKey]          = String.Concat(Convert.ToString(messageParser.From.Address, CultureInfo.InvariantCulture), ConstantStrings.Semicolon, fromDisplayName.Replace(Convert.ToString(messageParser.From.Address, CultureInfo.InvariantCulture), string.Empty).Replace(ConstantStrings.OpeningBracket + ConstantStrings.ClosingBracket, string.Empty));
                    mailProperties[ConstantStrings.MailSearchEmailSubject] = messageParser.Subject;
                    mailProperties[ConstantStrings.MailSentDateKey]        = Convert.ToString(messageParser.DeliveryDate, CultureInfo.InvariantCulture);
                    mailProperties[ConstantStrings.MailReceivedDateKey]    = Convert.ToString(messageParser.ReceivedDate, CultureInfo.InvariantCulture);
                    mailProperties[ConstantStrings.MailOriginalName]       = messageParser.Subject;
                    StringBuilder mailReceiver   = new StringBuilder();
                    StringBuilder mailCCAddress  = new StringBuilder();
                    StringBuilder attachmentName = new StringBuilder();

                    foreach (MailAddress toItem in messageParser.To)
                    {
                        string toMailAlias = Convert.ToString(toItem.Address, CultureInfo.InvariantCulture);
                        string toMailName  = Convert.ToString(toItem.DisplayName, CultureInfo.InvariantCulture);
                        if (toMailName.Contains(toMailAlias))
                        {
                            toMailName = toMailName.Replace(toMailAlias, string.Empty).Replace(ConstantStrings.OpeningBracket + ConstantStrings.ClosingBracket, string.Empty);
                        }

                        mailReceiver.Append(toMailAlias + ConstantStrings.Semicolon + toMailName + ConstantStrings.Semicolon);
                    }

                    mailProperties[ConstantStrings.MailReceiverKey] = Convert.ToString(mailReceiver, CultureInfo.InvariantCulture);

                    foreach (MailAddress itemCC in messageParser.CC)
                    {
                        string mailCCAlias = Convert.ToString(itemCC.Address, CultureInfo.InvariantCulture);
                        string mailCCName  = Convert.ToString(itemCC.DisplayName, CultureInfo.InvariantCulture);
                        if (mailCCName.Contains(mailCCAlias))
                        {
                            mailCCName = mailCCName.Replace(mailCCAlias, string.Empty).Replace(ConstantStrings.OpeningBracket + ConstantStrings.ClosingBracket, string.Empty);
                        }

                        mailCCAddress.Append(mailCCAlias + ConstantStrings.Semicolon + mailCCName + ConstantStrings.Semicolon);
                    }

                    mailProperties[ConstantStrings.MailCCAddressKey] = Convert.ToString(mailCCAddress, CultureInfo.InvariantCulture);

                    foreach (System.Net.Mail.Attachment itemAttachment in messageParser.Attachments)
                    {
                        if (!string.IsNullOrWhiteSpace(itemAttachment.Name))
                        {
                            attachmentName.Append(itemAttachment.Name + ConstantStrings.Semicolon);
                        }
                    }

                    for (int mailEntitiesCount = 0; mailEntitiesCount < messageParser.Entities.Count; mailEntitiesCount++)
                    {
                        if (string.Equals(messageParser.Entities[mailEntitiesCount].MediaMainType, ConstantStrings.MailAttachmentMediaMainType, StringComparison.CurrentCultureIgnoreCase))
                        {
                            attachmentName.Append(messageParser.Entities[mailEntitiesCount].ContentDescription + ConstantStrings.Semicolon);
                        }
                    }

                    mailProperties[ConstantStrings.MailAttachmentKey] = Convert.ToString(attachmentName, CultureInfo.InvariantCulture);

                    // Setting email importance
                    mailProperties[ConstantStrings.MailImportanceKey] = (!string.IsNullOrWhiteSpace(messageParser.MailImportance) ? messageParser.MailImportance : ConstantStrings.MailDefaultImportance);

                    // Setting email categories
                    mailProperties[ConstantStrings.MailCategoriesKey] = (!string.IsNullOrWhiteSpace(messageParser.MailCategories) ? messageParser.MailCategories.Replace(ConstantStrings.Comma, ConstantStrings.Semicolon) : string.Empty);
                }
            }

            return(mailProperties);
        }