Class for creating,parsing,modifing rfc 2822 mime messages.
Message examples: Simple message: //--- Beginning of message From: [email protected] To: [email protected] Subject: Message subject. Content-Type: text/plain Message body text. Bla blaa blaa,blaa. //--- End of message In simple message MainEntity is whole message. Message with attachments: //--- Beginning of message From: [email protected] To: [email protected] Subject: Message subject. Content-Type: multipart/mixed; boundary="multipart_mixed" --multipart_mixed /* text entity */ Content-Type: text/plain Message body text. Bla blaa blaa,blaa. --multipart_mixed /* attachment entity */ Content-Type: application/octet-stream attachment_data --multipart_mixed-- //--- End of message MainEntity is multipart_mixed entity and text and attachment entities are child entities of MainEntity.
예제 #1
0
 /// <summary>
 /// Constructs FETCH BODY and BODYSTRUCTURE response.
 /// </summary>
 /// <param name="mime">Mime message.</param>
 /// <param name="bodystructure">Specifies if to construct BODY or BODYSTRUCTURE.</param>
 /// <returns></returns>
 public static string ConstructBodyStructure(LumiSoft.Net.Mime.Mime mime, bool bodystructure)
 {
     if (bodystructure)
     {
         return("BODYSTRUCTURE " + ConstructParts(mime.MainEntity, bodystructure));
     }
     else
     {
         return("BODY " + ConstructParts(mime.MainEntity, bodystructure));
     }
 }
        /// <summary>
        /// Gets if specified values match search criteria.
        /// </summary>
        /// <param name="no">Message sequence number.</param>
        /// <param name="uid">Message UID.</param>
        /// <param name="size">Message size in bytes.</param>
        /// <param name="internalDate">Message INTERNALDATE (dateTime when server stored message).</param>
        /// <param name="flags">Message flags.</param>
        /// <param name="header">Message header. This is only needed if this.IsHeaderNeeded is true.</param>
        /// <param name="bodyText">Message body text (must be decoded unicode text). This is only needed if this.IsBodyTextNeeded is true.</param>
        /// <returns></returns>
        public bool Matches(int no,int uid,int size,DateTime internalDate,IMAP_MessageFlags flags,string header,string bodyText)
        {
            // Parse header only if it's needed
            LumiSoft.Net.Mime.Mime m = null;
            if(m_pSearchCriteria.IsHeaderNeeded()){
                m = new LumiSoft.Net.Mime.Mime();
                m.MainEntity.Header.Parse(header);
            }

            return m_pSearchCriteria.Match(no,uid,size,internalDate,flags,m,bodyText);
        }
        /// <summary>
        /// Default constructor.
        /// </summary>
        public RelayVariablesManager(Relay_Session relaySession,string errorText,Stream messageStream)
        {
            m_pRealySession  = relaySession;
            m_ErrorText      = errorText;
            m_pMessageStream = messageStream;

            try{
                m_pMime = Mime.Parse(messageStream);
            }
            catch{
            }
        }
        /// <summary>
        /// Gets if specified values match search criteria.
        /// </summary>
        /// <param name="no">Message sequence number.</param>
        /// <param name="uid">Message UID.</param>
        /// <param name="size">Message size in bytes.</param>
        /// <param name="internalDate">Message INTERNALDATE (dateTime when server stored message).</param>
        /// <param name="flags">Message flags.</param>
        /// <param name="header">Message header. This is only needed if this.IsHeaderNeeded is true.</param>
        /// <param name="bodyText">Message body text (must be decoded unicode text). This is only needed if this.IsBodyTextNeeded is true.</param>
        /// <returns></returns>
        public bool Matches(int no, int uid, int size, DateTime internalDate, IMAP_MessageFlags flags, string header, string bodyText)
        {
            // Parse header only if it's needed
            LumiSoft.Net.Mime.Mime m = null;
            if (m_pSearchCriteria.IsHeaderNeeded())
            {
                m = new LumiSoft.Net.Mime.Mime();
                m.MainEntity.Header.Parse(header);
            }

            return(m_pSearchCriteria.Match(no, uid, size, internalDate, flags, m, bodyText));
        }
예제 #5
0
        /// <summary>
        /// Gets requested mime entity header. Returns null if specified mime entity doesn't exist.
        /// Note: Header terminator blank line is included.
        /// </summary>
        /// <param name="parser">Reference to mime parser.</param>
        /// <param name="mimeEntitySpecifier">Mime entity specifier. Nested mime entities are pointed by '.'.
        /// For example: 1,1.1,2.1, ... .</param>
        /// <returns>Returns requested mime entity data or NULL if requested entry doesn't exist.</returns>
        public static byte[] GetMimeEntityHeader(LumiSoft.Net.Mime.Mime parser, string mimeEntitySpecifier)
        {
            MimeEntity mEntry = GetMimeEntity(parser, mimeEntitySpecifier);

            if (mEntry != null)
            {
                return(GetMimeEntityHeader(mEntry));
            }
            else
            {
                return(null);
            }
        }
예제 #6
0
        /// <summary>
        /// Gets requested mime entity data. Returns null if specified mime entity doesn't exist.
        /// </summary>
        /// <param name="parser">Reference to mime parser.</param>
        /// <param name="mimeEntitySpecifier">Mime entity specifier. Nested mime entities are pointed by '.'.
        /// For example: 1,1.1,2.1, ... .</param>
        /// <returns>Returns requested mime entity data or NULL if requested entry doesn't exist.</returns>
        public static byte[] GetMimeEntityData(LumiSoft.Net.Mime.Mime parser, string mimeEntitySpecifier)
        {
            MimeEntity entity = GetMimeEntity(parser, mimeEntitySpecifier);

            if (entity != null)
            {
                return(entity.DataEncoded);
            }
            else
            {
                return(null);
            }
        }
예제 #7
0
        /// <summary>
        /// Gets specified mime entity. Returns null if specified mime entity doesn't exist.
        /// </summary>
        /// <param name="parser">Reference to mime parser.</param>
        /// <param name="mimeEntitySpecifier">Mime entity specifier. Nested mime entities are pointed by '.'.
        /// For example: 1,1.1,2.1, ... .</param>
        /// <returns></returns>
        public static MimeEntity GetMimeEntity(LumiSoft.Net.Mime.Mime parser, string mimeEntitySpecifier)
        {
            // TODO: nested rfc 822 message

            // For single part message there is only one entity with value 1.
            // Example:
            //		header
            //		entity -> 1

            // For multipart message, entity counting starts from MainEntity.ChildEntities
            // Example:
            //		header
            //		multipart/mixed
            //			entity1  -> 1
            //			entity2  -> 2
            //          ...

            // Single part
            if ((parser.MainEntity.ContentType & MediaType_enum.Multipart) == 0)
            {
                if (mimeEntitySpecifier.Length == 1 && Convert.ToInt32(mimeEntitySpecifier) == 1)
                {
                    return(parser.MainEntity);
                }
                else
                {
                    return(null);
                }
            }
            // multipart
            else
            {
                MimeEntity entity = parser.MainEntity;
                string[]   parts  = mimeEntitySpecifier.Split('.');
                foreach (string part in parts)
                {
                    int mEntryNo = Convert.ToInt32(part) - 1;                     // Enitites are zero base, mimeEntitySpecifier is 1 based.
                    if (mEntryNo > -1 && mEntryNo < entity.ChildEntities.Count)
                    {
                        entity = entity.ChildEntities[mEntryNo];
                    }
                    else
                    {
                        return(null);
                    }
                }

                return(entity);
            }
        }
예제 #8
0
        private string GetEmailAsMimeString(out int byteCount)
        {
            var mime             = new LumiSoft.Net.Mime.Mime();
            var mimeEntity       = mime.MainEntity;
            var emailAddressFrom = EmailHelper.ToEmailAddress(Email.From);

            mimeEntity.From = new AddressList();
            foreach (var emailAddress in emailAddressFrom)
            {
                mimeEntity.From.Add(new MailboxAddress(emailAddress.DisplayName, emailAddress.Address));
            }

            var emailAddressTo = EmailHelper.ToEmailAddress(Email.To);

            mimeEntity.To = new AddressList();
            foreach (var emailAddress in emailAddressTo)
            {
                mimeEntity.To.Add(new MailboxAddress(emailAddress.DisplayName, emailAddress.Address));
            }

            var emailAddressCc = EmailHelper.ToEmailAddress(Email.Cc);

            mimeEntity.Cc = new AddressList();
            foreach (var emailAddress in emailAddressCc)
            {
                mimeEntity.Cc.Add(new MailboxAddress(emailAddress.DisplayName, emailAddress.Address));
            }

            mimeEntity.Subject                 = Email.Subject;
            mimeEntity.ContentType             = MediaType_enum.Text_html;
            mimeEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
            mimeEntity.DataText                = Email.Body;

            var mimeString = mime.ToStringData();

            byteCount = mime.ToByteData().Count();

            return(mimeString);
        }
예제 #9
0
		/// <summary>
		/// Creates simple mime message with attachments.
		/// </summary>
		/// <param name="from">Header field From: value.</param>
		/// <param name="to">Header field To: value.</param>
		/// <param name="subject">Header field Subject: value.</param>
		/// <param name="bodyText">Body text of message. NOTE: Pass null is body text isn't wanted.</param>
		/// <param name="bodyHtml">Body HTML text of message. NOTE: Pass null is body HTML text isn't wanted.</param>
		/// <param name="attachmentFileNames">Attachment file names. Pass null if no attachments. NOTE: File name must contain full path to file, for example: c:\test.pdf.</param>
		/// <returns></returns>
		public static Mime CreateSimple(AddressList from,AddressList to,string subject,string bodyText,string bodyHtml,string[] attachmentFileNames)
		{
			Mime m = new Mime();

			MimeEntity mainEntity = m.MainEntity;
			mainEntity.From = from;
			mainEntity.To = to;
			mainEntity.Subject = subject;

			// There are no atachments
			if(attachmentFileNames == null || attachmentFileNames.Length == 0){
				// If bodyText and bodyHtml both specified
				if(bodyText != null && bodyHtml != null){
					mainEntity.ContentType = MediaType_enum.Multipart_alternative;

					MimeEntity textEntity = mainEntity.ChildEntities.Add();
					textEntity.ContentType = MediaType_enum.Text_plain;
					textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textEntity.DataText = bodyText;

					MimeEntity textHtmlEntity = mainEntity.ChildEntities.Add();
					textHtmlEntity.ContentType = MediaType_enum.Text_html;
					textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textHtmlEntity.DataText = bodyHtml;
				}
				// There is only body text
				else if(bodyText != null){
					MimeEntity textEntity = mainEntity;
					textEntity.ContentType = MediaType_enum.Text_plain;
					textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textEntity.DataText = bodyText;
				}
				// There is only body html text
				else if(bodyHtml != null){
					MimeEntity textHtmlEntity = mainEntity;
					textHtmlEntity.ContentType = MediaType_enum.Text_html;
					textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textHtmlEntity.DataText = bodyHtml;
				}
			}
			// There are attachments
			else{				
				mainEntity.ContentType = MediaType_enum.Multipart_mixed;

				// If bodyText and bodyHtml both specified
				if(bodyText != null && bodyHtml != null){
					MimeEntity multiPartAlternativeEntity = mainEntity.ChildEntities.Add();
					multiPartAlternativeEntity.ContentType = MediaType_enum.Multipart_alternative;

					MimeEntity textEntity = multiPartAlternativeEntity.ChildEntities.Add();
					textEntity.ContentType = MediaType_enum.Text_plain;
					textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textEntity.DataText = bodyText;

					MimeEntity textHtmlEntity = multiPartAlternativeEntity.ChildEntities.Add();
					textHtmlEntity.ContentType = MediaType_enum.Text_html;
					textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textHtmlEntity.DataText = bodyHtml;
				}
				// There is only body text
				else if(bodyText != null){
					MimeEntity textEntity = mainEntity.ChildEntities.Add();
					textEntity.ContentType = MediaType_enum.Text_plain;
					textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textEntity.DataText = bodyText;
				}
				// There is only body html text
				else if(bodyHtml != null){
					MimeEntity textHtmlEntity = mainEntity.ChildEntities.Add();
					textHtmlEntity.ContentType = MediaType_enum.Text_html;
					textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
					textHtmlEntity.DataText = bodyHtml;
				}

				foreach(string fileName in attachmentFileNames){
					MimeEntity attachmentEntity = mainEntity.ChildEntities.Add();
					attachmentEntity.ContentType = MediaType_enum.Application_octet_stream;
					attachmentEntity.ContentDisposition = ContentDisposition_enum.Attachment;
					attachmentEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
					attachmentEntity.ContentDisposition_FileName = Core.GetFileNameFromPath(fileName);
					attachmentEntity.DataFromFile(fileName);
				}
			}

			return m;
		}
예제 #10
0
		/// <summary>
		/// Parses mime message from stream.
		/// </summary>
		/// <param name="stream">Mime message stream.</param>
		/// <returns></returns>
		public static Mime Parse(Stream stream)
		{
			Mime mime = new Mime();
			mime.MainEntity.Parse(new SmartStream(stream,false),null);

			return mime;
		}
 /// <summary>
 /// Checks if specified message matches to specified criteria.
 /// </summary>
 /// <param name="matchExpression">Match expression.</param>
 /// <param name="mailFrom">SMTP MAIL FROM: command email value.</param>
 /// <param name="rcptTo">SMTP RCPT TO: command email values.</param>
 /// <param name="smtpSession">SMTP current session.</param>
 /// <param name="mime">Message to match.</param>
 /// <param name="messageSize">Message size in bytes.</param>
 /// <returns>Returns true if message matches to specified criteria.</returns>
 public bool Match(string matchExpression,string mailFrom,string[] rcptTo,SMTP_Session smtpSession,Mime mime,int messageSize)
 {
     LumiSoft.Net.StringReader r = new LumiSoft.Net.StringReader(matchExpression);
     return Match(false,r,mailFrom,rcptTo,smtpSession,mime,messageSize);
 }
        /// <summary>
        /// Checks if specified message matches to specified criteria.
        /// </summary>
        /// <param name="syntaxCheckOnly">Specifies if syntax check is only done. If true no matching is done.</param>
        /// <param name="r">Match expression reader what contains match expression.</param>
        /// <param name="mailFrom">SMTP MAIL FROM: command email value.</param>
        /// <param name="rcptTo">SMTP RCPT TO: command email values.</param>
        /// <param name="smtpSession">SMTP current session.</param>
        /// <param name="mime">Message to match.</param>
        /// <param name="messageSize">Message size in bytes.</param>
        /// <returns>Returns true if message matches to specified criteria.</returns>
        private bool Match(bool syntaxCheckOnly,LumiSoft.Net.StringReader r,string mailFrom,string[] rcptTo,SMTP_Session smtpSession,Mime mime,int messageSize)
        {
            /* Possible keywords order
                At first there can be NOT,parethesized or matcher
                    After NOT, parethesized or matcher
                    After matcher, AND or OR
                    After OR, NOT,parethesized or matcher
                    After AND, NOT,parethesized or matcher
                    After parethesized, NOT or matcher
            */

            PossibleClauseItem possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.NOT | PossibleClauseItem.Matcher;
            bool lastMatchValue = false;

            // Empty string passed
            r.ReadToFirstChar();
            if(r.Available == 0){
                throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !");
            }

            // Parse while there are expressions or get error
            while(r.Available > 0){
                r.ReadToFirstChar();

                // Syntax check must consider that there is alwas match !!!
                if(syntaxCheckOnly){
                    lastMatchValue = true;
                }

                #region () Groupped matchers

                // () Groupped matchers
                if(r.StartsWith("(")){
                    lastMatchValue = Match(syntaxCheckOnly,new LumiSoft.Net.StringReader(r.ReadParenthesized()),mailFrom,rcptTo,smtpSession,mime,messageSize);

                    possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher | PossibleClauseItem.NOT;
                }

                #endregion

                #region AND clause

                // AND clause
                else if(r.StartsWith("and",false)){
                    // See if AND allowed
                    if((possibleClauseItems & PossibleClauseItem.AND) == 0){
                        throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !");
                    }

                    // Last match value is false, no need to check next conditions
                    if(!lastMatchValue){
                        return false;
                    }

                    // Remove AND
                    r.ReadWord();
                    r.ReadToFirstChar();

                    lastMatchValue = Match(syntaxCheckOnly,r,mailFrom,rcptTo,smtpSession,mime,messageSize);

                    possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher | PossibleClauseItem.NOT;
                }

                #endregion

                #region OR clause

                // OR clause
                else if(r.StartsWith("or",false)){
                    // See if OR allowed
                    if((possibleClauseItems & PossibleClauseItem.OR) == 0){
                        throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !");
                    }

                    // Remove OR
                    r.ReadWord();
                    r.ReadToFirstChar();

                    // Last match value is false, then we need to check next condition.
                    // Otherwise OR is matched already, just eat next matcher.
                    if(lastMatchValue){
                        // Skip next clause
                        Match(syntaxCheckOnly,r,mailFrom,rcptTo,smtpSession,mime,messageSize);
                    }
                    else{
                        lastMatchValue = Match(syntaxCheckOnly,r,mailFrom,rcptTo,smtpSession,mime,messageSize);
                    }

                    possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher | PossibleClauseItem.NOT;
                }

                #endregion

                #region NOT clause

                // NOT clause
                else if(r.StartsWith("not",false)){
                    // See if NOT allowed
                    if((possibleClauseItems & PossibleClauseItem.NOT) == 0){
                        throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !");
                    }

                    // Remove NOT
                    r.ReadWord();
                    r.ReadToFirstChar();

                    // Just reverse match result value
                    lastMatchValue = !Match(syntaxCheckOnly,r,mailFrom,rcptTo,smtpSession,mime,messageSize);

                    possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher;
                }

                #endregion

                else{
                    // See if matcher allowed
                    if((possibleClauseItems & PossibleClauseItem.Matcher) == 0){
                        throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected ! \r\n\r\n Near: '" + r.OriginalString.Substring(0,r.Position) + "'");
                    }

                    // 1) matchsource
                    // 2) keyword

                    // Read match source
                    string word = r.ReadWord();
                    if(word == null){
                        throw new Exception("Invalid syntax: matcher is missing !");
                    }
                    word = word.ToLower();
                    string[] matchSourceValues = new string[]{};

                    #region smtp.mail_from

                    // SMTP command MAIL FROM: value.
                    //  smtp.mail_from
                    if(word == "smtp.mail_from"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{mailFrom};
                        }
                    }

                    #endregion

                    #region smtp.rcpt_to

                    // SMTP command RCPT TO: values.
                    //  smtp.mail_to
                    else if(word == "smtp.rcpt_to"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = rcptTo;
                        }
                    }

                    #endregion

                    #region smtp.ehlo

                    // SMTP command EHLO/HELO: value.
                    //  smtp.ehlo
                    else if(word == "smtp.ehlo"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{smtpSession.EhloName};
                        }
                    }

                    #endregion

                    #region smtp.authenticated

                    // Specifies if SMTP session is authenticated.
                    //  smtp.authenticated
                    else if(word == "smtp.authenticated"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{smtpSession.Authenticated.ToString()};
                        }
                    }

                    #endregion

                    #region smtp.user

                    // SMTP authenticated user name. Empy string "" if not authenticated.
                    //  smtp.user
                    else if(word == "smtp.user"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{smtpSession.UserName};
                        }
                    }

                    #endregion

                    #region smtp.remote_ip

                    // SMTP session connected client IP address.
                    //  smtp.remote_ip
                    else if(word == "smtp.remote_ip"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{smtpSession.RemoteEndPoint.Address.ToString()};
                        }
                    }

                    #endregion

                    #region message.size

                    // Message size in bytes.
                    //  message.size
                    else if(word == "message.size"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{messageSize.ToString()};
                        }
                    }

                    #endregion

                    #region message.header <SP> "HeaderFieldName:"

                    // Message main header header field. If multiple header fields, then all are checked.
                    //  message.header <SP> "HeaderFieldName:"
                    else if(word == "message.header"){
                        string headerFieldName = r.ReadWord();
                        if(headerFieldName == null){
                            throw new Exception("Match source MainHeaderField HeaderFieldName is missing ! Syntax:{MainHeaderField <SP> \"HeaderFieldName:\"}");
                        }

                        if(!syntaxCheckOnly){
                            if(mime.MainEntity.Header.Contains(headerFieldName)){
                                HeaderField[] fields = mime.MainEntity.Header.Get(headerFieldName);
                                matchSourceValues = new string[fields.Length];
                                for(int i=0;i<matchSourceValues.Length;i++){
                                    matchSourceValues[i] = fields[i].Value;
                                }
                            }
                        }
                    }

                    #endregion

                    #region message.all_headers <SP> "HeaderFieldName:"

                    // Any mime entity header header field. If multiple header fields, then all are checked.
                    //  message.all_headers <SP> "HeaderFieldName:"
                    else if(word == "message.all_headers"){
                        string headerFieldName = r.ReadWord();
                        if(headerFieldName == null){
                            throw new Exception("Match source MainHeaderField HeaderFieldName is missing ! Syntax:{MainHeaderField <SP> \"HeaderFieldName:\"}");
                        }

                        if(!syntaxCheckOnly){
                            List<string> values = new List<string>();
                            foreach(MimeEntity entity in mime.MimeEntities){
                                if(entity.Header.Contains(headerFieldName)){
                                    HeaderField[] fields = entity.Header.Get(headerFieldName);
                                    for(int i=0;i<fields.Length;i++){
                                        values.Add(fields[i].Value);
                                    }
                                }
                            }
                            matchSourceValues = values.ToArray();
                        }
                    }

                    #endregion

                    #region message.body_text

                    // Message body text.
                    //  message.body_text
                    else if(word == "message.body_text"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{mime.BodyText};
                        }
                    }

                    #endregion

                    #region message.body_html

                    // Message body html.
                    //  message.body_html
                    else if(word == "message.body_html"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{mime.BodyHtml};
                        }
                    }

                    #endregion

                    #region message.content_md5

                    // Message any mime entity decoded data MD5 hash.
                    //  message.content_md5
                    else if(word == "message.content_md5"){
                        if(!syntaxCheckOnly){
                            List<string> values = new List<string>();
                            foreach(MimeEntity entity in mime.MimeEntities){
                                try{
                                    byte[] data = entity.Data;
                                    if(data != null){
                                        System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                                        values.Add(System.Text.Encoding.Default.GetString(md5.ComputeHash(data)));
                                    }
                                }
                                catch{
                                    // Message data parsing failed, just skip that entity md5
                                }
                            }
                            matchSourceValues = values.ToArray();
                        }
                    }

                    #endregion

                    #region sys.date_time

                    // System current date time. Format: yyyy.MM.dd HH:mm:ss.
                    //  sys.date_time
                    else if(word == "sys.date_time"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss")};
                        }
                    }

                    #endregion

                    #region sys.date

                    // System current date. Format: yyyy.MM.dd.
                    //  sys.date
                    else if(word == "sys.date"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{DateTime.Today.ToString("dd.MM.yyyy")};
                        }
                    }

                    #endregion

                    #region sys.time

                    // System current time. Format: HH:mm:ss.
                    //  sys.time
                    else if(word == "sys.time"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{DateTime.Now.ToString("HH:mm:ss")};
                        }
                    }

                    #endregion

                    #region sys.day_of_week

                    // Day of week. Days: sunday,monday,tuesday,wednesday,thursday,friday,saturday.
                    //  sys.day_of_week
                    else if(word == "sys.day_of_week"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{DateTime.Today.DayOfWeek.ToString()};
                        }
                    }

                    #endregion

                    /*
                    // Day of month. Format: 1 - 31. If no so much days in month, then replaced with month max days.
                    // sys.day_of_month
                    else if(word == "sys.day_of_month"){
                    }
            */
                    #region sys.day_of_year

                    // Month of year. Format: 1 - 12.
                    // sys.day_of_year
                    else if(word == "sys.day_of_year"){
                        if(!syntaxCheckOnly){
                            matchSourceValues = new string[]{DateTime.Today.ToString("M")};
                        }
                    }

                    #endregion

                    #region Unknown

                    // Unknown
                    else{
                        throw new Exception("Unknown match source '" + word + "' !");
                    }

                    #endregion

                    /* If we reach so far, then we have valid match sorce and compare value.
                       Just do compare.
                    */

                    // Reset lastMatch result
                    lastMatchValue = false;

                    // Read matcher
                    word = r.ReadWord(true,new char[]{' '},true);
                    if(word == null){
                        throw new Exception("Invalid syntax: operator is missing ! \r\n\r\n Near: '" + r.OriginalString.Substring(0,r.Position) + "'");
                    }
                    word = word.ToLower();

                    #region * <SP> "astericPattern"

                    // * <SP> "astericPattern"
                    if(word == "*"){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(SCore.IsAstericMatch(val,matchSourceValue.ToLower())){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region !* <SP> "astericPattern"

                    // !* <SP> "astericPattern"
                    else if(word == "!*"){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(SCore.IsAstericMatch(val,matchSourceValue.ToLower())){
                                    lastMatchValue = false;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region == <SP> "value"

                    // == <SP> "value"
                    else if(word == "=="){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(val == matchSourceValue.ToLower()){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region != <SP> "value"

                    // != <SP> "value"
                    else if(word == "!="){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found, then already value equals
                            foreach(string matchSourceValue in matchSourceValues){
                                if(val == matchSourceValue.ToLower()){
                                    lastMatchValue = false;
                                    break;
                                }
                                lastMatchValue = true;
                            }
                        }
                    }

                    #endregion

                    #region >= <SP> "value"

                    // >= <SP> "value"
                    else if(word == ">="){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(matchSourceValue.ToLower().CompareTo(val) >= 0){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region <= <SP> "value"

                    // <= <SP> "value"
                    else if(word == "<="){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(matchSourceValue.ToLower().CompareTo(val) <= 0){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region > <SP> "value"

                    // > <SP> "value"
                    else if(word == ">"){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(matchSourceValue.ToLower().CompareTo(val) > 0){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region < <SP> "value"

                    // < <SP> "value"
                    else if(word == "<"){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(matchSourceValue.ToLower().CompareTo(val) < 0){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region regex <SP> "value"

                    // Regex <SP> "value"
                    else if(word == "regex"){
                        string val = r.ReadWord();
                        if(val == null){
                            throw new Exception("Invalid syntax: <SP> \"value\" is missing !");
                        }
                        val = val.ToLower();

                        if(!syntaxCheckOnly){
                            // We check matchSourceValues when first is found
                            foreach(string matchSourceValue in matchSourceValues){
                                if(Regex.IsMatch(val,matchSourceValue.ToLower())){
                                    lastMatchValue = true;
                                    break;
                                }
                            }
                        }
                    }

                    #endregion

                    #region Unknown

                    // Unknown
                    else{
                        throw new Exception("Unknown keword '" + word + "' !");
                    }

                    #endregion

                    possibleClauseItems = PossibleClauseItem.AND | PossibleClauseItem.OR;
                }
            }

            return lastMatchValue;
        }
예제 #13
0
        /// <summary>
        /// Gets if specified message matches with this class search-key.
        /// </summary>
        /// <param name="no">IMAP message sequence number.</param>
        /// <param name="uid">IMAP message UID.</param>
        /// <param name="size">IMAP message size in bytes.</param>
        /// <param name="internalDate">IMAP message INTERNALDATE (dateTime when server stored message).</param>
        /// <param name="flags">IMAP message flags.</param>
        /// <param name="mime">Mime message main header only.</param>
        /// <param name="bodyText">Message body text.</param>
        /// <returns></returns>
        public bool Match(long no, long uid, long size, DateTime internalDate, IMAP_MessageFlags flags, LumiSoft.Net.Mime.Mime mime, string bodyText)
        {
            #region ALL

            // ALL
            //		All messages in the mailbox; the default initial key for ANDing.
            if (m_SearchKeyName == "ALL")
            {
                return(true);
            }

            #endregion

            #region BEFORE

            // BEFORE <date>
            //	Messages whose internal date (disregarding time and timezone)
            //	is earlier than the specified date.
            else if (m_SearchKeyName == "BEFORE")
            {
                if (internalDate.Date < (DateTime)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region BODY

            // BODY <string>
            //	Messages that contain the specified string in the body of the message.
            //
            //	NOTE: Compare must be done on decoded header and decoded body of message.
            //		  In all search keys that use strings, a message matches the key if
            //		  the string is a substring of the field.  The matching is case-insensitive.
            else if (m_SearchKeyName == "BODY")
            {
                string val = bodyText;
                if (val != null && val.ToLower().IndexOf(((string)m_SearchKeyValue).ToLower()) > -1)
                {
                    return(true);
                }
            }

            #endregion

            #region HEADER

            // HEADER <field-name> <string>
            //	Messages that have a header with the specified field-name (as
            //	defined in [RFC-2822]) and that contains the specified string
            //	in the text of the header (what comes after the colon).  If the
            //	string to search is zero-length, this matches all messages that
            //	have a header line with the specified field-name regardless of
            //	the contents.
            //
            //	NOTE: Compare must be done on decoded header field value.
            //		  In all search keys that use strings, a message matches the key if
            //		  the string is a substring of the field.  The matching is case-insensitive.
            else if (m_SearchKeyName == "HEADER")
            {
                string[] headerField_value = (string[])m_SearchKeyValue;

                // If header field name won't end with :, add it
                if (!headerField_value[0].EndsWith(":"))
                {
                    headerField_value[0] = headerField_value[0] + ":";
                }

                if (mime.MainEntity.Header.Contains(headerField_value[0]))
                {
                    if (headerField_value[1].Length == 0)
                    {
                        return(true);
                    }
                    else if (mime.MainEntity.Header.GetFirst(headerField_value[0]).Value.ToLower().IndexOf(headerField_value[1].ToLower()) > -1)
                    {
                        return(true);
                    }
                }
            }

            #endregion

            #region KEYWORD

            // KEYWORD <flag>
            //	Messages with the specified keyword flag set.
            else if (m_SearchKeyName == "KEYWORD")
            {
                if ((flags & IMAP_Utils.ParseMessageFlags((string)m_SearchKeyValue)) != 0)
                {
                    return(true);
                }
            }

            #endregion

            #region LARGER

            // LARGER <n>
            //	Messages with an [RFC-2822] size larger than the specified number of octets.
            else if (m_SearchKeyName == "LARGER")
            {
                if (size > (long)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region NOT

            //	NOT <search-key> or (<search-key> <search-key> ...)(SearchGroup)
            //		Messages that do not match the specified search key.
            else if (m_SearchKeyName == "NOT")
            {
                return(!SearchGroup.Match_Key_Value(m_SearchKeyValue, no, uid, size, internalDate, flags, mime, bodyText));
            }

            #endregion

            #region ON

            // ON <date>
            //	Messages whose internal date (disregarding time and timezone)
            //	is within the specified date.
            else if (m_SearchKeyName == "ON")
            {
                if (internalDate.Date == (DateTime)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region OR

            //	OR <search-key1> <search-key2> - SearckKey can be parenthesis list of keys !
            //		Messages that match either search key.
            else if (m_SearchKeyName == "OR")
            {
                object serachKey1 = ((object[])m_SearchKeyValue)[0];
                object serachKey2 = ((object[])m_SearchKeyValue)[1];

                if (SearchGroup.Match_Key_Value(serachKey1, no, uid, size, internalDate, flags, mime, bodyText) || SearchGroup.Match_Key_Value(serachKey2, no, uid, size, internalDate, flags, mime, bodyText))
                {
                    return(true);
                }
            }

            #endregion

            #region SENTBEFORE

            // SENTBEFORE <date>
            //	Messages whose [RFC-2822] Date: header (disregarding time and
            //	timezone) is earlier than the specified date.
            else if (m_SearchKeyName == "SENTBEFORE")
            {
                if (mime.MainEntity.Date.Date < (DateTime)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region SENTON

            // SENTON <date>
            //	Messages whose [RFC-2822] Date: header (disregarding time and
            //	timezone) is within the specified date.
            else if (m_SearchKeyName == "SENTON")
            {
                if (mime.MainEntity.Date.Date == (DateTime)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region SENTSINCE

            // SENTSINCE <date>
            //	Messages whose [RFC-2822] Date: header (disregarding time and
            //	timezone) is within or later than the specified date.
            else if (m_SearchKeyName == "SENTSINCE")
            {
                if (mime.MainEntity.Date.Date >= (DateTime)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region SINCE

            // SINCE <date>
            //	Messages whose internal date (disregarding time and timezone)
            //	is within or later than the specified date.
            else if (m_SearchKeyName == "SINCE")
            {
                if (internalDate.Date >= (DateTime)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region SMALLER

            // SMALLER <n>
            //	Messages with an [RFC-2822] size smaller than the specified	number of octets.
            else if (m_SearchKeyName == "SMALLER")
            {
                if (size < (long)m_SearchKeyValue)
                {
                    return(true);
                }
            }

            #endregion

            #region TEXT

            // TEXT <string>
            //	Messages that contain the specified string in the header or	body of the message.
            //
            //  NOTE: Compare must be done on decoded header and decoded body of message.
            //		  In all search keys that use strings, a message matches the key if
            //		  the string is a substring of the field.  The matching is case-insensitive.
            else if (m_SearchKeyName == "TEXT")
            {
                // See body first
                string val = bodyText;
                if (val != null && val.ToLower().IndexOf(((string)m_SearchKeyValue).ToLower()) > -1)
                {
                    return(true);
                }

                // If we reach so far, that means body won't contain specified text and we need to check header.
                foreach (HeaderField headerField in mime.MainEntity.Header)
                {
                    if (headerField.Value.ToLower().IndexOf(((string)m_SearchKeyValue).ToLower()) > -1)
                    {
                        return(true);
                    }
                }
            }

            #endregion

            #region UID

            // UID <sequence set>
            //	Messages with unique identifiers corresponding to the specified
            //	unique identifier set.  Sequence set ranges are permitted.
            else if (m_SearchKeyName == "UID")
            {
                return(((IMAP_SequenceSet)m_SearchKeyValue).Contains(uid));
            }

            #endregion

            #region UNKEYWORD

            // UNKEYWORD <flag>
            //	Messages that do not have the specified keyword flag set.
            else if (m_SearchKeyName == "UNKEYWORD")
            {
                if ((flags & IMAP_Utils.ParseMessageFlags((string)m_SearchKeyValue)) == 0)
                {
                    return(true);
                }
            }

            #endregion

            #region SEQUENCESET

            // <sequence set>
            //		Messages with message sequence numbers corresponding to the
            //		specified message sequence number set.
            else if (m_SearchKeyName == "SEQUENCESET")
            {
                return(((IMAP_SequenceSet)m_SearchKeyValue).Contains(no));
            }

            #endregion

            return(false);
        }
예제 #14
0
        /// <summary>
        /// Parses mime message from stream.
        /// </summary>
        /// <param name="stream">Mime message stream.</param>
        /// <returns></returns>
        public static Mime Parse(Stream stream)
        {
            Mime mime = new Mime();
            mime.MainEntity.Parse(stream,null);

            return mime;
        }
예제 #15
0
        /// <summary>
        /// Parses mime message from stream.
        /// </summary>
        /// <param name="stream">Mime message stream.</param>
        /// <returns></returns>
        public static Mime Parse(Stream stream)
        {
            Mime mime = new Mime();

            using (var ss = new SmartStream(stream,false))
                mime.MainEntity.Parse(ss, null);

            return mime;
        }
        /// <summary>
        /// Creates undelivered warning for user and places it to relay folder.
        /// </summary>
        /// <param name="relayInfo">Relay info</param>
        /// <param name="error">SMTP returned error text.</param>
        /// <param name="file">Messsage file.</param>
        private void MakeUndeliveredWarning(RelayInfo relayInfo,string error,Stream file)
        {
            try{
                // If sender isn't specified, we can't send warning to sender.
                // Just skip warning sending.
                if(relayInfo.From.Length == 0){
                    return;
                }

                file.Position = relayInfo.MessageStartPos;
                RelayVariablesManager variablesMgr = new RelayVariablesManager(this,error,file);
                file.Position = relayInfo.MessageStartPos;

                ServerReturnMessage messageTemplate = m_pRelayServer.UndeliveredMessage;
                if(messageTemplate == null){
                    string bodyRtf = "" +
                    "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fnil\\fcharset0 Verdana;}{\\f1\\fnil\\fcharset186 Verdana;}{\\f2\\fswiss\\fcharset186{\\*\\fname Arial;}Arial Baltic;}{\\f3\\fnil\\fcharset0 Microsoft Sans Serif;}}\r\n" +
                    "{\\colortbl ;\\red0\\green64\\blue128;\\red255\\green0\\blue0;\\red0\\green128\\blue0;}\r\n" +
                    "\\viewkind4\\uc1\\pard\\f0\\fs20 This e-mail is generated by the Server(\\cf1 <#relay.hostname>\\cf0 )  to notify you, \\par\r\n" +
                    "\\lang1061\\f1 that \\lang1033\\f0 your message to \\cf1 <#relay.to>\\cf0  dated \\b\\fs16 <#message.header[\"Date:\"]>\\b0  \\fs20 could not be sent at the first attempt.\\par\r\n" +
                    "\\par\r\n" +
                    "Recipient \\i <#relay.to>'\\i0 s Server (\\cf1 <#relay.session_hostname>\\cf0 ) returned the following response: \\cf2 <#relay.error>\\cf0\\par\r\n" +
                    "\\par\r\n" +
                    "\\par\r\n" +
                    "Please note Server will attempt to deliver this message for \\b <#relay.undelivered_after>\\b0  hours.\\par\r\n" +
                    "\\par\r\n" +
                    "--------\\par\r\n" +
                    "\\par\r\n" +
                    "Your original message is attached to this e-mail (\\b data.eml\\b0 )\\par\r\n" +
                    "\\par\r\n" +
                    "\\fs16 The tracking number for this message is \\cf3 <#relay.session_messageid>\\cf0\\fs20\\par\r\n" +
                    "\\lang1061\\f2\\par\r\n" +
                    "\\pard\\lang1033\\f3\\fs17\\par\r\n" +
                    "}\r\n";

                    messageTemplate = new ServerReturnMessage("Delayed delivery notice: <#message.header[\"Subject:\"]>",bodyRtf);
                }

                // Make new message
                Mime m = new Mime();
                MimeEntity mainEntity = m.MainEntity;
                // Force to create From: header field
                mainEntity.From = new AddressList();
                mainEntity.From.Add(new MailboxAddress("postmaster"));
                // Force to create To: header field
                mainEntity.To = new AddressList();
                mainEntity.To.Add(new MailboxAddress(relayInfo.From));
                mainEntity.Subject = variablesMgr.Process(messageTemplate.Subject);
                mainEntity.ContentType = MediaType_enum.Multipart_mixed;

                string rtf = variablesMgr.Process(messageTemplate.BodyTextRtf);

                MimeEntity multipartAlternativeEntity = mainEntity.ChildEntities.Add();
                multipartAlternativeEntity.ContentType = MediaType_enum.Multipart_alternative;

                MimeEntity textEntity = multipartAlternativeEntity.ChildEntities.Add();
                textEntity.ContentType = MediaType_enum.Text_plain;
                textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                textEntity.DataText = SCore.RtfToText(rtf);

                MimeEntity htmlEntity = multipartAlternativeEntity.ChildEntities.Add();
                htmlEntity.ContentType = MediaType_enum.Text_html;
                htmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                htmlEntity.DataText = SCore.RtfToHtml(rtf);

                MimeEntity attachmentEntity = mainEntity.ChildEntities.Add();
                attachmentEntity.ContentType = MediaType_enum.Application_octet_stream;
                attachmentEntity.ContentDisposition = ContentDisposition_enum.Attachment;
                attachmentEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
                attachmentEntity.ContentDisposition_FileName = "data.eml";
                attachmentEntity.DataFromStream(file);

                using(MemoryStream strm = new MemoryStream()){
                    m.ToStream(strm);
                    m_pRelayServer.VirtualServer.ProcessAndStoreMessage("",new string[]{relayInfo.From},strm,null);
                }
            }
            catch(Exception x){
                Error.DumpError(x,new System.Diagnostics.StackTrace());
            }
        }
예제 #17
0
        /// <summary>
        /// Creates simple mime message with attachments.
        /// </summary>
        /// <param name="from">Header field From: value.</param>
        /// <param name="to">Header field To: value.</param>
        /// <param name="subject">Header field Subject: value.</param>
        /// <param name="bodyText">Body text of message. NOTE: Pass null is body text isn't wanted.</param>
        /// <param name="bodyHtml">Body HTML text of message. NOTE: Pass null is body HTML text isn't wanted.</param>
        /// <param name="attachmentFileNames">Attachment file names. Pass null if no attachments. NOTE: File name must contain full path to file, for example: c:\test.pdf.</param>
        /// <returns></returns>
        public static Mime CreateSimple(AddressList from, AddressList to, string subject, string bodyText, string bodyHtml, string[] attachmentFileNames)
        {
            Mime m = new Mime();

            MimeEntity mainEntity = m.MainEntity;

            mainEntity.From    = from;
            mainEntity.To      = to;
            mainEntity.Subject = subject;

            // There are no atachments
            if (attachmentFileNames == null || attachmentFileNames.Length == 0)
            {
                // If bodyText and bodyHtml both specified
                if (bodyText != null && bodyHtml != null)
                {
                    mainEntity.ContentType = MediaType_enum.Multipart_alternative;

                    MimeEntity textEntity = mainEntity.ChildEntities.Add();
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;

                    MimeEntity textHtmlEntity = mainEntity.ChildEntities.Add();
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }
                // There is only body text
                else if (bodyText != null)
                {
                    MimeEntity textEntity = mainEntity;
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;
                }
                // There is only body html text
                else if (bodyHtml != null)
                {
                    MimeEntity textHtmlEntity = mainEntity;
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }
            }
            // There are attachments
            else
            {
                mainEntity.ContentType = MediaType_enum.Multipart_mixed;

                // If bodyText and bodyHtml both specified
                if (bodyText != null && bodyHtml != null)
                {
                    MimeEntity multiPartAlternativeEntity = mainEntity.ChildEntities.Add();
                    multiPartAlternativeEntity.ContentType = MediaType_enum.Multipart_alternative;

                    MimeEntity textEntity = multiPartAlternativeEntity.ChildEntities.Add();
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;

                    MimeEntity textHtmlEntity = multiPartAlternativeEntity.ChildEntities.Add();
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }
                // There is only body text
                else if (bodyText != null)
                {
                    MimeEntity textEntity = mainEntity.ChildEntities.Add();
                    textEntity.ContentType             = MediaType_enum.Text_plain;
                    textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textEntity.DataText = bodyText;
                }
                // There is only body html text
                else if (bodyHtml != null)
                {
                    MimeEntity textHtmlEntity = mainEntity.ChildEntities.Add();
                    textHtmlEntity.ContentType             = MediaType_enum.Text_html;
                    textHtmlEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
                    textHtmlEntity.DataText = bodyHtml;
                }

                foreach (string fileName in attachmentFileNames)
                {
                    MimeEntity attachmentEntity = mainEntity.ChildEntities.Add();
                    attachmentEntity.ContentType                 = MediaType_enum.Application_octet_stream;
                    attachmentEntity.ContentDisposition          = ContentDisposition_enum.Attachment;
                    attachmentEntity.ContentTransferEncoding     = ContentTransferEncoding_enum.Base64;
                    attachmentEntity.ContentDisposition_FileName = Core.GetFileNameFromPath(fileName);
                    attachmentEntity.DataFromFile(fileName);
                }
            }

            return(m);
        }
 /// <summary>
 /// 调用lumisoft发送邮件
 /// </summary>
 /// <param name="fromEmailAddr">发送者的邮件地址</param>
 /// <param name="toEmailAddr">给谁发的邮件地址</param>
 /// <param name="subjectText">主题</param>
 /// <param name="bodyText">正文</param>
 /// <param name="filePath">附件路径</param>
 /// <returns>成功与否</returns>
 public static bool SendMailByLumisoft(string fromEmailAddr, string toEmailAddr, string subjectText, string bodyText, string filePath)
 {
     Mime m = new Mime();
     MimeEntity mainEntity = m.MainEntity;
     // Force to create From: header field
     mainEntity.From = new AddressList();
     mainEntity.From.Add(new MailboxAddress(fromEmailAddr, fromEmailAddr));
     // Force to create To: header field
     mainEntity.To = new AddressList();
     mainEntity.To.Add(new MailboxAddress(toEmailAddr, toEmailAddr));
     mainEntity.Subject = subjectText;
     //添加正文
     mainEntity.ContentType = MediaType_enum.Multipart_mixed;
     MimeEntity textEntity = mainEntity.ChildEntities.Add();
     textEntity.ContentType = MediaType_enum.Text_html;
     textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
     textEntity.DataText = bodyText;
     //发送附件
     if (!string.IsNullOrEmpty(filePath))
     {
         MimeEntity attachmentEntity = new MimeEntity();
         attachmentEntity.ContentType = MediaType_enum.Application_octet_stream;
         attachmentEntity.ContentDisposition = ContentDisposition_enum.Attachment;
         attachmentEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
         attachmentEntity.ContentDisposition_FileName = filePath;
         attachmentEntity.DataFromFile(filePath);
         mainEntity.ChildEntities.Add(attachmentEntity);
     }
     try
     {
         SMTP_Client.QuickSend(m);
         return true;
     }
     catch (Exception e)
     {
         //Console.Write(e.StackTrace);
         return false;
     }
 }